This commit is contained in:
Evert Prants 2024-06-10 17:43:16 +03:00
parent d8f6d24511
commit af9c70f169
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
10 changed files with 26 additions and 11 deletions

View File

@ -6,6 +6,7 @@
--in-background-image: none; --in-background-image: none;
--in-normalized-background: #cceaff; --in-normalized-background: #cceaff;
--in-container-background: #f1faff; --in-container-background: #f1faff;
--in-container-shadow: 0px 0px 16px 0px rgba(0, 0, 0, 0.15);
--in-text-color: #000000; --in-text-color: #000000;
--in-link-color: #000000; --in-link-color: #000000;

View File

@ -25,7 +25,7 @@ const handleThemeHook = (async ({ resolve, event }) => {
const newTheme = event.url.searchParams.get('themeMode') as ThemeModeType; const newTheme = event.url.searchParams.get('themeMode') as ThemeModeType;
const cookieTheme = event.cookies.get('themeMode') as ThemeModeType; const cookieTheme = event.cookies.get('themeMode') as ThemeModeType;
const theme: ThemeModeType | null = newTheme || cookieTheme; const theme: ThemeModeType = newTheme || cookieTheme;
if (theme) { if (theme) {
return await resolve(event, { return await resolve(event, {
transformPageChunk: ({ html }) => html.replace(/theme-base=""/g, `theme-base="${theme}"`) transformPageChunk: ({ html }) => html.replace(/theme-base=""/g, `theme-base="${theme}"`)

View File

@ -48,8 +48,8 @@
<dt>{$t('admin.oauth2.urls.title')}</dt> <dt>{$t('admin.oauth2.urls.title')}</dt>
<dd> <dd>
{#each client.urls as url} {#each client.urls as url}
<a href={url.url} target="_blank" rel="nofollow noreferrer" class="client-url" <span class="client-url"
>{$t(`admin.oauth2.urls.types.${url.type}`)} &lt;{url.url}&gt;</a >{$t(`admin.oauth2.urls.types.${url.type}`)} &lt;{url.url}&gt;</span
> >
{/each} {/each}
</dd> </dd>

View File

@ -23,6 +23,9 @@
padding: 40px; padding: 40px;
max-width: 1080px; max-width: 1080px;
width: 100%; width: 100%;
box-shadow: var(--in-container-shadow);
-webkit-box-shadow: var(--in-container-shadow);
-moz-box-shadow: var(--in-container-shadow);
} }
main { main {

View File

@ -24,5 +24,8 @@
padding: 40px; padding: 40px;
max-width: 600px; max-width: 600px;
width: 100%; width: 100%;
box-shadow: var(--in-container-shadow);
-webkit-box-shadow: var(--in-container-shadow);
-moz-box-shadow: var(--in-container-shadow);
} }
</style> </style>

View File

@ -250,6 +250,7 @@ export const userToken = mysqlTable('user_token', {
}); });
export type UserToken = typeof userToken.$inferSelect; export type UserToken = typeof userToken.$inferSelect;
export type NewUserToken = typeof userToken.$inferInsert;
export const auditLogRelations = relations(auditLog, ({ one }) => ({ export const auditLogRelations = relations(auditLog, ({ one }) => ({
user: one(user, { user: one(user, {

View File

@ -1,24 +1,24 @@
import { and, eq, gt, isNull, or, sql } from 'drizzle-orm'; import { and, eq, gt, isNull, or, sql } from 'drizzle-orm';
import { CryptoUtils } from '../crypto-utils'; import { CryptoUtils } from '../crypto-utils';
import { DB, userToken, type User, type UserToken } from '../drizzle'; import { DB, userToken, type User, type UserToken, type NewUserToken } from '../drizzle';
export class UserTokens { export class UserTokens {
static async create( static async create(
type: (typeof userToken.$inferInsert)['type'], type: NewUserToken['type'],
expires: Date, expires: Date,
userId?: number, userId?: number,
nonce?: string, nonce?: string,
metadata?: string metadata?: string
) { ) {
const token = CryptoUtils.generateString(64); const token = CryptoUtils.generateString(64);
const obj = <typeof userToken.$inferInsert>{ const obj = {
type, type,
token, token,
userId, userId,
expires_at: expires, expires_at: expires,
nonce, nonce,
metadata metadata
}; } satisfies NewUserToken;
const [retval] = await DB.drizzle.insert(userToken).values(obj); const [retval] = await DB.drizzle.insert(userToken).values(obj);
return { id: retval.insertId, ...obj } as UserToken; return { id: retval.insertId, ...obj } as UserToken;
} }
@ -28,7 +28,7 @@ export class UserTokens {
await DB.drizzle.delete(userToken).where(eq(userToken.token, removeBy)); await DB.drizzle.delete(userToken).where(eq(userToken.token, removeBy));
} }
static async getByToken(token: string, type: (typeof userToken.$inferSelect)['type']) { static async getByToken(token: string, type: UserToken['type']) {
const [returned] = await DB.drizzle const [returned] = await DB.drizzle
.select() .select()
.from(userToken) .from(userToken)

View File

@ -13,7 +13,7 @@ export class TimeOTP {
} }
public static getUri(secret: string, username: string): string { public static getUri(secret: string, username: string): string {
return totp.keyuri(username, PUBLIC_SITE_NAME, secret); return totp.keyuri(username, env.PUBLIC_SITE_NAME, secret);
} }
public static createSecret(): string { public static createSecret(): string {

View File

@ -1,3 +1,4 @@
import { env } from '$env/dynamic/private';
import { redirect } from '@sveltejs/kit'; import { redirect } from '@sveltejs/kit';
export const actions = { export const actions = {
@ -8,6 +9,7 @@ export const actions = {
cookies.set('themeMode', themeMode, { cookies.set('themeMode', themeMode, {
maxAge: 60 * 60 * 24 * 365, maxAge: 60 * 60 * 24 * 365,
httpOnly: true, httpOnly: true,
secure: env.SESSION_SECURE === 'true',
sameSite: 'lax', sameSite: 'lax',
path: '/' path: '/'
}); });

View File

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
import { enhance } from '$app/forms'; import { enhance } from '$app/forms';
import { t } from '$lib/i18n';
import type { ActionData, PageData } from './$types'; import type { ActionData, PageData } from './$types';
import Alert from '$lib/components/Alert.svelte'; import Alert from '$lib/components/Alert.svelte';
import Button from '$lib/components/Button.svelte'; import Button from '$lib/components/Button.svelte';
@ -8,8 +9,9 @@
import FormControl from '$lib/components/form/FormControl.svelte'; import FormControl from '$lib/components/form/FormControl.svelte';
import FormSection from '$lib/components/form/FormSection.svelte'; import FormSection from '$lib/components/form/FormSection.svelte';
import FormWrapper from '$lib/components/form/FormWrapper.svelte'; import FormWrapper from '$lib/components/form/FormWrapper.svelte';
import { t } from '$lib/i18n';
import ButtonRow from '$lib/components/container/ButtonRow.svelte'; import ButtonRow from '$lib/components/container/ButtonRow.svelte';
import TitleRow from '$lib/components/container/TitleRow.svelte';
import ThemeButton from '$lib/components/ThemeButton.svelte';
export let data: PageData; export let data: PageData;
export let form: ActionData; export let form: ActionData;
@ -20,7 +22,10 @@
</svelte:head> </svelte:head>
<SideContainer> <SideContainer>
<TitleRow>
<h1>{env.PUBLIC_SITE_NAME}</h1> <h1>{env.PUBLIC_SITE_NAME}</h1>
<ThemeButton />
</TitleRow>
<h2>{$t('account.login.title')}</h2> <h2>{$t('account.login.title')}</h2>