+1
-1
who-am-i/src/oauth.rs
+1
-1
who-am-i/src/oauth.rs
+31
-10
who-am-i/src/server.rs
+31
-10
who-am-i/src/server.rs
···
125
125
headers: HeaderMap,
126
126
) -> impl IntoResponse {
127
127
let err = |reason, check_frame| {
128
-
let info = json!({
129
-
"reason": reason,
130
-
"check_frame": check_frame,
131
-
});
132
-
RenderHtml("prompt-error", engine.clone(), info).into_response()
128
+
let info = json!({ "reason": reason, "check_frame": check_frame });
129
+
let html = RenderHtml("prompt-error", engine.clone(), info);
130
+
(StatusCode::BAD_REQUEST, html).into_response()
133
131
};
134
132
135
133
let Some(referrer) = headers.get(REFERER) else {
···
194
192
}): State<AppState>,
195
193
Query(params): Query<UserInfoParams>,
196
194
) -> impl IntoResponse {
195
+
let err = |status, reason| (status, Json(json!({ "reason": reason }))).into_response();
196
+
197
197
let Some(task_handle) = resolve_handles.take(¶ms.fetch_key) else {
198
-
return "oops, task does not exist or is gone".into_response();
198
+
return err(StatusCode::NOT_FOUND, "fetch key does not exist or expired");
199
199
};
200
-
if let Ok(handle) = task_handle.await.unwrap() {
201
-
Json(json!({ "handle": handle })).into_response()
202
-
} else {
203
-
"no handle?".into_response()
200
+
201
+
match task_handle.await {
202
+
Err(task_err) => {
203
+
eprintln!("task join error? {task_err:?}");
204
+
err(StatusCode::INTERNAL_SERVER_ERROR, "server errored")
205
+
}
206
+
Ok(Err(ResolveHandleError::ResolutionFailed(atrium_identity::Error::NotFound))) => {
207
+
err(StatusCode::NOT_FOUND, "handle not found")
208
+
}
209
+
Ok(Err(ResolveHandleError::ResolutionFailed(e))) => {
210
+
eprintln!("handle resolution failed: {e:?}");
211
+
err(
212
+
StatusCode::INTERNAL_SERVER_ERROR,
213
+
"handle resolution failed",
214
+
)
215
+
}
216
+
Ok(Err(ResolveHandleError::NoHandle)) => err(
217
+
StatusCode::INTERNAL_SERVER_ERROR,
218
+
"resolved identity but did not find a handle",
219
+
),
220
+
Ok(Err(ResolveHandleError::InvalidHandle(_h, reason))) => err(
221
+
StatusCode::INTERNAL_SERVER_ERROR,
222
+
&format!("handle appears invalid: {reason}"),
223
+
),
224
+
Ok(Ok(handle)) => Json(json!({ "handle": handle })).into_response(),
204
225
}
205
226
}
206
227
who-am-i/static/favicon.ico
who-am-i/static/favicon.ico
This is a binary file and will not be displayed.
+146
who-am-i/static/style.css
+146
who-am-i/static/style.css
···
1
+
body {
2
+
color: #434;
3
+
font-family: 'Iowan Old Style', 'Palatino Linotype', 'URW Palladio L', P052, serif;
4
+
margin: 0;
5
+
min-height: 100vh;
6
+
padding: 0;
7
+
}
8
+
.wrap {
9
+
border: 2px solid #221828;
10
+
border-radius: 0.5rem;
11
+
box-sizing: border-box;
12
+
overflow: hidden;
13
+
display: flex;
14
+
flex-direction: column;
15
+
height: 100vh;
16
+
}
17
+
.wrap.unframed {
18
+
border-radius: 0;
19
+
border-width: 0.4rem;
20
+
}
21
+
header {
22
+
background: #221828;
23
+
display: flex;
24
+
justify-content: space-between;
25
+
padding: 0 0.25rem;
26
+
color: #c9b;
27
+
display: flex;
28
+
gap: 0.5rem;
29
+
align-items: baseline;
30
+
}
31
+
header > * {
32
+
flex-basis: 33%;
33
+
}
34
+
header > .empty {
35
+
font-size: 0.8rem;
36
+
opacity: 0.5;
37
+
}
38
+
header > .title {
39
+
text-align: center;
40
+
}
41
+
header > a.micro {
42
+
text-decoration: none;
43
+
font-size: 0.8rem;
44
+
text-align: right;
45
+
opacity: 0.5;
46
+
}
47
+
header > a.micro:hover {
48
+
opacity: 1;
49
+
}
50
+
main {
51
+
background: #ccc;
52
+
display: flex;
53
+
flex-direction: column;
54
+
flex-grow: 1;
55
+
padding: 0.25rem 0.5rem;
56
+
}
57
+
.mini-content {
58
+
margin: 1rem auto 0;
59
+
padding: 1rem 0.5rem;
60
+
max-width: 21rem;
61
+
}
62
+
63
+
p {
64
+
margin: 1rem 0 0;
65
+
text-align: center;
66
+
}
67
+
.parent-host {
68
+
font-weight: bold;
69
+
color: #48c;
70
+
display: inline-block;
71
+
padding: 0 0.125rem;
72
+
border-radius: 0.25rem;
73
+
border: 1px solid #aaa;
74
+
font-size: 0.8rem;
75
+
}
76
+
77
+
#loader {
78
+
display: flex;
79
+
flex-grow: 1;
80
+
justify-content: center;
81
+
align-items: center;
82
+
}
83
+
.spinner {
84
+
animation: rotation 1.618s ease-in-out infinite;
85
+
border-radius: 50%;
86
+
border: 3px dashed #434;
87
+
box-sizing: border-box;
88
+
display: inline-block;
89
+
height: 1.5em;
90
+
width: 1.5em;
91
+
}
92
+
@keyframes rotation {
93
+
0% { transform: rotate(0deg) }
94
+
100% { transform: rotate(360deg) }
95
+
}
96
+
97
+
#user-info {
98
+
flex-grow: 1;
99
+
display: flex;
100
+
flex-direction: column;
101
+
justify-content: center;
102
+
}
103
+
#action {
104
+
background: #eee;
105
+
display: flex;
106
+
justify-content: space-between;
107
+
padding: 0.5rem 0.25rem 0.5rem 0.5rem;
108
+
font-size: 0.8rem;
109
+
align-items: baseline;
110
+
border-radius: 0.5rem;
111
+
border: 1px solid #bbb;
112
+
cursor: pointer;
113
+
}
114
+
#action:hover {
115
+
background: #fff;
116
+
}
117
+
#allow {
118
+
background: transparent;
119
+
border: none;
120
+
border-left: 1px solid #bbb;
121
+
padding: 0 0.5rem;
122
+
color: #375;
123
+
font: inherit;
124
+
cursor: pointer;
125
+
}
126
+
#action:hover #allow {
127
+
color: #285;
128
+
}
129
+
130
+
#or {
131
+
font-size: 0.8rem;
132
+
text-align: center;
133
+
}
134
+
#or p {
135
+
margin: 0 0 1rem;
136
+
}
137
+
138
+
input#handle {
139
+
border: none;
140
+
border-bottom: 1px dashed #aaa;
141
+
background: transparent;
142
+
}
143
+
144
+
.hidden {
145
+
display: none !important;
146
+
}
+17
who-am-i/templates/base-base.hbs
+17
who-am-i/templates/base-base.hbs
···
1
+
<!doctype html>
2
+
<html lang="en">
3
+
<head>
4
+
<meta charset="utf-8" />
5
+
<title>who-am-i</title>
6
+
<meta name="description" content="{{> description }}">
7
+
<meta property="og:type" content="website">
8
+
<meta property="og:description" content="{{> description}}">
9
+
<!-- <meta property="og:image" content=""> -->
10
+
11
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
12
+
<link href="/style.css" rel="stylesheet" type="text/css" />
13
+
</head>
14
+
<body>
15
+
{{> body}}
16
+
</body>
17
+
</html>
+28
who-am-i/templates/base-framed.hbs
+28
who-am-i/templates/base-framed.hbs
···
1
+
{{#*inline "description"}}{{/inline}}
2
+
3
+
{{#*inline "body"}}
4
+
<div class="wrap">
5
+
<header>
6
+
<div class="empty">🔒</div>
7
+
<code class="title" style="font-family: monospace;"
8
+
>who-am-i</code>
9
+
<a href="https://microcosm.blue" target="_blank" class="micro"
10
+
><span style="color: #f396a9">m</span
11
+
><span style="color: #f49c5c">i</span
12
+
><span style="color: #c7b04c">c</span
13
+
><span style="color: #92be4c">r</span
14
+
><span style="color: #4ec688">o</span
15
+
><span style="color: #51c2b6">c</span
16
+
><span style="color: #54bed7">o</span
17
+
><span style="color: #8fb1f1">s</span
18
+
><span style="color: #ce9df1">m</span
19
+
></a>
20
+
</header>
21
+
22
+
<main>
23
+
{{> main}}
24
+
</main>
25
+
</div>
26
+
{{/inline}}
27
+
28
+
{{#> base-base}}{{/base-base}}
+26
who-am-i/templates/base-full.hbs
+26
who-am-i/templates/base-full.hbs
···
1
+
{{#*inline "body"}}
2
+
<div class="wrap unframed">
3
+
<header>
4
+
<div class="empty">🔒</div>
5
+
<code class="title" style="font-family: monospace;"
6
+
>who-am-i</code>
7
+
<a href="https://microcosm.blue" target="_blank" class="micro"
8
+
><span style="color: #f396a9">m</span
9
+
><span style="color: #f49c5c">i</span
10
+
><span style="color: #c7b04c">c</span
11
+
><span style="color: #92be4c">r</span
12
+
><span style="color: #4ec688">o</span
13
+
><span style="color: #51c2b6">c</span
14
+
><span style="color: #54bed7">o</span
15
+
><span style="color: #8fb1f1">s</span
16
+
><span style="color: #ce9df1">m</span
17
+
></a>
18
+
</header>
19
+
20
+
<main>
21
+
{{> main}}
22
+
</main>
23
+
</div>
24
+
{{/inline}}
25
+
26
+
{{#> base-base}}{{/base-base}}
+9
who-am-i/templates/hello.hbs
+9
who-am-i/templates/hello.hbs
+17
who-am-i/templates/prompt-error.hbs
+17
who-am-i/templates/prompt-error.hbs
···
1
+
{{#*inline "main"}}
2
+
<div class="prompt-error">
3
+
<p class="went-wrong">Something went wrong :(</p>
4
+
<p class="reason">{{ reason }}</p>
5
+
<p id="maybe-not-in-iframe" class="hidden">
6
+
Possibly related: this prompt is meant to be shown in an iframe, but it seems like it's not.
7
+
</p>
8
+
</div>
9
+
10
+
<script>
11
+
if ({{{json check_frame}}} && window.self === window.top) {
12
+
document.getElementById('maybe-not-in-iframe').classList.remove('hidden');
13
+
}
14
+
</script>
15
+
{{/inline}}
16
+
17
+
{{#> base-framed}}{{/base-framed}}