From 853571dac5f9fe0b3f98648e34ab4d6316cc992a Mon Sep 17 00:00:00 2001 From: Seania Date: Sat, 14 Jan 2023 07:33:51 +0900 Subject: [PATCH] fix login & permission editor of users --- src/hooks.server.ts | 39 +++-- src/lib/auth/user/server.ts | 16 ++ src/lib/bitfield.ts | 2 +- src/lib/community/article/server.ts | 2 +- src/lib/community/board/server.ts | 4 +- src/lib/community/comment/server.ts | 3 +- src/lib/community/permission/index.ts | 153 ++++++++++++------ src/lib/community/permission/name.ts | 39 +++++ src/lib/community/permission/shared/flags.ts | 34 ++++ src/lib/components/Checkbox.svelte | 24 ++- src/lib/components/Nav.svelte | 1 - src/lib/database/index.ts | 1 + src/routes/+layout.svelte | 19 ++- .../[id=integer]/api/write/+server.ts | 23 +-- .../[id=integer]/manage/+page.svelte | 6 +- .../manage/permissions/$types.d.ts | 6 + .../manage/permissions/+page.server.ts | 47 ++++++ .../manage/permissions/+page.svelte | 13 ++ src/routes/community/api/search/+server.ts | 1 - src/routes/login/+page.server.ts | 2 +- src/routes/login/+page.svelte | 34 ++-- src/routes/user/+layout.server.ts | 1 - src/routes/user/admin/+layout.server.ts | 3 +- src/routes/user/admin/list/+page.svelte | 10 +- src/routes/user/admin/promote/$types.d.ts | 7 + src/routes/user/admin/promote/+page.server.ts | 58 +++++++ src/routes/user/admin/promote/+page.svelte | 74 ++++++++- 27 files changed, 504 insertions(+), 118 deletions(-) create mode 100644 src/lib/community/permission/name.ts create mode 100644 src/lib/community/permission/shared/flags.ts create mode 100644 src/routes/community/[id=integer]/manage/permissions/$types.d.ts create mode 100644 src/routes/community/[id=integer]/manage/permissions/+page.server.ts create mode 100644 src/routes/community/[id=integer]/manage/permissions/+page.svelte create mode 100644 src/routes/user/admin/promote/$types.d.ts create mode 100644 src/routes/user/admin/promote/+page.server.ts diff --git a/src/hooks.server.ts b/src/hooks.server.ts index c0e5c1a..f74ad07 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -15,13 +15,14 @@ import { version as versionUuid, } from '$lib/uuid/esm-node'; import {env} from 'node:process'; +import {isEmpty} from 'lodash-es'; +import {Permissions} from '$lib/community/permission'; global.atob = atob; global.btoa = btoa; - // noinspection JSUnusedGlobalSymbols -export const handle = sequence(init, ui, images, auth, setSessionId); +export const handle = sequence(init, ui, images, auth, setSessionId, setPermissions); function init({event, resolve}: HandleParameters): MaybePromise { if (!event.locals) { @@ -157,14 +158,14 @@ function images({event, resolve}: HandleParameters): MaybePromise { return resolve(event); } -function resolveJwt(jwt?: Jwt): IUserSession | undefined { +function resolveJwt(jwt?: Jwt, scope: 'user' | 'refresh' = 'user'): IUserSession | undefined { if (!jwt) { return undefined; } const body = jwt.body.toJSON(); - if (body.iss !== 'https://ru.hn/' || body.scope !== 'user') { + if (body.iss !== 'https://ru.hn/' || body.scope !== scope) { return undefined; } @@ -177,7 +178,7 @@ async function auth({event, resolve}: HandleParameters): Promise { if (token) { const jwt = njwt.verify(token, key); - const body = resolveJwt(jwt); + const body = resolveJwt(jwt, 'user'); if (!body) { event.locals.user = body; @@ -190,16 +191,19 @@ async function auth({event, resolve}: HandleParameters): Promise { if (refresh) { const jwt = njwt.verify(refresh, key); - const body = resolveJwt(jwt); + const body = resolveJwt(jwt, 'refresh'); if (!body) { event.locals.user = body; return resolve(event); } - const {uid} = body; - const user = await User.findByUniqueId(uid); - const newToken = await user?.token('user'); + const {sub} = body; + const user = User.fromSub(sub); + const newToken = await user?.token('user', { + rank: await user.rank, + adult: await user.isAdult(), + }); if (newToken) { event.cookies.set('token', newToken.compact(), { path: '/', @@ -210,6 +214,8 @@ async function auth({event, resolve}: HandleParameters): Promise { }); event.locals.user = newToken.body.toJSON() as any; + } else { + console.error('no token?'); } } } @@ -238,6 +244,21 @@ async function setSessionId({event, resolve}: HandleParameters): Promise { + if (event.locals?.user) { + const user = User.fromSub(event.locals.user.sub)!; + const {permissions} = user; + const all = await permissions.getAll(); + if (isEmpty(all)) { + permissions.set(Permissions.DefaultPermissions).then(); + } + } + return resolve(event); +} + interface HandleParameters { event: RequestEvent, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise diff --git a/src/lib/auth/user/server.ts b/src/lib/auth/user/server.ts index d5c9460..8102dfe 100644 --- a/src/lib/auth/user/server.ts +++ b/src/lib/auth/user/server.ts @@ -8,13 +8,19 @@ import type {IUser} from '$lib/types/user'; import {isStringInteger} from '$lib/util'; import type {IArangoDocumentIdentifier} from '$lib/database'; import {Notifications} from '$lib/notifications/server'; +import {Permissions} from '$lib/community/permission'; +import {last} from 'lodash-es'; +import {error} from '@sveltejs/kit'; +import HttpStatus from 'http-status-codes'; type UnsafeUser = IUser & { password: string }; export class User { private readonly notifications: Notifications; + readonly permissions: Permissions; constructor(readonly id: string) { this.notifications = new Notifications(this); + this.permissions = new Permissions(null, this); } private stored: UnsafeUser | undefined; @@ -90,6 +96,11 @@ export class User { }); } + static fromSub(sub: string): User | null { + const id = last(sub.split('/')); + return id ? new User(id) : null; + } + static async findByUniqueId(uid?: string): Promise { // console.trace('3'); if (!uid) { @@ -137,6 +148,11 @@ export class User { throw Error('password invalid (is that shorten than 6)'); } + const regex = /^[a-zA-Z0-9ㄱ-ㅎ가-힣_]+$/; + if (!regex.test(this.id)) { + throw error(HttpStatus.BAD_REQUEST, 'Not allowed character found'); + } + const hashed = await argon2.hash(password); await db.query(aql` diff --git a/src/lib/bitfield.ts b/src/lib/bitfield.ts index 45adaf7..b385d74 100644 --- a/src/lib/bitfield.ts +++ b/src/lib/bitfield.ts @@ -146,6 +146,6 @@ export class BitField { } } -export function BitFlag(x: bigint | number) { +export function BitFlag(x: bigint | number): bigint { return BigInt(1) << BigInt(x); } \ No newline at end of file diff --git a/src/lib/community/article/server.ts b/src/lib/community/article/server.ts index 4918c08..f3480be 100644 --- a/src/lib/community/article/server.ts +++ b/src/lib/community/article/server.ts @@ -15,7 +15,7 @@ import {uploadAllowedExtensions} from '$lib/file/image/shared'; import {env} from 'node:process'; export class Article { - + readonly type = 'article'; title: string | undefined; content: string | undefined; diff --git a/src/lib/community/board/server.ts b/src/lib/community/board/server.ts index e2b5ffb..f4b92f3 100644 --- a/src/lib/community/board/server.ts +++ b/src/lib/community/board/server.ts @@ -18,7 +18,9 @@ import {inRange} from 'lodash-es'; type BoardType = 'default' | 'best'; export class Board { - constructor(private readonly id: string) { + readonly type = 'board'; + + constructor(readonly id: string) { } static async listAll() { diff --git a/src/lib/community/comment/server.ts b/src/lib/community/comment/server.ts index bd3480b..5eed625 100644 --- a/src/lib/community/comment/server.ts +++ b/src/lib/community/comment/server.ts @@ -5,7 +5,8 @@ import db from '$lib/database/instance'; import {aql} from 'arangojs'; export class Comment { - constructor(private readonly id: string) { + readonly type = 'comment'; + constructor(readonly id: string) { } static async new(relative: Article, author: User, content: string): Promise { diff --git a/src/lib/community/permission/index.ts b/src/lib/community/permission/index.ts index d6b72ee..40f49be 100644 --- a/src/lib/community/permission/index.ts +++ b/src/lib/community/permission/index.ts @@ -1,14 +1,15 @@ -import {Board} from '$lib/community/board/server'; -import {Article} from '$lib/community/article/server'; -import {Comment} from '$lib/community/comment/server'; +import type {Board} from '$lib/community/board/server'; +import type {Article} from '$lib/community/article/server'; +import type {Comment} from '$lib/community/comment/server'; import {User} from '$lib/auth/user/server'; import {EUserRanks} from '$lib/types/user-ranks'; -import {BitField, type BitFieldResolvable, BitFlag} from '$lib/bitfield'; +import db from '$lib/database/instance'; +import {aql} from 'arangojs'; +import {flags} from '$lib/community/permission/shared/flags'; -export class Permission extends BitField { +export class Permissions { private user: User; - constructor(bits: BitFieldResolvable = 0, private context: Board | Article | Comment, user: string | User) { - super(bits); + constructor(private context: Board | Article | Comment | null, user: string | User) { if (user instanceof User) { this.user = user; } else { @@ -16,62 +17,114 @@ export class Permission extends BitField { } } - static FLAGS = { - READ_POST: BitFlag(0), - WRITE_POST: BitFlag(1), - EDIT_POST: BitFlag(2), - DELETE_POST: BitFlag(3), - MANAGE_POST: BitFlag(4), - VIEW_LIST: BitFlag(5), - READ_COMMENT: BitFlag(6), - VIEW_BOARDLIST: BitFlag(7), - WRITE_COMMENT: BitFlag(8), - EDIT_COMMENT: BitFlag(9), - DELETE_COMMENT: BitFlag(10), - MANAGE_COMMENT: BitFlag(11), - NEW_BOARD: BitFlag(12), - DELETE_BOARD: BitFlag(13), - RENAME_BOARD: BitFlag(14), - LOCK_BOARD: BitFlag(15), - BAN_USER_PERMANENTLY: BitFlag(16), - BAN_USER_TEMPORARY: BitFlag(17), - REORDER_BOARD: BitFlag(18), - ADULT: BitFlag(19), - CHANGE_PUB_BOARD: BitFlag(20), - CHANGE_USER_GRANT: BitFlag(21), - CHANGE_USER_PERMISSION: BitFlag(22), - CHANGE_USERNAME: BitFlag(23), - ADD_TAG: BitFlag(24), - REMOVE_TAG: BitFlag(25), - REMOVE_OWN_TAG: BitFlag(26), - VIEW_TAG_OWNER: BitFlag(27), - }; - - async own(permission: Permissions): Promise { - return new Promise(async (resolve, reject) => { + static readonly FLAGS = flags; + + static readonly DefaultPermissions = + Permissions.FLAGS.WRITE_ARTICLE | + Permissions.FLAGS.READ_ARTICLE | + Permissions.FLAGS.EDIT_ARTICLE | + Permissions.FLAGS.DELETE_ARTICLE | + Permissions.FLAGS.READ_COMMENT | + Permissions.FLAGS.EDIT_COMMENT | + Permissions.FLAGS.WRITE_COMMENT | + Permissions.FLAGS.DELETE_COMMENT | + Permissions.FLAGS.VIEW_BOARDLIST | + Permissions.FLAGS.VIEW_ARTICLELIST + ; + + private check(source: bigint, compare: bigint): boolean { + // eslint-disable-next-line no-extra-boolean-cast + return !!(source & Permissions.FLAGS.ALL) ? true : !!(source & compare); + } + + hasOwn(permission: bigint): Promise { + return new Promise(async (resolve) => { if (await this.user.rank <= EUserRanks.Banned) { - return false; + return resolve(false); } - if (this.context instanceof Board) { - - } else if (this.context instanceof Article) { + if (await this.user.rank >= EUserRanks.Admin) { + return resolve(true); + } - } else if (this.context instanceof Comment) { + const result = await this.get(); + if (!result) { + return resolve(false); } - return false; + + return resolve(this.check(result, permission)); }); } - get isReadable(): Promise { - return new Promise(() => { + async set(permission: bigint) { + const search = { + user: await this.user.uid, + context: this.context?.type ?? null, + target: this.context?.id ?? null, + }; + const newPermission = { + ...search, + permissions: permission.toString(), + }; + return await db.query(aql` + upsert ${search} insert ${newPermission} update ${{permissions: permission.toString()}} in permissions`); + } - }); + async enable(permission: bigint) { + const current = await this.get() ?? Permissions.DefaultPermissions; + if (!this.check(current, permission)) { + await this.set(current ^ permission); + } + } + + async disable(permission: bigint) { + const current = await this.get() ?? Permissions.DefaultPermissions; + if (this.check(current, permission)) { + await this.set(current ^ permission); + } } + + async get(): Promise { + const search = { + user: await this.user.uid, + context: this.context?.type ?? null, + target: this.context?.id ?? null, + }; + + const cursor = await db.query(aql` + for p in permissions + filter p.user == ${search.user} && p.context == ${search.context} && p.target == ${search.target} + return p`); + + const data = await cursor.next(); + + console.log(data); + + if (!data) { + return null; + } + + return BigInt(data.permissions); + } + + async getAll() { + const search = { + user: await this.user.uid, + context: this.context?.type ?? null, + target: this.context?.id ?? null, + }; + + const cursor = await db.query(aql` + for p in permissions + filter p.user == ${search.user} + return p`); + + return await cursor.all(); + } + } -export type Permissions = 'read' | 'write' | 'delete' | 'edit'; export type UserPermissions = boolean | AdultCertification | [boolean, AdultCertification]; enum AdultCertification { None, diff --git a/src/lib/community/permission/name.ts b/src/lib/community/permission/name.ts new file mode 100644 index 0000000..677d278 --- /dev/null +++ b/src/lib/community/permission/name.ts @@ -0,0 +1,39 @@ +import type {Permissions} from '$lib/community/permission/index'; + +type permissions = typeof Permissions.FLAGS; +export type PermissionsFlags = keyof permissions; + +export const names: Record = { + ADD_TAG: '태그 추가', + ADULT: '성인', + ALL: '모두 (관리자)', + BAN_USER_PERMANENTLY: '사용자 영구밴', + BAN_USER_TEMPORARY: '사용자 임시밴', + CHANGE_PUB_BOARD: '게시판 가시성 변경', + CHANGE_USERNAME: '사용자 이름 변경', + CHANGE_USER_GRANT: '사용자 등급 변경', + CHANGE_USER_PERMISSION: '사용자 권한 변경', + DELETE_ARTICLE: '게시글 삭제', + DELETE_BOARD: '게시판 삭제', + DELETE_COMMENT: '댓글 삭제', + EDIT_ARTICLE: '게시글 편집', + EDIT_COMMENT: '댓글 편집', + LOCK_BOARD: '게시판 잠금', + MANAGE_ARTICLE: '게시글 관리', + MANAGE_BOARD: '게시판 관리', + MANAGE_COMMENT: '댓글 관리', + NEW_BOARD: '새 게시판 생성', + READ_ARTICLE: '게시글 읽기', + READ_COMMENT: '댓글 읽기', + REMOVE_OWN_TAG: '소유한 태그 지우기', + REMOVE_TAG: '태그 지우기', + RENAME_BOARD: '게시판 이름 변경', + REORDER_BOARD: '게시판 순서 변경', + VIEW_BOARDLIST: '게시판 목록 보기', + VIEW_ARTICLELIST: '게시글 목록 보기', + VIEW_TAG_OWNER: '태그 작성자 목록 보기', + WRITE_ARTICLE: '게시글 쓰기', + WRITE_COMMENT: '댓글 쓰기', +}; + +export default names; \ No newline at end of file diff --git a/src/lib/community/permission/shared/flags.ts b/src/lib/community/permission/shared/flags.ts new file mode 100644 index 0000000..78460c6 --- /dev/null +++ b/src/lib/community/permission/shared/flags.ts @@ -0,0 +1,34 @@ +import {BitFlag} from '$lib/bitfield'; + +export const flags = { + ALL: BitFlag(0), + READ_ARTICLE: BitFlag(1), + WRITE_ARTICLE: BitFlag(2), + EDIT_ARTICLE: BitFlag(3), + DELETE_ARTICLE: BitFlag(4), + MANAGE_ARTICLE: BitFlag(5), + VIEW_ARTICLELIST: BitFlag(6), + READ_COMMENT: BitFlag(7), + VIEW_BOARDLIST: BitFlag(8), + WRITE_COMMENT: BitFlag(9), + EDIT_COMMENT: BitFlag(10), + DELETE_COMMENT: BitFlag(11), + MANAGE_COMMENT: BitFlag(12), + NEW_BOARD: BitFlag(13), + DELETE_BOARD: BitFlag(14), + RENAME_BOARD: BitFlag(15), + LOCK_BOARD: BitFlag(16), + BAN_USER_PERMANENTLY: BitFlag(17), + BAN_USER_TEMPORARY: BitFlag(18), + ADULT: BitFlag(19), + REORDER_BOARD: BitFlag(20), + CHANGE_PUB_BOARD: BitFlag(21), + CHANGE_USER_GRANT: BitFlag(22), + CHANGE_USER_PERMISSION: BitFlag(23), + CHANGE_USERNAME: BitFlag(24), + ADD_TAG: BitFlag(25), + REMOVE_TAG: BitFlag(26), + REMOVE_OWN_TAG: BitFlag(27), + VIEW_TAG_OWNER: BitFlag(28), + MANAGE_BOARD: BitFlag(29), +}; \ No newline at end of file diff --git a/src/lib/components/Checkbox.svelte b/src/lib/components/Checkbox.svelte index d8a2ad3..e1b5e2a 100644 --- a/src/lib/components/Checkbox.svelte +++ b/src/lib/components/Checkbox.svelte @@ -1,6 +1,8 @@ -
- - - +
\ No newline at end of file + + \ No newline at end of file diff --git a/src/lib/components/Nav.svelte b/src/lib/components/Nav.svelte index 62959a6..e86f2ab 100644 --- a/src/lib/components/Nav.svelte +++ b/src/lib/components/Nav.svelte @@ -219,7 +219,6 @@ - {#if $client?.user && $client.user.rank > EUserRanks.User}
  • ): AllowedExtensions[] { - const {image_order} = cookies; - return ((image_order)?.split(',') as AllowedExtensions[] || undefined) ?? ['jxl', 'avif', 'webp', 'png']; + function getImageOrder(imageOrder?: string): AllowedExtensions[] { + return ((imageOrder ?? 'jxl,avif,webp,png').split(',') as AllowedExtensions[] || undefined) ?? ['jxl', 'avif', 'webp', 'png']; } afterNavigate(() => { - const cookies = CookieParser.parse(document.cookie); + // const cookies = CookieParser.parse(document.cookie); client.update((prev) => { return { user: prev.user ?? data.user, settings: { - imageOrder: getImageOrder(cookies), + imageOrder: getImageOrder(Cookies.get('image_order')), }, ui: { - commentFolding: cookies?.comment_folding === 'true', - buttonAlign: cookies?.button_align !== 'left' ? 'right' : 'left', - listType: cookies?.list_type !== 'gallery' ? 'list' : 'gallery', + commentFolding: Cookies.get('comment_folding') === 'true', + buttonAlign: Cookies.get('button_align') !== 'left' ? 'right' : 'left', + listType: Cookies.get('list_type') !== 'gallery' ? 'list' : 'gallery', }, }; }); - // console.log(data, $client); + console.log(data, $client); }); onMount(() => { diff --git a/src/routes/community/[id=integer]/api/write/+server.ts b/src/routes/community/[id=integer]/api/write/+server.ts index 394fbc6..18a2baf 100644 --- a/src/routes/community/[id=integer]/api/write/+server.ts +++ b/src/routes/community/[id=integer]/api/write/+server.ts @@ -17,7 +17,7 @@ import type {IUser} from '$lib/types/user'; import {Pusher} from '$lib/pusher/server'; import {getTagErrors} from '../../[article=integer]/api/tag/add/+server'; import {error} from '$lib/kit'; -import {Permission} from '$lib/community/permission'; +import {Permissions} from '$lib/community/permission'; export async function GET({params, locals: {user}}: RequestEvent): Promise { if (!user) { @@ -49,9 +49,12 @@ export async function GET({params, locals: {user}}: RequestEvent): Promise { - // console.log('new write') + if (!locals.user) { + throw error(HttpStatus.NOT_ACCEPTABLE, 'please login and try again'); + } + const article = new ArticleDto(await request.json()); - const write = new WriteRequest(article); + const write = new WriteRequest(article, locals.user.uid); if (isEmpty(write.title)) { throw error(HttpStatus.NOT_ACCEPTABLE, 'title is too short'); @@ -69,10 +72,6 @@ export async function POST({request, params, locals}: RequestEvent): Promise, userId: string) { if (this.isTitleEmpty || this.isContentEmpty) { @@ -134,7 +133,7 @@ class WriteRequest { } this.board = new Board(this.boardId!); - this.permission = new Permission('', userId); + this.permission = new Permissions(this.board, userId); } get boardId(): string | undefined { @@ -191,7 +190,9 @@ class WriteRequest { * @param userId 글을 쓴 사람의 유니크 id입니다. * @return notify 전용 값입니다. */ - async saveToDB(userId: string) { + async submit(userId: string) { + this.permission.hasOwn(Permissions.FLAGS.WRITE_ARTICLE); + if (!await this.isBoardExists) { this.error = 'board not exsists'; return; diff --git a/src/routes/community/[id=integer]/manage/+page.svelte b/src/routes/community/[id=integer]/manage/+page.svelte index f51a312..8d5d82b 100644 --- a/src/routes/community/[id=integer]/manage/+page.svelte +++ b/src/routes/community/[id=integer]/manage/+page.svelte @@ -35,10 +35,14 @@ - + 비공개 게시글 목록 + + 이 게시판 필요 권한 설정 + + diff --git a/src/routes/community/[id=integer]/manage/permissions/$types.d.ts b/src/routes/community/[id=integer]/manage/permissions/$types.d.ts new file mode 100644 index 0000000..87eb71c --- /dev/null +++ b/src/routes/community/[id=integer]/manage/permissions/$types.d.ts @@ -0,0 +1,6 @@ +import type {IUser} from '$lib/types/user'; + +export interface PageData { + managers: IUser[]; + requires: bigint; +} \ No newline at end of file diff --git a/src/routes/community/[id=integer]/manage/permissions/+page.server.ts b/src/routes/community/[id=integer]/manage/permissions/+page.server.ts new file mode 100644 index 0000000..bef315e --- /dev/null +++ b/src/routes/community/[id=integer]/manage/permissions/+page.server.ts @@ -0,0 +1,47 @@ +import type {ServerLoadEvent} from '@sveltejs/kit'; +import type {PageData} from './$types'; +import {User} from '$lib/auth/user/server'; +import {error} from '@sveltejs/kit'; +import HttpStatus from 'http-status-codes'; +import {Permissions} from '$lib/community/permission'; +import {Board} from '$lib/community/board/server'; + +export async function load({params: {id: bid}, locals}: ServerLoadEvent): Promise { + if (!locals.user) { + throw error(HttpStatus.UNAUTHORIZED); + } + + const user = User.fromSub(locals.user.sub); + + if (!user || !bid) { + throw error(HttpStatus.BAD_GATEWAY, 'Invalid request'); + } + + const board = new Board(bid); + + const request = new PermissionRequest(board, user); + + if (!await request.isAccessible()) { + throw error(HttpStatus.FORBIDDEN, 'You have no permissions'); + } + + + return { + managers: [], + requires: 12401240125125125401024012400n, + } +} + +class PermissionRequest { + + constructor(private readonly board: Board, + private readonly user: User) { + } + + isAccessible() { + // const permissions = this.user.permissions; + const permissions = new Permissions(this.board, this.user); + return permissions.hasOwn(Permissions.FLAGS.MANAGE_ARTICLE); + } + +} \ No newline at end of file diff --git a/src/routes/community/[id=integer]/manage/permissions/+page.svelte b/src/routes/community/[id=integer]/manage/permissions/+page.svelte new file mode 100644 index 0000000..3d25397 --- /dev/null +++ b/src/routes/community/[id=integer]/manage/permissions/+page.svelte @@ -0,0 +1,13 @@ + +
    +
    +

    이 게시판 관리자

    +
    + {data.requires} +
    +
    +
    \ No newline at end of file diff --git a/src/routes/community/api/search/+server.ts b/src/routes/community/api/search/+server.ts index 2dd2ab0..fbb1106 100644 --- a/src/routes/community/api/search/+server.ts +++ b/src/routes/community/api/search/+server.ts @@ -1,7 +1,6 @@ import type {RequestEvent} from '@sveltejs/kit'; import HttpStatus from 'http-status-codes'; import {isEmpty, last} from 'lodash-es'; -import type {ArticleItemDto} from '$lib/types/dto/article-item.dto'; import {client} from '$lib/database/search'; import {json} from '$lib/kit'; diff --git a/src/routes/login/+page.server.ts b/src/routes/login/+page.server.ts index bfdcd08..a81051a 100644 --- a/src/routes/login/+page.server.ts +++ b/src/routes/login/+page.server.ts @@ -48,7 +48,7 @@ export const actions: Actions = { cookies.set('refresh', refresh.compact(), { path: '/', - expires, + expires: expireRefresh, sameSite: 'strict', httpOnly: true, secure: !env.IS_DEV, diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte index 38d0658..e648d9b 100644 --- a/src/routes/login/+page.svelte +++ b/src/routes/login/+page.svelte @@ -5,27 +5,29 @@ import {client, decodeToken} from '$lib/auth/user/client'; import {page} from '$app/stores'; import {onDestroy} from 'svelte'; + import {browser} from '$app/environment'; - const unsub = page.subscribe(({form}) => { - const token = form?.token; + if (browser) { + onDestroy( + page.subscribe(({form}) => { + const token = form?.token; - if (token) { - const user = decodeToken(token); + if (token) { + const user = decodeToken(token); - if (user) { - $client.user = user; + if (user) { + $client.user = user; - NotificationsClient.init(user.uid); + NotificationsClient.init(user.uid); - goto(sessionStorage.getItem('ru.hn:back') ?? '/').then(() => { - sessionStorage.removeItem('ru.hn:back'); - }); - } - } - - }); - - onDestroy(unsub); + goto(sessionStorage.getItem('ru.hn:back') ?? '/').then(() => { + sessionStorage.removeItem('ru.hn:back'); + }); + } + } + }) + ); + } diff --git a/src/routes/user/+layout.server.ts b/src/routes/user/+layout.server.ts index f3638c7..23887ee 100644 --- a/src/routes/user/+layout.server.ts +++ b/src/routes/user/+layout.server.ts @@ -3,7 +3,6 @@ import {redirect} from '$lib/kit'; import HttpStatus from '$lib/http-status'; export async function load({locals}: ServerLoadEvent): Promise { - // console.log('user/+layout.server.ts:', !locals.user); if (!locals.user) { throw redirect(HttpStatus.MOVED_TEMPORARILY, '/login'); } diff --git a/src/routes/user/admin/+layout.server.ts b/src/routes/user/admin/+layout.server.ts index 8b170ef..05b9b9b 100644 --- a/src/routes/user/admin/+layout.server.ts +++ b/src/routes/user/admin/+layout.server.ts @@ -2,7 +2,8 @@ import {error} from '@sveltejs/kit'; import type {ServerLoadEvent} from '@sveltejs/kit'; import {EUserRanks} from '$lib/types/user-ranks'; -export async function load({locals: {user}, }: ServerLoadEvent): Promise { +export async function load({locals: {user}, parent}: ServerLoadEvent): Promise { + await parent(); if (!user || user.rank <= EUserRanks.User) { throw error(404, 'Page not found'); } diff --git a/src/routes/user/admin/list/+page.svelte b/src/routes/user/admin/list/+page.svelte index 755db09..ff19632 100644 --- a/src/routes/user/admin/list/+page.svelte +++ b/src/routes/user/admin/list/+page.svelte @@ -10,6 +10,7 @@ import type {PageData} from './$types'; import {client} from '$lib/auth/user/client'; + import type {IUser} from '$lib/types/user'; export let data: PageData @@ -39,7 +40,7 @@
    - {user.id} + {user.id} {EUserRanks[user.rank]} @@ -61,9 +62,10 @@ 영구정지 {#if ($client?.user ?? data.user)?.rank >= EUserRanks.Admin} - + + 권한 설정 + {/if} {#if ($client?.user ?? data.user)?.rank >= EUserRanks.Admin}