feat(frontend): added returnTo to login and signin page
This commit is contained in:
parent
033d399fcb
commit
b1d4f68453
14 changed files with 352 additions and 1460 deletions
|
|
@ -1,86 +1,163 @@
|
|||
import { addRoute, setTitle, type RouteHandlerParams, type RouteHandlerReturn } from "@app/routing";
|
||||
import {
|
||||
addRoute,
|
||||
navigateTo,
|
||||
setTitle,
|
||||
type RouteHandlerParams,
|
||||
type RouteHandlerReturn,
|
||||
} from "@app/routing";
|
||||
import { showError, showInfo, showSuccess } from "@app/toast";
|
||||
import authHtml from './login.html?raw';
|
||||
import client from '@app/api'
|
||||
import authHtml from "./login.html?raw";
|
||||
import client from "@app/api";
|
||||
import { updateUser } from "@app/auth";
|
||||
import Cookie from 'js-cookie';
|
||||
import Cookie from "js-cookie";
|
||||
import loggedInHtml from "./alreadyLoggedin.html?raw";
|
||||
import cuteCat from "./cuteCat.png";
|
||||
import { isNullish } from "@app/utils";
|
||||
|
||||
|
||||
type Providers = {
|
||||
name: string,
|
||||
display_name: string,
|
||||
icon_url?: string,
|
||||
color?: { default: string, hover: string },
|
||||
};
|
||||
|
||||
function handleLogin(_url: string, _args: RouteHandlerParams): RouteHandlerReturn {
|
||||
setTitle('Login')
|
||||
async function handleLogin(
|
||||
_url: string,
|
||||
_args: RouteHandlerParams,
|
||||
): Promise<RouteHandlerReturn> {
|
||||
setTitle("Login");
|
||||
let user = await updateUser();
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const returnTo = urlParams.get("returnTo");
|
||||
if (user !== null) {
|
||||
return {
|
||||
html: loggedInHtml,
|
||||
postInsert: async (app) => {
|
||||
const bLogoutButton =
|
||||
app?.querySelector<HTMLButtonElement>("button#bLogout");
|
||||
if (isNullish(bLogoutButton))
|
||||
return showError("Error while rending page");
|
||||
const iCuteCat =
|
||||
app?.querySelector<HTMLImageElement>("img#cuteCatImage");
|
||||
if (isNullish(iCuteCat))
|
||||
return showError("Error while rending page");
|
||||
const bReturnTo =
|
||||
app?.querySelector<HTMLButtonElement>("button#bReturnTo");
|
||||
if (isNullish(bReturnTo))
|
||||
return showError("Error while rending page");
|
||||
iCuteCat.src = cuteCat;
|
||||
iCuteCat.hidden = false;
|
||||
bLogoutButton.addEventListener("click", async () => {
|
||||
await client.logout();
|
||||
navigateTo("/login");
|
||||
});
|
||||
if (returnTo !== null) {
|
||||
bReturnTo.parentElement!.hidden = false;
|
||||
bReturnTo.addEventListener("click", async () => {
|
||||
if (returnTo !== null) navigateTo(returnTo);
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
html: authHtml, postInsert: async (app) => {
|
||||
const fLogin = document.querySelector<HTMLFormElement>('form#login-form');
|
||||
html: authHtml,
|
||||
postInsert: async (app) => {
|
||||
const aHref =
|
||||
app?.querySelector<HTMLAnchorElement>('a[href="/signin"]');
|
||||
if (!isNullish(aHref) && returnTo !== null) {
|
||||
aHref.href = `/signin?returnTo=${encodeURI(returnTo)}`;
|
||||
}
|
||||
const fLogin =
|
||||
document.querySelector<HTMLFormElement>("form#login-form");
|
||||
if (fLogin === null)
|
||||
return showError('Error while rendering the page: no form found');
|
||||
fLogin.addEventListener('submit', async function(e: SubmitEvent) {
|
||||
return showError(
|
||||
"Error while rendering the page: no form found",
|
||||
);
|
||||
fLogin.addEventListener("submit", async function (e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
let form = e.target as (HTMLFormElement | null);
|
||||
if (form === null)
|
||||
return showError('Failed to send form...');
|
||||
let formData = Object.fromEntries((new FormData(form)).entries());
|
||||
if (!('login' in formData) || typeof formData['login'] !== 'string' || (formData['login'] as string).length === 0)
|
||||
return showError('Please enter a Login');
|
||||
if (!('password' in formData) || typeof formData['password'] !== 'string' || (formData['password'] as string).length === 0)
|
||||
return showError('Please enter a Password');
|
||||
let form = e.target as HTMLFormElement | null;
|
||||
if (form === null) return showError("Failed to send form...");
|
||||
let formData = Object.fromEntries(new FormData(form).entries());
|
||||
if (
|
||||
!("login" in formData) ||
|
||||
typeof formData["login"] !== "string" ||
|
||||
(formData["login"] as string).length === 0
|
||||
)
|
||||
return showError("Please enter a Login");
|
||||
if (
|
||||
!("password" in formData) ||
|
||||
typeof formData["password"] !== "string" ||
|
||||
(formData["password"] as string).length === 0
|
||||
)
|
||||
return showError("Please enter a Password");
|
||||
try {
|
||||
const res = await client.login({ loginRequest: { name: formData.login, password: formData.password } });
|
||||
const res = await client.login({
|
||||
loginRequest: {
|
||||
name: formData.login,
|
||||
password: formData.password,
|
||||
},
|
||||
});
|
||||
switch (res.kind) {
|
||||
case 'success': {
|
||||
Cookie.set('token', res.payload.token, { path: '/', sameSite: 'lax' });
|
||||
case "success": {
|
||||
Cookie.set("token", res.payload.token, {
|
||||
path: "/",
|
||||
sameSite: "lax",
|
||||
});
|
||||
let user = await updateUser();
|
||||
if (user === null)
|
||||
return showError('Failed to get user: no user ?');
|
||||
setTitle(`Welcome ${user.guest ? '[GUEST] ' : ''}${user.name}`);
|
||||
return showError(
|
||||
"Failed to get user: no user ?",
|
||||
);
|
||||
setTitle(
|
||||
`Welcome ${user.guest ? "[GUEST] " : ""}${user.name}`,
|
||||
);
|
||||
if (returnTo !== null) navigateTo(returnTo);
|
||||
break;
|
||||
}
|
||||
case 'otpRequired': {
|
||||
showInfo('Got ask OTP, not yet implemented');
|
||||
case "otpRequired": {
|
||||
showInfo("Got ask OTP, not yet implemented");
|
||||
break;
|
||||
}
|
||||
case 'failed': {
|
||||
case "failed": {
|
||||
showError(`Failed to login: ${res.msg}`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Login error:", e);
|
||||
showError('Failed to login: Unknown error');
|
||||
showError("Failed to login: Unknown error");
|
||||
}
|
||||
});
|
||||
|
||||
const bLoginAsGuest = document.querySelector<HTMLButtonElement>('#bGuestLogin');
|
||||
bLoginAsGuest?.addEventListener('click', async () => {
|
||||
const bLoginAsGuest =
|
||||
document.querySelector<HTMLButtonElement>("#bGuestLogin");
|
||||
bLoginAsGuest?.addEventListener("click", async () => {
|
||||
try {
|
||||
const res = await client.guestLogin();
|
||||
switch (res.kind) {
|
||||
case 'success': {
|
||||
Cookie.set('token', res.payload.token, { path: '/', sameSite: 'lax' });
|
||||
case "success": {
|
||||
Cookie.set("token", res.payload.token, {
|
||||
path: "/",
|
||||
sameSite: "lax",
|
||||
});
|
||||
let user = await updateUser();
|
||||
if (user === null)
|
||||
return showError('Failed to get user: no user ?');
|
||||
setTitle(`Welcome ${user.guest ? '[GUEST] ' : ''}${user.name}`);
|
||||
return showError(
|
||||
"Failed to get user: no user ?",
|
||||
);
|
||||
setTitle(
|
||||
`Welcome ${user.guest ? "[GUEST] " : ""}${user.name}`,
|
||||
);
|
||||
if (returnTo !== null) navigateTo(returnTo);
|
||||
break;
|
||||
}
|
||||
case 'failed': {
|
||||
case "failed": {
|
||||
showError(`Failed to login: ${res.msg}`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Login error:", e);
|
||||
showError('Failed to login: Unknown error');
|
||||
showError("Failed to login: Unknown error");
|
||||
}
|
||||
});
|
||||
|
||||
const dOtherLoginArea = document.querySelector<HTMLDivElement>('#otherLogin');
|
||||
const dOtherLoginArea =
|
||||
document.querySelector<HTMLDivElement>("#otherLogin");
|
||||
if (dOtherLoginArea) {
|
||||
let styleSheetElement = document.createElement('style');
|
||||
let styleSheetElement = document.createElement("style");
|
||||
styleSheetElement.innerText = "";
|
||||
// TODO: fetch all the providers from an API ?
|
||||
const providersReq = await client.providerList();
|
||||
|
|
@ -92,37 +169,32 @@ function handleLogin(_url: string, _args: RouteHandlerParams): RouteHandlerRetur
|
|||
]*/
|
||||
let first = true;
|
||||
for (const p of providers) {
|
||||
let b = document.createElement('button');
|
||||
if (first && providers.length % 2) b.classList.add('last:col-span-2');
|
||||
let b = document.createElement("button");
|
||||
if (first && providers.length % 2)
|
||||
b.classList.add("last:col-span-2");
|
||||
first = false;
|
||||
b.classList.add(...(
|
||||
'w-full text-white font-medium py-2 rounded-xl transition'
|
||||
.split(' ')
|
||||
));
|
||||
b.classList.add(`providerButton-${p.name}`)
|
||||
b.classList.add(
|
||||
..."w-full text-white font-medium py-2 rounded-xl transition".split(
|
||||
" ",
|
||||
),
|
||||
);
|
||||
b.classList.add(`providerButton-${p.name}`);
|
||||
|
||||
const col = p.colors;
|
||||
|
||||
for (const k of Object.keys(col)) {
|
||||
let c = (col as any)[k].trim();
|
||||
if (c.startsWith('bg-')) {
|
||||
c = c.replace(/^bg-/, '');
|
||||
if (c.startsWith("bg-")) {
|
||||
c = c.replace(/^bg-/, "");
|
||||
const customProp = c.match(/^\((.+)\)$/);
|
||||
const customVal = c.match(/^\[(.+)\]$/);
|
||||
|
||||
if (customProp)
|
||||
c = `var(${customProp[1]})`
|
||||
else if (customVal)
|
||||
c = customVal[1];
|
||||
else if (c === 'inherit')
|
||||
c = 'inherit';
|
||||
else if (c === 'current')
|
||||
c = 'currentColor';
|
||||
else if (c === 'transparent')
|
||||
c = 'transparent';
|
||||
else
|
||||
c = `var(--color-${c})`
|
||||
|
||||
if (customProp) c = `var(${customProp[1]})`;
|
||||
else if (customVal) c = customVal[1];
|
||||
else if (c === "inherit") c = "inherit";
|
||||
else if (c === "current") c = "currentColor";
|
||||
else if (c === "transparent") c = "transparent";
|
||||
else c = `var(--color-${c})`;
|
||||
}
|
||||
(col as any)[k] = c;
|
||||
}
|
||||
|
|
@ -134,19 +206,17 @@ function handleLogin(_url: string, _args: RouteHandlerParams): RouteHandlerRetur
|
|||
b.dataset.name = p.name;
|
||||
//if (p.icon_url) b.dataset.icon = p.icon_url;
|
||||
|
||||
b.innerHTML = `<span class="">${p.displayName}</span>`
|
||||
b.addEventListener('click', () => {
|
||||
b.innerHTML = `<span class="">${p.displayName}</span>`;
|
||||
b.addEventListener("click", () => {
|
||||
location.href = `/api/auth/oauth2/${p.name}/login`;
|
||||
})
|
||||
});
|
||||
|
||||
dOtherLoginArea.insertAdjacentElement('afterbegin', b);
|
||||
dOtherLoginArea.insertAdjacentElement("afterbegin", b);
|
||||
}
|
||||
app?.appendChild(styleSheetElement);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
addRoute('/login', handleLogin, { bypass_auth: true })
|
||||
addRoute("/login", handleLogin, { bypass_auth: true });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue