Skip to content

Commit 9229838

Browse files
authored
Merge pull request #336 from tayloraswift/symbolgraph-download-links
compute and conditionally show symbol graph download links
2 parents 9032b85 + aae2935 commit 9229838

9 files changed

+132
-71
lines changed

Sources/UnidocUI/Endpoints/Tags/Unidoc.BuildFormTool.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ extension Unidoc.BuildFormTool
5050
return .init(form: form, area: area, disabled: .alreadySubmitted)
5151
}
5252

53-
guard case _? = view.global
53+
guard view.authenticated
5454
else
5555
{
5656
return .init(form: form, area: area, disabled: .unauthenticated)
@@ -77,7 +77,7 @@ extension Unidoc.BuildFormTool
7777
return .init(form: form, area: area, disabled: .alreadyStarted)
7878
}
7979

80-
guard case _? = view.global
80+
guard view.authenticated
8181
else
8282
{
8383
return .init(form: form, area: area, disabled: .unauthenticated)

Sources/UnidocUI/Endpoints/Tags/Unidoc.CompleteBuildsTable.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ extension Unidoc.CompleteBuildsTable:HTML.OutputStreamable
107107
}
108108

109109
// You need to be logged in to view build logs.
110-
guard case _? = self.view.global
110+
guard self.view.authenticated
111111
else
112112
{
113113
return

Sources/UnidocUI/Endpoints/Tags/Unidoc.DisabledButton.swift

+3-8
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,9 @@ extension Unidoc.DisabledButton:HTML.OutputStreamable
2323
{
2424
form[.button]
2525
{
26-
if case nil = self.view.global
27-
{
28-
$0.title = "You are not logged in!"
29-
}
30-
else
31-
{
32-
$0.title = "You are not an editor of this package!"
33-
}
26+
$0.title = self.view.authenticated
27+
? "You are not an editor of this package!"
28+
: "You are not logged in!"
3429

3530
$0.class = self.area ? "area" : "text"
3631
$0.disabled = true

Sources/UnidocUI/Endpoints/Tags/Unidoc.RefsPage.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ extension Unidoc.RefsPage
202202
$0.class = "area"
203203
$0.type = "submit"
204204

205-
if case nil = self.view.global
205+
if !self.view.authenticated
206206
{
207207
$0.disabled = true
208208
$0.title = "You are not logged in!"
@@ -232,7 +232,7 @@ extension Unidoc.RefsPage
232232

233233
section[.h2] = Heading.settings
234234

235-
if case nil = self.view.global
235+
if !self.view.authenticated
236236
{
237237
section[.p] { $0.class = "note" } = "You are not logged in!"
238238
}
@@ -281,7 +281,7 @@ extension Unidoc.RefsPage
281281
{
282282
$0 += self.package.hidden ? "yes" : "no"
283283

284-
if case .administratrix? = self.view.global
284+
if self.view.admin
285285
{
286286
// If package is hidden, we can unhide it without confirmation.
287287
let confirm:Bool = !self.package.hidden
@@ -374,7 +374,7 @@ extension Unidoc.RefsPage
374374
}
375375

376376

377-
if case nil = self.view.global
377+
if !self.view.authenticated
378378
{
379379
section[.form]
380380
{
@@ -469,7 +469,7 @@ extension Unidoc.RefsPage
469469
$0.class = "area"
470470
$0.type = "submit"
471471

472-
if case nil = self.view.global
472+
if !self.view.authenticated
473473
{
474474
$0.disabled = true
475475
$0.title = "You are not logged in!"
@@ -520,7 +520,7 @@ extension Unidoc.RefsPage
520520
}
521521
}
522522

523-
guard case .administratrix? = self.view.global
523+
guard self.view.admin
524524
else
525525
{
526526
return

Sources/UnidocUI/Endpoints/Tags/Unidoc.RefsTable.Row.Graph.swift

+65-45
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ extension Unidoc.RefsTable.Row.Graph:HTML.OutputStreamable
9191
} = "(\(size >> 10) kb)"
9292
}
9393

94-
guard self.view.editor
94+
// You need to be logged-in to see the menu.
95+
guard self.view.authenticated
9596
else
9697
{
9798
return
@@ -102,70 +103,89 @@ extension Unidoc.RefsTable.Row.Graph:HTML.OutputStreamable
102103
$0[.button] = "•••"
103104
$0[.ul]
104105
{
105-
$0[.li]
106+
if self.view.editor
106107
{
107-
$0[.form]
108+
$0[.li]
108109
{
109-
$0.enctype = "\(MediaType.application(.x_www_form_urlencoded))"
110-
$0.action = "\(Unidoc.Post[.build, confirm: true])"
111-
$0.method = "post"
112-
} = Unidoc.BuildFormTool.init(
113-
form: .init(symbol: self.symbol, action: .submit),
114-
area: .init(text: nil, type: .inline))
110+
$0[.form]
111+
{
112+
$0.enctype = "\(MediaType.application(.x_www_form_urlencoded))"
113+
$0.action = "\(Unidoc.Post[.build, confirm: true])"
114+
$0.method = "post"
115+
} = Unidoc.BuildFormTool.init(
116+
form: .init(symbol: self.symbol, action: .submit),
117+
area: .init(text: nil, type: .inline))
118+
}
115119
}
116120

117121
guard
118-
case .administratrix? = self.view.global,
119122
case .some(let graph) = self.state
120123
else
121124
{
122125
return
123126
}
124127

125-
for (label, route):(String, Unidoc.LinkerRoute) in [
126-
("Uplink", .uplink),
127-
("Unlink", .unlink),
128-
("Delete", .delete),
129-
]
128+
let object:Unidoc.GraphPath = .init(edition: graph.id, type: .bson_zz)
129+
130+
// For now, allow all logged-in users to obtain the download link.
131+
// This only makes sense in production.
132+
if self.view.enforced
130133
{
131134
$0[.li]
132135
{
133-
var action:URI = Unidoc.ServerRoot.link / "\(route)"
134-
135-
switch route
136-
{
137-
// Uplink does not require confirmation.
138-
case .uplink: break
139-
case .unlink: action["y"] = "false"
140-
case .delete: action["y"] = "false"
141-
}
142-
143-
$0[.form]
136+
$0[.a]
144137
{
145-
$0.enctype = "\(MediaType.application(.x_www_form_urlencoded))"
146-
$0.action = "\(action)"
147-
$0.method = "post"
148-
} = Unidoc.LinkerTool.init(
149-
form: .init(edition: graph.id,
150-
back: "\(Unidoc.RefsEndpoint[self.symbol.package])"),
151-
name: label)
138+
$0.target = "_blank"
139+
$0.rel = .external
140+
$0.href = "https://static.swiftinit.org\(object)"
141+
} = "Download"
152142
}
153143
}
154144

155-
$0[.li]
145+
if self.view.admin
156146
{
157-
$0[.a]
147+
$0[.li]
158148
{
159-
let path:Unidoc.GraphPath = .init(edition: graph.id,
160-
type: .bson_zz)
161-
162-
$0.target = "_blank"
163-
$0.rel = .external
164-
$0.href = """
165-
https://s3.console.aws.amazon.com/s3/object/symbolgraphs\
166-
?region=us-east-1&bucketType=general&prefix=\(path.prefix)
167-
"""
168-
} = "Inspect object"
149+
$0[.a]
150+
{
151+
$0.target = "_blank"
152+
$0.rel = .external
153+
$0.href = """
154+
https://s3.console.aws.amazon.com/s3/object/symbolgraphs\
155+
?region=us-east-1&bucketType=general&prefix=\(object.prefix)
156+
"""
157+
} = "Inspect object"
158+
}
159+
160+
for (label, route):(String, Unidoc.LinkerRoute) in [
161+
("Uplink", .uplink),
162+
("Unlink", .unlink),
163+
("Delete", .delete),
164+
]
165+
{
166+
$0[.li]
167+
{
168+
var action:URI = Unidoc.ServerRoot.link / "\(route)"
169+
170+
switch route
171+
{
172+
// Uplink does not require confirmation.
173+
case .uplink: break
174+
case .unlink: action["y"] = "false"
175+
case .delete: action["y"] = "false"
176+
}
177+
178+
$0[.form]
179+
{
180+
$0.enctype = "\(MediaType.application(.x_www_form_urlencoded))"
181+
$0.action = "\(action)"
182+
$0.method = "post"
183+
} = Unidoc.LinkerTool.init(
184+
form: .init(edition: graph.id,
185+
back: "\(Unidoc.RefsEndpoint[self.symbol.package])"),
186+
name: label)
187+
}
188+
}
169189
}
170190
}
171191
}

Sources/UnidocUI/Endpoints/Tags/Unidoc.RulesPage.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ extension Unidoc.RulesPage:Unidoc.ApplicationPage
126126
$0.class = "area"
127127
$0.type = "submit"
128128

129-
if case nil = self.view.global
129+
if !self.view.authenticated
130130
{
131131
$0.disabled = true
132132
$0.title = "You are not logged in!"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
extension Unidoc.Permissions
2+
{
3+
enum Global
4+
{
5+
/// Authenticated.
6+
case authenticated(Unidoc.User.Level)
7+
/// Not authenticated, running in local development mode.
8+
case developer
9+
/// Not authenticated, running in production mode.
10+
case guest
11+
}
12+
}

Sources/UnidocUI/Unidoc.Permissions.swift

+39-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ extension Unidoc
22
{
33
struct Permissions
44
{
5-
let global:Unidoc.User.Level?
5+
private
6+
let global:Global
67
let rights:Unidoc.PackageRights
78

8-
init(global:Unidoc.User.Level?, rights:Unidoc.PackageRights)
9+
init(global:Global, rights:Unidoc.PackageRights)
910
{
1011
self.global = global
1112
self.rights = rights
@@ -14,18 +15,52 @@ extension Unidoc
1415
}
1516
extension Unidoc.Permissions
1617
{
18+
/// Indicates whether the user is logged in. In local development mode, this returns true.
19+
var authenticated:Bool
20+
{
21+
switch self.global
22+
{
23+
case .authenticated: true
24+
case .developer: true
25+
case .guest: false
26+
}
27+
}
28+
29+
/// Indicates if the server is enforcing permissions. In local development mode, this
30+
/// returns false.
31+
var enforced:Bool
32+
{
33+
switch self.global
34+
{
35+
case .authenticated: true
36+
case .developer: false
37+
case .guest: true
38+
}
39+
}
40+
1741
/// Indicates whether information restricted to editors should be displayed. This returns
1842
/// true for package owners and for administratrices regardless of their relationship to the
1943
/// package.
2044
var editor:Bool
2145
{
22-
self.global == .administratrix || self.rights >= .editor
46+
self.admin || self.rights >= .editor
2347
}
2448

2549
/// Indicates whether information restricted to owners should be displayed. This returns
2650
/// true for administratrices regardless of their relationship to the package.
2751
var owner:Bool
2852
{
29-
self.global == .administratrix || self.rights >= .owner
53+
self.admin || self.rights >= .owner
54+
}
55+
56+
var admin:Bool
57+
{
58+
switch self.global
59+
{
60+
case .authenticated(.administratrix): true
61+
case .authenticated(_): false
62+
case .developer: true
63+
case .guest: false
64+
}
3065
}
3166
}

Sources/UnidocUI/Unidoc.Security (ext).swift

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,18 @@ extension Unidoc.Security
44
{
55
if case .ignored = self
66
{
7-
/// In development mode, everyone is an administratrix!
8-
return .init(global: user.map { _ in .administratrix }, rights: .owner)
7+
return .init(global: .developer, rights: .owner)
98
}
109

1110
if let user:Unidoc.User
1211
{
13-
return .init(global: user.level, rights: .of(account: user.id,
12+
return .init(global: .authenticated(user.level), rights: .of(account: user.id,
1413
access: user.access,
1514
rulers: package.rulers))
1615
}
1716
else
1817
{
19-
return .init(global: nil, rights: .reader)
18+
return .init(global: .guest, rights: .reader)
2019
}
2120
}
2221
}

0 commit comments

Comments
 (0)