From 97283c2db76b64cc53ccae8b2e581d87189f9bf5 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 06:09:15 +0900 Subject: [PATCH 1/8] fix: login of admin in database --- packages/server/src/auth/data.ts | 9 ++++++--- packages/server/src/auth/handler/ssu_login.ts | 14 +++----------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/server/src/auth/data.ts b/packages/server/src/auth/data.ts index b5b1ea14..b883883b 100644 --- a/packages/server/src/auth/data.ts +++ b/packages/server/src/auth/data.ts @@ -1,5 +1,5 @@ import type { GetItemInput, UpdateItemInput, UpdateItemOutput } from 'aws-sdk/clients/dynamodb'; -import { ForbiddenError, UnauthorizedError } from '../util/error'; +import { BlockedError, ForbiddenError, UnauthorizedError } from '../util/error'; import { adminId, dynamoDB, TableName } from '../util/database'; import type { AWSError } from 'aws-sdk'; @@ -40,7 +40,8 @@ export const revokeToken = async function ( export const issueToken = async function ( id: string, - token: string + token: string, + isServiceBlocked: boolean ): Promise<{ id: string; expires: number }> { const expires = Date.now() + 3600 * 1000 * 24; const condition = 'attribute_exists(d)'; @@ -66,11 +67,13 @@ export const issueToken = async function ( res = await dynamoDB.updateItem(req).promise(); } catch (e) { if ((e as AWSError).name === 'ConditionalCheckFailedException') { - throw new ForbiddenError('This user cannot login to service'); + throw new BlockedError('This user cannot login to service'); } throw e; } if (res.Attributes.hasOwnProperty('aT') && res.Attributes.aT.S === token) { + if (res.Attributes.iA?.BOOL !== true && isServiceBlocked) + throw new BlockedError('This user cannot login to service'); return { id, expires }; } else { throw new ForbiddenError('Cannot issue token', { id, expires }); diff --git a/packages/server/src/auth/handler/ssu_login.ts b/packages/server/src/auth/handler/ssu_login.ts index d2c9f6e1..0a3883a0 100644 --- a/packages/server/src/auth/handler/ssu_login.ts +++ b/packages/server/src/auth/handler/ssu_login.ts @@ -2,15 +2,9 @@ import https from 'https'; import type { APIGatewayProxyHandler } from 'aws-lambda'; import * as jwt from 'jsonwebtoken'; import { createResponse, JWT_SECRET } from '../../common'; -import { - BlockedError, - errorResponse, - responseAsLockerError, - UnauthorizedError -} from '../../util/error'; +import { errorResponse, responseAsLockerError, UnauthorizedError } from '../../util/error'; import { issueToken } from '../data'; import { queryConfig } from '../../config/data'; -import { adminId } from '../../util/database'; import { getBlockedDepartments } from '../../util/access'; function requestBody(result: string): Promise { @@ -48,13 +42,11 @@ export const ssuLoginHandler: APIGatewayProxyHandler = async (event) => { const id = await obtainId(result); const configs = await queryConfig(); const blockedDepartments = getBlockedDepartments(configs); - if (adminId !== id && blockedDepartments.includes('SERVICE')) { - return errorResponse(new BlockedError('Service unavailable')); - } + const isServiceBlocked = blockedDepartments.includes('SERVICE'); const accessToken = jwt.sign({ aud: id }, JWT_SECRET, { expiresIn: 3600 * 1000 }); - const issued = await issueToken(id, accessToken); + const issued = await issueToken(id, accessToken, isServiceBlocked); const left = Math.floor((issued.expires - Date.now()) / 1000); const res = { success: true, From e81d8be79da5d0b7f34671cf6863d04866f195e1 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 06:09:34 +0900 Subject: [PATCH 2/8] fix: make `/locker/claim` and `/locker/unclaim` throw BlockedError --- packages/server/src/locker/data.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/server/src/locker/data.ts b/packages/server/src/locker/data.ts index 869320ea..dc9c8336 100644 --- a/packages/server/src/locker/data.ts +++ b/packages/server/src/locker/data.ts @@ -6,7 +6,7 @@ import type { UpdateItemOutput } from 'aws-sdk/clients/dynamodb'; import { adminId, dynamoDB, TableName } from '../util/database'; -import { CantClaimError, CantUnclaimError, ForbiddenError, NotFoundError } from '../util/error'; +import { BlockedError, CantClaimError, CantUnclaimError, NotFoundError } from '../util/error'; import type { AWSError } from 'aws-sdk'; export const claimLocker = async function ( @@ -39,7 +39,7 @@ export const claimLocker = async function ( blockedDepartments.map((d) => [`:${d}`, { S: d }]) ); conditionValues[':true'] = { BOOL: true }; - const condition = blockedDepartments.map((d) => `(NOT d = :${d})`).join(' AND '); + const condition = blockedDepartments.map((d) => `NOT d = :${d}`).join(' AND '); const req: UpdateItemInput = { TableName, Key: { type: { S: 'user' }, id: { S: id } }, @@ -62,7 +62,7 @@ export const claimLocker = async function ( res = await dynamoDB.updateItem(req).promise(); } catch (e) { if ((e as AWSError).name === 'ConditionalCheckFailedException') { - throw new ForbiddenError(); + throw new BlockedError(); } throw e; } @@ -86,14 +86,12 @@ export const unclaimLocker = async function ( blockedDepartments.map((d) => [`:${d}`, { S: d }]) ); conditionValues[':true'] = { BOOL: true }; - const condition = blockedDepartments.map((d) => `(NOT d = :${d})`).join(' AND '); + const condition = blockedDepartments.map((d) => `NOT d = :${d}`).join(' AND '); const req: UpdateItemInput = { TableName, Key: { type: { S: 'user' }, id: { S: id } }, UpdateExpression: 'REMOVE #lockerId', - ConditionExpression: `#aT = :token AND attribute_exists(#lockerId)${ - condition ? ` AND ((${condition}) OR iA = true)` : '' - }`, + ConditionExpression: `#aT = :token ${condition ? ` AND ((${condition}) OR iA = :true)` : ''}`, ExpressionAttributeNames: { '#lockerId': 'lockerId', '#aT': 'aT' @@ -109,7 +107,7 @@ export const unclaimLocker = async function ( res = await dynamoDB.updateItem(req).promise(); } catch (e) { if ((e as AWSError).name === 'ConditionalCheckFailedException') { - throw new ForbiddenError(); + throw new BlockedError(); } throw e; } From 971f01b5afdb4354b4d3365cdf267fcfafae1225 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 06:32:37 +0900 Subject: [PATCH 3/8] feat(NavigationShell): add `disableBlock` prop --- .../client/src/components/molecule/NavigationShell.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/client/src/components/molecule/NavigationShell.svelte b/packages/client/src/components/molecule/NavigationShell.svelte index 889376bf..9d4309a6 100644 --- a/packages/client/src/components/molecule/NavigationShell.svelte +++ b/packages/client/src/components/molecule/NavigationShell.svelte @@ -24,6 +24,8 @@ export let collapsable = true; + export let disableBlock = false; + let serviceName = '사물함 예약 시스템'; $: if ($config && $config.success) { @@ -32,7 +34,7 @@ } - + Date: Mon, 12 Sep 2022 06:32:54 +0900 Subject: [PATCH 4/8] fix(index): service status indicator --- packages/client/src/routes/+page.svelte | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/client/src/routes/+page.svelte b/packages/client/src/routes/+page.svelte index 24818894..8410415b 100644 --- a/packages/client/src/routes/+page.svelte +++ b/packages/client/src/routes/+page.svelte @@ -53,6 +53,8 @@ $: errorData = apiResponse && apiResponse.success === false ? apiResponse.error : undefined; + $: serviceConfig = $config && $config.success ? getServiceConfig($config.result) : undefined; + $: if ($config && $config.success && countData) { lockerCount = updateLockerCount($config.result, countData); } @@ -117,7 +119,7 @@ - {#if $config && $config.success && !isActivated($config.result.activateFrom, $config.result.activateTo)} + {#if serviceConfig && !isActivated(serviceConfig.activateFrom, serviceConfig.activateTo)} {:else} From c67b9cef3930b019fe73cca2088001f43ddf1f4b Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 06:33:25 +0900 Subject: [PATCH 5/8] fix(admin): don't show service block modal --- packages/client/src/routes/admin/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/routes/admin/+page.svelte b/packages/client/src/routes/admin/+page.svelte index c45d9079..ac810eff 100644 --- a/packages/client/src/routes/admin/+page.svelte +++ b/packages/client/src/routes/admin/+page.svelte @@ -125,7 +125,7 @@ - +
{#if $user && $user.success}

설정

From 1897de87229ae1788787182b6113c5631573e282 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 06:34:28 +0900 Subject: [PATCH 6/8] feat(Shell): show user reserved lockerId in block modal --- packages/client/src/components/molecule/Shell.svelte | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/molecule/Shell.svelte b/packages/client/src/components/molecule/Shell.svelte index 0179940d..9663f6dc 100644 --- a/packages/client/src/components/molecule/Shell.svelte +++ b/packages/client/src/components/molecule/Shell.svelte @@ -14,6 +14,7 @@ import { getDepartmentConfig, getServiceConfig } from '$lib/api/config'; import { isActivated } from '$lib/utils'; import Info from '../../icons/Info.svelte'; + import { extractLockerInfoFromId } from '$lib/utils.js'; let clazz = ''; export { clazz as class }; @@ -94,9 +95,15 @@
- console.log('hello')} + + {}} secondaryClass='hidden' primaryText='로그아웃' isPrimaryBtnIconRight on:click={() => goto('/logout')}> - 현재 예약 가능한 시간이 아닙니다. +

현재 예약 가능한 시간이 아닙니다.

+ {#if $user && $user.success && $user.result.lockerId} + {@const lockerInfo = extractLockerInfoFromId($user.result.lockerId)} +

`{lockerInfo.floor}층 | {lockerInfo.sectionId}구역 + - {lockerInfo.lockerNum}번

+ {/if}
\ No newline at end of file From b32e8c85842c9e3519cd5769c343e345946912ec Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 06:35:05 +0900 Subject: [PATCH 7/8] chore: 0.10.2 --- package.json | 2 +- packages/client/package.json | 2 +- packages/server/package.json | 2 +- packages/types/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 358378de..92d1c378 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lockerweb", - "version": "0.10.1", + "version": "0.10.2", "description": "SSU IT Collage Locker system.", "private": true, "scripts": { diff --git a/packages/client/package.json b/packages/client/package.json index 63b58640..0b00fc34 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "client", - "version": "0.10.1", + "version": "0.10.2", "scripts": { "dev": "cross-env VITE_BASE_URL=http://localhost:3000 vite dev --port 5002 --host 0.0.0.0", "build": "vite build", diff --git a/packages/server/package.json b/packages/server/package.json index 37e30158..693092fb 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "server", - "version": "0.10.1", + "version": "0.10.2", "description": "Backend Lambda script for lockerweb", "license": "MIT", "scripts": { diff --git a/packages/types/package.json b/packages/types/package.json index 0375230a..c24f2b09 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@types/lockerweb", - "version": "0.10.1", + "version": "0.10.2", "types": "index.d.ts", "license": "MIT", "dependencies": { From 1d2a9948c6de8ef1e7a725eac6136d0e8fc0b55e Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 06:47:06 +0900 Subject: [PATCH 8/8] feat(Shell): add description to lockerId in block modal --- packages/client/src/components/molecule/Shell.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/molecule/Shell.svelte b/packages/client/src/components/molecule/Shell.svelte index 9663f6dc..a4972569 100644 --- a/packages/client/src/components/molecule/Shell.svelte +++ b/packages/client/src/components/molecule/Shell.svelte @@ -102,8 +102,8 @@

현재 예약 가능한 시간이 아닙니다.

{#if $user && $user.success && $user.result.lockerId} {@const lockerInfo = extractLockerInfoFromId($user.result.lockerId)} -

`{lockerInfo.floor}층 | {lockerInfo.sectionId}구역 - - {lockerInfo.lockerNum}번

+

내가 예약한 사물함: {lockerInfo.floor}층 | {lockerInfo.sectionId}구역 + - {lockerInfo.lockerNum}번

{/if}
\ No newline at end of file