Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6f251f5

Browse files
committed
feat: support RDP-specific deep links
1 parent83b1554 commit6f251f5

File tree

3 files changed

+89
-10
lines changed

3 files changed

+89
-10
lines changed

‎Coder-Desktop/Coder-Desktop/URLHandler.swift

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,65 @@ class URLHandler {
2020
guard deployment.host()== url.hostelse{
2121
throw.invalidAuthority(url.host()??"<none>")
2222
}
23+
letroute:CoderRoute
2324
do{
24-
switchtry router.match(url: url){
25-
caselet.open(workspace, agent, type):
26-
switch type{
27-
caselet.rdp(creds):
28-
handleRDP(workspace: workspace, agent: agent, creds: creds)
29-
}
30-
}
25+
route=try router.match(url: url)
3126
}catch{
3227
throw.matchError(url: url)
3328
}
3429

35-
func handleRDP(workspace _:String, agent _:String, creds _:RDPCredentials){
36-
// TODO: Handle RDP
30+
switch route{
31+
caselet.open(workspace, agent, type):
32+
switch type{
33+
caselet.rdp(creds):
34+
tryhandleRDP(workspace: workspace, agent: agent, creds: creds)
35+
}
36+
}
37+
}
38+
39+
privatefunc handleRDP(workspace:String, agent:String, creds:RDPCredentials)throws(URLError){
40+
guard vpn.state==.connectedelse{
41+
throw.openError(.coderConnectOffline)
42+
}
43+
44+
guardlet workspace= vpn.menuState.findWorkspace(name: workspace)else{
45+
throw.openError(.invalidWorkspace(workspace: workspace))
46+
}
47+
48+
guardlet agent= vpn.menuState.findAgent(workspaceID: workspace.id, name: agent)else{
49+
throw.openError(.invalidAgent(workspace: workspace.name, agent: agent))
50+
}
51+
52+
varrdpString="rdp:full address=s:\(agent.primaryHost):3389"
53+
iflet username= creds.username{
54+
rdpString+="&username=s:\(username)"
55+
}
56+
guardlet url=URL(string: rdpString)else{
57+
throw.openError(.couldNotCreateRDPURL(rdpString))
58+
}
59+
60+
letalert=NSAlert()
61+
alert.messageText="Opening RDP"
62+
alert.informativeText="Connecting to\(agent.primaryHost)."
63+
iflet username= creds.username{
64+
alert.informativeText+="\nUsername:\(username)"
65+
}
66+
if creds.password!=nil{
67+
alert.informativeText+="\nThe password will be copied to your clipboard."
68+
}
69+
70+
alert.alertStyle=.informational
71+
alert.addButton(withTitle:"Open")
72+
alert.addButton(withTitle:"Cancel")
73+
letresponse= alert.runModal()
74+
if response==.alertFirstButtonReturn{
75+
iflet password= creds.password{
76+
NSPasteboard.general.clearContents()
77+
NSPasteboard.general.setString(password, forType:.string)
78+
}
79+
NSWorkspace.shared.open(url)
80+
}else{
81+
// User cancelled
3782
}
3883
}
3984
}

‎Coder-Desktop/Coder-Desktop/VPN/MenuState.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ struct VPNMenuState {
5858
// or have any invalid UUIDs.
5959
varinvalidAgents:[Vpn_Agent]=[]
6060

61+
publicfunc findAgent(workspaceID:UUID, name:String)->Agent?{
62+
agents.first(where:{ $0.value.wsID== workspaceID && $0.value.name== name})?.value
63+
}
64+
65+
publicfunc findWorkspace(name:String)->Workspace?{
66+
workspaces
67+
.first(where:{ $0.value.name== name})?.value
68+
}
69+
6170
mutatingfunc upsertAgent(_ agent:Vpn_Agent){
6271
guard
6372
let id=UUID(uuidData: agent.id),

‎Coder-Desktop/VPNLib/CoderRouter.swift

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,40 @@ public enum RouterError: Error {
3232
case invalidAuthority(String)
3333
case matchError(url:URL)
3434
case noSession
35+
case openError(OpenError)
3536

36-
publicvardescription:String{
37+
vardescription:String{
3738
switchself{
3839
caselet.invalidAuthority(authority):
3940
"Authority '\(authority)' does not match the host of the current Coder deployment."
4041
caselet.matchError(url):
4142
"Failed to handle\(url.absoluteString) because the format is unsupported."
4243
case.noSession:
4344
"Not logged in."
45+
caselet.openError(error):
46+
error.description
47+
}
48+
}
49+
50+
varlocalizedDescription:String{ description}
51+
}
52+
53+
publicenumOpenError:Error{
54+
case invalidWorkspace(workspace:String)
55+
case invalidAgent(workspace:String, agent:String)
56+
case coderConnectOffline
57+
case couldNotCreateRDPURL(String)
58+
59+
publicvardescription:String{
60+
switchself{
61+
caselet.invalidWorkspace(ws):
62+
"Could not find workspace '\(ws)'. Does it exist?"
63+
case.coderConnectOffline:
64+
"Coder Connect must be running."
65+
caselet.invalidAgent(workspace: workspace, agent: agent):
66+
"Could not find agent '\(agent)' in workspace '\(workspace)'. Is the workspace running?"
67+
caselet.couldNotCreateRDPURL(rdpString):
68+
"Could not create construct RDP url from '\(rdpString)'."
4469
}
4570
}
4671

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp