add: app sdk client auth flow example
This commit is contained in:
parent
0138bf4cd4
commit
9ccbc69405
9 changed files with 95 additions and 27 deletions
|
@ -112,7 +112,7 @@ macro_rules! get_user_from_token {
|
||||||
Ok((grant, ua)) => {
|
Ok((grant, ua)) => {
|
||||||
if grant.scopes.contains(&$grant_scope) {
|
if grant.scopes.contains(&$grant_scope) {
|
||||||
if ua.permissions.check_banned() {
|
if ua.permissions.check_banned() {
|
||||||
Some(tetratto_core::model::auth::User::banned())
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(ua)
|
Some(ua)
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,7 +180,8 @@
|
||||||
(li (b (text "Redirect URL: ")) (text "{{ app.redirect }}"))
|
(li (b (text "Redirect URL: ")) (text "{{ app.redirect }}"))
|
||||||
(li (b (text "Quota status: ")) (text "{{ app.quota_status }}"))
|
(li (b (text "Quota status: ")) (text "{{ app.quota_status }}"))
|
||||||
(li (b (text "User grants: ")) (text "{{ app.grants }}"))
|
(li (b (text "User grants: ")) (text "{{ app.grants }}"))
|
||||||
(li (b (text "Grant URL: ")) (text "{{ config.host }}/auth/connections_link/app/{{ app.id }}")))
|
(li (b (text "Grant URL: ")) (text "{{ config.host }}/auth/connections_link/app/{{ app.id }}"))
|
||||||
|
(li (b (text "App ID (for SDK): ")) (text "{{ app.id }}")))
|
||||||
|
|
||||||
(a
|
(a
|
||||||
("class" "button")
|
("class" "button")
|
||||||
|
|
|
@ -41,8 +41,7 @@
|
||||||
("id" "homepage")
|
("id" "homepage")
|
||||||
("placeholder" "homepage")
|
("placeholder" "homepage")
|
||||||
("required" "")
|
("required" "")
|
||||||
("minlength" "2")
|
("minlength" "2")))
|
||||||
("maxlength" "32")))
|
|
||||||
(div
|
(div
|
||||||
("class" "flex flex-col gap-1")
|
("class" "flex flex-col gap-1")
|
||||||
(label
|
(label
|
||||||
|
@ -53,8 +52,7 @@
|
||||||
("name" "redirect")
|
("name" "redirect")
|
||||||
("id" "redirect")
|
("id" "redirect")
|
||||||
("placeholder" "redirect URL")
|
("placeholder" "redirect URL")
|
||||||
("minlength" "2")
|
("minlength" "2")))
|
||||||
("maxlength" "32")))
|
|
||||||
(button
|
(button
|
||||||
(text "{{ text \"communities:action.create\" }}"))))
|
(text "{{ text \"communities:action.create\" }}"))))
|
||||||
|
|
||||||
|
|
|
@ -176,11 +176,7 @@ export default function tetratto({
|
||||||
window.localStorage.setItem("atto:grant.user_id", uid);
|
window.localStorage.setItem("atto:grant.user_id", uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refresh_token(verifier) {
|
async function refresh_token() {
|
||||||
if (!user_token) {
|
|
||||||
throw Error("No user token provided.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return api_promise(
|
return api_promise(
|
||||||
json_parse(
|
json_parse(
|
||||||
await (
|
await (
|
||||||
|
@ -190,10 +186,10 @@ export default function tetratto({
|
||||||
method,
|
method,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Cookie": `__Secure-atto-token=${user_token}`,
|
"X-Cookie": `Atto-Grant=${user_token}`,
|
||||||
},
|
},
|
||||||
body: json_stringify({
|
body: json_stringify({
|
||||||
verifier,
|
verifier: user_verifier,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -203,10 +199,10 @@ export default function tetratto({
|
||||||
}
|
}
|
||||||
|
|
||||||
async function request({
|
async function request({
|
||||||
api_path,
|
route,
|
||||||
method = "POST",
|
method = "POST",
|
||||||
content_type = "application/json",
|
content_type = "application/json",
|
||||||
body = "{}",
|
body = {},
|
||||||
}) {
|
}) {
|
||||||
if (!user_token) {
|
if (!user_token) {
|
||||||
throw Error("No user token provided.");
|
throw Error("No user token provided.");
|
||||||
|
@ -215,16 +211,19 @@ export default function tetratto({
|
||||||
return api_promise(
|
return api_promise(
|
||||||
json_parse(
|
json_parse(
|
||||||
await (
|
await (
|
||||||
await fetch(`${host}/api/v1/${api_path}`, {
|
await fetch(`${host}/api/v1/${route}`, {
|
||||||
method,
|
method,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": content_type,
|
"Content-Type":
|
||||||
"X-Cookie": `__Secure-atto-token=${user_token}`,
|
method === "GET" ? null : content_type,
|
||||||
|
"X-Cookie": `Atto-Grant=${user_token}`,
|
||||||
},
|
},
|
||||||
body:
|
body:
|
||||||
content_type === "application/json"
|
method === "GET"
|
||||||
? json_stringify(body)
|
? null
|
||||||
: body,
|
: content_type === "application/json"
|
||||||
|
? json_stringify(body)
|
||||||
|
: body,
|
||||||
})
|
})
|
||||||
).text(),
|
).text(),
|
||||||
),
|
),
|
||||||
|
@ -233,6 +232,11 @@ export default function tetratto({
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
return {
|
return {
|
||||||
|
user_id,
|
||||||
|
user_token,
|
||||||
|
user_verifier,
|
||||||
|
app_id,
|
||||||
|
api_key,
|
||||||
// app data
|
// app data
|
||||||
app,
|
app,
|
||||||
query,
|
query,
|
||||||
|
|
|
@ -196,8 +196,8 @@ impl DataManager {
|
||||||
|
|
||||||
let res = query_row!(
|
let res = query_row!(
|
||||||
&conn,
|
&conn,
|
||||||
"SELECT * FROM users WHERE (SELECT jsonb_array_elements(grants::jsonb) @> ('{\"token\":\"' || $1 || '\"}')::jsonb)",
|
"SELECT * FROM users WHERE grants LIKE $1",
|
||||||
&[&token],
|
&[&format!("%\"token\":\"{token}\"%")],
|
||||||
|x| Ok(Self::get_user_from_row(x))
|
|x| Ok(Self::get_user_from_row(x))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
1
example/.gitignore
vendored
1
example/.gitignore
vendored
|
@ -4,6 +4,7 @@ html/*
|
||||||
public/*
|
public/*
|
||||||
!public/footer.html
|
!public/footer.html
|
||||||
!public/robots.txt
|
!public/robots.txt
|
||||||
|
!public/examples
|
||||||
media/*
|
media/*
|
||||||
icons/*
|
icons/*
|
||||||
langs/*
|
langs/*
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
// APP_API_KEY=... deno run --allow-net --allow-import --allow-env -r app_sdk_test.js
|
// APP_API_KEY=... deno run --allow-net --allow-import --allow-env -r app_sdk_test.js
|
||||||
const deno = Deno;
|
const deno = Deno;
|
||||||
const sdk = (await import("http://localhost:4118/js/app_sdk.js")).default(
|
const sdk = (await import("http://localhost:4118/js/app_sdk.js")).default({
|
||||||
"http://localhost:4118",
|
host: "http://localhost:4118",
|
||||||
deno.env.get("APP_API_KEY"),
|
api_key: deno.env.get("APP_API_KEY"),
|
||||||
);
|
});
|
||||||
|
|
||||||
// check data used
|
// check data used
|
||||||
console.log("data used:", (await sdk.app()).data_used);
|
console.log("data used:", (await sdk.app()).data_used);
|
||||||
|
|
39
example/public/examples/auth_flow_example/index.html
Normal file
39
example/public/examples/auth_flow_example/index.html
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Auth flow example</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<button
|
||||||
|
onclick="window.location.href = globalThis.sdk.GRANT_URL"
|
||||||
|
id="login_button"
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<p id="greeting"></p>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
const app_id = BigInt(prompt("App ID:"));
|
||||||
|
globalThis.sdk = (await import("/js/app_sdk.js")).from_localstorage(
|
||||||
|
{
|
||||||
|
host: window.location.origin,
|
||||||
|
app_id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sdk.user_id) {
|
||||||
|
const user = await sdk.request({
|
||||||
|
route: "auth/user/me",
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("login_button").remove();
|
||||||
|
document.getElementById("greeting").innerText =
|
||||||
|
`Hello, ${user.username}!`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
25
example/public/examples/auth_flow_example/redirect.html
Normal file
25
example/public/examples/auth_flow_example/redirect.html
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Auth flow example redirect</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Waiting...</p>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
const app_id = BigInt(prompt("App ID:"));
|
||||||
|
globalThis.sdk = (await import("/js/app_sdk.js")).from_localstorage(
|
||||||
|
{
|
||||||
|
host: window.location.origin,
|
||||||
|
app_id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
sdk.localstorage_accept_connection();
|
||||||
|
window.location.href =
|
||||||
|
"/public/examples/auth_flow_example/index.html";
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue