diff --git a/@sammo/crypto/src/AES.ts b/@sammo/crypto/src/AES.ts index 948ece4..617713b 100644 --- a/@sammo/crypto/src/AES.ts +++ b/@sammo/crypto/src/AES.ts @@ -1,4 +1,4 @@ -import type { BufferSource } from "./types.js"; +import type { BufferSource } from "@sammo/util"; const subtle = globalThis.crypto.subtle; diff --git a/server/util/LiteHashDRBG.ts b/@sammo/crypto/src/LiteHashDRBG.ts similarity index 96% rename from server/util/LiteHashDRBG.ts rename to @sammo/crypto/src/LiteHashDRBG.ts index 9b26a86..c2540f8 100644 --- a/server/util/LiteHashDRBG.ts +++ b/@sammo/crypto/src/LiteHashDRBG.ts @@ -1,9 +1,9 @@ -import type { RNG } from "./RNG.js"; +import type { RNG } from "../../../server/util/RNG.js"; -import { sha512 } from './sha2.js'; +import { sha512 } from '../../../server/util/sha2.js'; -import { convertBytesLikeToUint8Array } from "./convertBytesLikeToUint8Array.js"; -import type { BytesLike } from "./BytesLike.js"; +import { convertBytesLikeToUint8Array } from "@sammo/util/convertBytesLikeToUint8Array.js"; +import type { BytesLike } from "../../../server/util/BytesLike.js"; import { delay } from "./delay.js"; const maxRngSupportBit = 53; diff --git a/@sammo/crypto/src/index.ts b/@sammo/crypto/src/index.ts index 7e47e2d..38c3534 100644 --- a/@sammo/crypto/src/index.ts +++ b/@sammo/crypto/src/index.ts @@ -103,4 +103,6 @@ export * as RawTypes from './RawTypes.js'; export * from './utils.js'; export * from './types.js'; -export { TypeLength } from './TypeLength.js'; \ No newline at end of file +export { TypeLength } from './TypeLength.js'; + +export * from "./LiteHashDRBG.js" \ No newline at end of file diff --git a/@sammo/crypto/src/types.ts b/@sammo/crypto/src/types.ts index 53bdab5..609c844 100644 --- a/@sammo/crypto/src/types.ts +++ b/@sammo/crypto/src/types.ts @@ -1,4 +1,3 @@ -export type BufferSource = ArrayBufferView | ArrayBuffer | SharedArrayBuffer; export function isBufferSource(obj: unknown): obj is BufferSource { if (obj instanceof ArrayBuffer){ diff --git a/@sammo/gateway/src/api/Login/LoginByID.ts b/@sammo/gateway/src/api/Login/LoginByID.ts index a9c99bf..7a476e2 100644 --- a/@sammo/gateway/src/api/Login/LoginByID.ts +++ b/@sammo/gateway/src/api/Login/LoginByID.ts @@ -3,7 +3,7 @@ import { StartSession } from "@sammo/server_util"; import { POST, type APIReturnType } from "@strpc/express"; import { declProcDecorators } from "@strpc/express/proc_decorator"; import { z } from "zod"; -import { loginCtxSessionKey, type GatewayLoginCtx } from "../../procDecorator/ReqGatewayLogin.js"; +import { loginCtxSessionKey, type GatewayLoginCtx } from "@/procDecorator/ReqGatewayLogin.js"; import { delay } from "@sammo/util"; type BaseAPI = typeof structure.Login.LoginByID; diff --git a/@sammo/gateway/src/api/Login/index.ts b/@sammo/gateway/src/api/Login/index.ts index 4fc5a10..38bee8c 100644 --- a/@sammo/gateway/src/api/Login/index.ts +++ b/@sammo/gateway/src/api/Login/index.ts @@ -1,5 +1,5 @@ -import type { structure } from "../../../apiStructure/sammoGatewayAPI.js"; -import type { APINamespaceType } from "../../defs.js"; +import type { structure } from "@sammo/api_def/gateway"; +import type { APINamespaceType } from "@strpc/express"; import { LoginByID } from "./LoginByID.js"; import { LoginByToken } from "./LoginByToken.js"; import { ReqNonce } from "./ReqNonce.js"; diff --git a/@sammo/util/package.json b/@sammo/util/package.json index f3794f8..afbfbcc 100644 --- a/@sammo/util/package.json +++ b/@sammo/util/package.json @@ -6,11 +6,18 @@ "scripts": { "build": "tsc --build" }, + "exports": { + ".": "./dist/index.js", + "./converter": "./dist/converter.js", + "./datetime": "./dist/datetime.js", + "./korean": "./dist/korean.js" + }, "type": "module", "keywords": [], "author": "", "license": "MIT", "devDependencies": { + "@types/node": "^20.6.3", "lodash-es": "^4.17.21" }, "peerDependencies": { diff --git a/server/util/combineArray.ts b/@sammo/util/src/converter/combineArray.ts similarity index 100% rename from server/util/combineArray.ts rename to @sammo/util/src/converter/combineArray.ts diff --git a/server/util/combineObject.ts b/@sammo/util/src/converter/combineObject.ts similarity index 100% rename from server/util/combineObject.ts rename to @sammo/util/src/converter/combineObject.ts diff --git a/server/util/convertBytesLikeToArrayBuffer.ts b/@sammo/util/src/converter/convertBytesLikeToArrayBuffer.ts similarity index 100% rename from server/util/convertBytesLikeToArrayBuffer.ts rename to @sammo/util/src/converter/convertBytesLikeToArrayBuffer.ts diff --git a/server/util/convertBytesLikeToUint8Array.ts b/@sammo/util/src/converter/convertBytesLikeToUint8Array.ts similarity index 100% rename from server/util/convertBytesLikeToUint8Array.ts rename to @sammo/util/src/converter/convertBytesLikeToUint8Array.ts diff --git a/server/util/convertIDArray.ts b/@sammo/util/src/converter/convertIDArray.ts similarity index 80% rename from server/util/convertIDArray.ts rename to @sammo/util/src/converter/convertIDArray.ts index 972ff2a..df8b42b 100644 --- a/server/util/convertIDArray.ts +++ b/@sammo/util/src/converter/convertIDArray.ts @@ -1,4 +1,4 @@ -import type { IDItem } from './defs.js'; +import type { IDItem } from "../types.js"; export function convertIDArray(array: Iterable): IDItem[] { const result: IDItem[] = []; @@ -6,4 +6,4 @@ export function convertIDArray(array: Iterable): IDItem[] { result.push({ id }); } return result; -} \ No newline at end of file +} diff --git a/server/util/convertIterableToMap.ts b/@sammo/util/src/converter/convertIterableToMap.ts similarity index 100% rename from server/util/convertIterableToMap.ts rename to @sammo/util/src/converter/convertIterableToMap.ts diff --git a/@sammo/util/src/converter/index.ts b/@sammo/util/src/converter/index.ts new file mode 100644 index 0000000..cc667df --- /dev/null +++ b/@sammo/util/src/converter/index.ts @@ -0,0 +1,6 @@ +export * from "./combineObject.js"; +export * from "./combineArray.js"; +export * from "./convertBytesLikeToArrayBuffer.js"; +export * from "./convertBytesLikeToUint8Array.js"; +export * from "./convertIDArray.js"; +export * from "./convertIterableToMap.js" \ No newline at end of file diff --git a/server/util/formatTime.ts b/@sammo/util/src/datetime/formatTime.ts similarity index 100% rename from server/util/formatTime.ts rename to @sammo/util/src/datetime/formatTime.ts diff --git a/@sammo/util/src/datetime/index.ts b/@sammo/util/src/datetime/index.ts new file mode 100644 index 0000000..da6aacc --- /dev/null +++ b/@sammo/util/src/datetime/index.ts @@ -0,0 +1,3 @@ +export * from "./formatTime.js"; +export * from "./parseTime.js"; +export * from "./parseYearMonth.js"; \ No newline at end of file diff --git a/server/util/parseTime.ts b/@sammo/util/src/datetime/parseTime.ts similarity index 100% rename from server/util/parseTime.ts rename to @sammo/util/src/datetime/parseTime.ts diff --git a/server/util/parseYearMonth.ts b/@sammo/util/src/datetime/parseYearMonth.ts similarity index 100% rename from server/util/parseYearMonth.ts rename to @sammo/util/src/datetime/parseYearMonth.ts diff --git a/@sammo/util/src/index.ts b/@sammo/util/src/index.ts index 1905058..2e62dc1 100644 --- a/@sammo/util/src/index.ts +++ b/@sammo/util/src/index.ts @@ -4,6 +4,12 @@ export * from "./error.js" export * from "./unwrap.js" export * from "./types.js" +export * as converter from "./converter/index.js" +export * as datetime from "./datetime/index.js" +export * as korean from "./korean/index.js" + +import type { WrappedBuffer } from "./types.js" + export function isEmail(addr: string): boolean { return String(addr) .toLowerCase() @@ -23,12 +29,6 @@ export function calcBase64Len(length: number) { return ((4 * length / 3) + 3) & ~3; } -/** Buffer이지만 ts에서 타입 구분 편의를 제공 */ -export interface WrappedBuffer extends Buffer { - /** 타입구분자. 항상 undefined일 것이다 */ - _w_type?: string; -} - /** ArrayBuffer,Uint8Array,Buffer를 WrappedBuffer로 변환 */ export function wrapBuffer(buffer: BufferSource): T { @@ -65,15 +65,6 @@ export function delay(time: number, result?: T): Promise = string & { - /** 타입구분자. 항상 undefined일 것이다 */ - _b_type?: T; -} - export function base64FromWrappedBuffer(buffer: T | ArrayBuffer | Uint8Array): Base64String { return Buffer.from(buffer).toString('base64'); } @@ -81,3 +72,17 @@ export function base64FromWrappedBuffer(buffer: T | Arr export function wrappedBufferFromBase64(base64: Base64String): T { return Buffer.from(base64, 'base64') as T; } + + +export function isBufferSource(obj: unknown): obj is BufferSource { + if (obj instanceof ArrayBuffer){ + return true; + } + if('SharedArrayBuffer' in globalThis && obj instanceof SharedArrayBuffer){ + return true; + } + if (ArrayBuffer.isView(obj)){ + return true; + } + return false; +} \ No newline at end of file diff --git a/server/util/automata초성.ts b/@sammo/util/src/korean/automata초성.ts similarity index 100% rename from server/util/automata초성.ts rename to @sammo/util/src/korean/automata초성.ts diff --git a/server/util/convertSearch초성.ts b/@sammo/util/src/korean/convertSearch초성.ts similarity index 100% rename from server/util/convertSearch초성.ts rename to @sammo/util/src/korean/convertSearch초성.ts diff --git a/server/util/filter초성.ts b/@sammo/util/src/korean/filter초성.ts similarity index 100% rename from server/util/filter초성.ts rename to @sammo/util/src/korean/filter초성.ts diff --git a/server/util/filter초성withAlphabet.ts b/@sammo/util/src/korean/filter초성withAlphabet.ts similarity index 100% rename from server/util/filter초성withAlphabet.ts rename to @sammo/util/src/korean/filter초성withAlphabet.ts diff --git a/@sammo/util/src/korean/index.ts b/@sammo/util/src/korean/index.ts new file mode 100644 index 0000000..43526e8 --- /dev/null +++ b/@sammo/util/src/korean/index.ts @@ -0,0 +1,4 @@ +export * from "./automata초성.js"; +export * from "./convertSearch초성.js" +export * from "./filter초성.js"; +export * from "./filter초성withAlphabet.js"; \ No newline at end of file diff --git a/@sammo/util/src/types.ts b/@sammo/util/src/types.ts index 7b5ecba..997f463 100644 --- a/@sammo/util/src/types.ts +++ b/@sammo/util/src/types.ts @@ -1 +1,28 @@ -export type Nullable = T | null | undefined; \ No newline at end of file +export type Nullable = T | null | undefined; + +export declare type ValuesOf = T[keyof T]; + +export type IDItem = { + id: T; +}; + + + +/** Buffer이지만 ts에서 타입 구분 편의를 제공 */ +export interface WrappedBuffer extends Buffer { + /** 타입구분자. 항상 undefined일 것이다 */ + _w_type?: string; +} + +export type BufferSource = ArrayBufferView | ArrayBuffer | SharedArrayBuffer; +export type BytesLike = BufferSource | string; + + +/** + * base64 string에 내부 타입으로 WrappedBuffer를 보관한 형태 + */ +// eslint-disable-next-line @typescript-eslint/ban-types +export type Base64String = string & { + /** 타입구분자. 항상 undefined일 것이다 */ + _b_type?: T; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7066df1..657aa97 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -272,6 +272,9 @@ importers: '@sammo/util': devDependencies: + '@types/node': + specifier: ^20.6.3 + version: 20.6.3 lodash-es: specifier: ^4.17.21 version: 4.17.21 diff --git a/server/SecureToken.ts b/server/SecureToken.ts deleted file mode 100644 index ccd1bc1..0000000 --- a/server/SecureToken.ts +++ /dev/null @@ -1,208 +0,0 @@ - -import 'dotenv/config'; -import { AES_GCM_Decrypt, AES_GCM_Encrypt } from "./util/aes.js"; -import { webcrypto } from "crypto"; -import { Buffer } from "buffer"; -import { sha512 } from "./util/sha2.js"; -import { BSON } from "bson"; - -/** - * Preshared Token Secret을 이용한 AES256-GCM 토큰 - * key, iv = SHA512(presharedSecret + nonce) 으로 생성 - */ - -export type SecureEncryptedToken = { - nonce: string; // [key, iv] = SHA512(presharedSecret + nonce) - encrypted: 1; - type: string; // aad[0] - validUntil: string; // aad[1] - payload: string; //BASE64(AES(BSON(aad),BSON(payload))) -} - -export type SecurePlaintextToken = { - nonce: string; // [key, iv] = SHA512(presharedSecret + nonce) - encrypted: 0; - type: string; // aad[0] - validUntil: string; // aad[1] - payload: string; // JSON => aad[2] - tag: string; //BASE64(AES(BSON(aad),null))) -} - -export type SecureToken = SecureEncryptedToken | SecurePlaintextToken; - -const staticPresharedTokenSecret: string | undefined = process.env.PRESHARED_TOKEN_SECRET; - -export async function generateSecureEncryptedToken(validUntil: Date, type: string, payload: T, presharedTokenSecret?: string): Promise { - if (!presharedTokenSecret) { - if (!staticPresharedTokenSecret) { - throw new Error("PRESHARED_TOKEN_SECRET is not set"); - } - presharedTokenSecret = staticPresharedTokenSecret; - } - - const secretLength = Buffer.byteLength(presharedTokenSecret, 'utf8'); - const secretBuffer = Buffer.alloc(secretLength + 16); - secretBuffer.write(presharedTokenSecret, 0, secretLength, 'utf8'); - - //secretBuffer에서 Buffer를 바로 준비해도 되지만, 혹시모를 안전상의 이유로 별도로 할당하고 복사 - const nonce = Buffer.from(webcrypto.getRandomValues(new Uint8Array(16))); - secretBuffer.set(nonce, secretLength); - - const keyBuffer = Buffer.from(await sha512(secretBuffer)); - - const key = new Uint8Array(keyBuffer.buffer, 0, 32); - const iv = new Uint8Array(keyBuffer.buffer, 32, 12); - - const validUntilText = validUntil.toISOString(); - - const aad = [type, validUntilText]; - - const aadRaw = BSON.serialize(aad); - const payloadRaw = BSON.serialize(payload); - - const ciphertext = Buffer.from(await AES_GCM_Encrypt(key, iv, payloadRaw, aadRaw)); - - return { - nonce: nonce.toString('base64'), - encrypted: 1, - type, - validUntil: validUntilText, - payload: ciphertext.toString('base64'), - } -} - -export async function parseSecureEncryptedToken(secureToken: SecureEncryptedToken, presharedTokenSecret?: string): Promise { - const now = new Date(); - const validUntil = new Date(secureToken.validUntil); - if (now > validUntil) { - throw new Error("token expired"); - } - - if(!secureToken.encrypted) { - throw new Error("token is not encrypted"); - } - - if (!presharedTokenSecret) { - if (!staticPresharedTokenSecret) { - throw new Error("PRESHARED_TOKEN_SECRET is not set"); - } - presharedTokenSecret = staticPresharedTokenSecret; - } - - const secretLength = Buffer.byteLength(presharedTokenSecret, 'utf8'); - const secretBuffer = Buffer.alloc(secretLength + 16); - secretBuffer.write(presharedTokenSecret, 0, secretLength, 'utf8'); - - const nonce = Buffer.from(secureToken.nonce, 'base64'); - secretBuffer.set(nonce, secretLength); - - const keyBuffer = Buffer.from(await sha512(secretBuffer)); - const key = new Uint8Array(keyBuffer.buffer, 0, 32); - const iv = new Uint8Array(keyBuffer.buffer, 32, 12); - - const aad = [secureToken.type, secureToken.validUntil]; - - const aadRaw = BSON.serialize(aad); - const payloadCiphertext = Buffer.from(secureToken.payload, 'base64'); - - const payloadRaw = new Uint8Array(await AES_GCM_Decrypt(key, iv, payloadCiphertext, aadRaw)); - const payload = BSON.deserialize(payloadRaw); - - return payload as T; -} - -export async function generateSecurePlaintextToken(validUntil: Date, type: string, payload: T, presharedTokenSecret?: string): Promise { - if (!presharedTokenSecret) { - if (!staticPresharedTokenSecret) { - throw new Error("PRESHARED_TOKEN_SECRET is not set"); - } - presharedTokenSecret = staticPresharedTokenSecret; - } - - const secretLength = Buffer.byteLength(presharedTokenSecret, 'utf8'); - const secretBuffer = Buffer.alloc(secretLength + 16); - secretBuffer.write(presharedTokenSecret, 0, secretLength, 'utf8'); - - //secretBuffer에서 Buffer를 바로 준비해도 되지만, 혹시모를 안전상의 이유로 별도로 할당하고 복사 - const nonce = Buffer.from(webcrypto.getRandomValues(new Uint8Array(16))); - secretBuffer.set(nonce, secretLength); - - const keyBuffer = Buffer.from(await sha512(secretBuffer)); - - const key = new Uint8Array(keyBuffer.buffer, 0, 32); - const iv = new Uint8Array(keyBuffer.buffer, 32, 12); - - const validUntilText = validUntil.toISOString(); - const jsonPayload = JSON.stringify(payload); - - const aad = [type, validUntilText, jsonPayload]; - const aadRaw = BSON.serialize(aad); - - const dummyPayload = new ArrayBuffer(0); - - const tag = Buffer.from(await AES_GCM_Encrypt(key, iv, dummyPayload, aadRaw)); - - return { - nonce: nonce.toString('base64'), - encrypted: 0, - type, - validUntil: validUntilText, - payload: jsonPayload, - tag: tag.toString('base64'), - } -} - -export async function parseSecurePlaintextToken(secureToken: SecurePlaintextToken, presharedTokenSecret?: string): Promise { - const now = new Date(); - const validUntil = new Date(secureToken.validUntil); - if (now > validUntil) { - throw new Error("token expired"); - } - - if (!presharedTokenSecret) { - if (!staticPresharedTokenSecret) { - throw new Error("PRESHARED_TOKEN_SECRET is not set"); - } - presharedTokenSecret = staticPresharedTokenSecret; - } - - if (secureToken.encrypted) { - throw new Error("token is encrypted"); - } - - const secretLength = Buffer.byteLength(presharedTokenSecret, 'utf8'); - const secretBuffer = Buffer.alloc(secretLength + 16); - secretBuffer.write(presharedTokenSecret, 0, secretLength, 'utf8'); - - const nonce = Buffer.from(secureToken.nonce, 'base64'); - secretBuffer.set(nonce, secretLength); - - const keyBuffer = Buffer.from(await sha512(secretBuffer)); - const key = new Uint8Array(keyBuffer.buffer, 0, 32); - const iv = new Uint8Array(keyBuffer.buffer, 32, 12); - - const aad = [secureToken.type, secureToken.validUntil, secureToken.payload]; - const aadRaw = BSON.serialize(aad); - - const tag = Buffer.from(secureToken.tag, 'base64'); - - await AES_GCM_Decrypt(key, iv, tag, aadRaw); - - return JSON.parse(secureToken.payload); -} - -export async function generateSecureToken(encrypted: boolean, validUntil: Date, type: string, payload: T, presharedTokenSecret?: string): Promise { - if (encrypted) { - return await generateSecureEncryptedToken(validUntil, type, payload, presharedTokenSecret); - } else { - return await generateSecurePlaintextToken(validUntil, type, payload, presharedTokenSecret); - } -} - -export async function parseSecureToken(secureToken: SecureToken, presharedTokenSecret?: string): Promise { - if (secureToken.encrypted) { - return await parseSecureEncryptedToken(secureToken, presharedTokenSecret); - } else { - return await parseSecurePlaintextToken(secureToken, presharedTokenSecret); - } -} \ No newline at end of file diff --git a/server/api/GatewayAPI/GetGameLoginToken.ts b/server/api/GatewayAPI/GetGameLoginToken.ts deleted file mode 100644 index 4102adb..0000000 --- a/server/api/GatewayAPI/GetGameLoginToken.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { GET } from "../defs.js"; -import type { structure } from "../../apiStructure/sammoGatewayAPI.js"; -import type { ExtractError, ExtractQuery, ExtractResponse } from "../../apiStructure/defs.js"; -import { StartSession } from "../../ProcDecorator/StartSession.js"; -import { declProcDecorators } from "../../ProcDecorator/base.js"; -import { ReqLogin } from "../../ProcDecorator/ReqLogin.js"; - -type BaseAPI = typeof structure.GetGameLoginToken; -type RType = ExtractResponse; -type EType = ExtractError; -type QType = ExtractQuery; - -export const GameLoginTokenSessionKey = "GameLoginToken"; - -export const GetGameLoginToken = GET(undefined)(declProcDecorators( - StartSession, - ReqLogin, -))( - async (query, ctx) => { - return { - result: false, - reason: 'NotYetImplemented', - }; - } -); \ No newline at end of file diff --git a/server/api/GatewayAPI/Install/index.ts b/server/api/GatewayAPI/Install/index.ts deleted file mode 100644 index e69de29..0000000 diff --git a/server/api/GatewayAPI/Install/initAdmin.ts b/server/api/GatewayAPI/Install/initAdmin.ts deleted file mode 100644 index e69de29..0000000 diff --git a/server/api/GatewayAPI/Login/ChangePassword.ts b/server/api/GatewayAPI/Login/ChangePassword.ts deleted file mode 100644 index 333e0d0..0000000 --- a/server/api/GatewayAPI/Login/ChangePassword.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { GET } from "../../defs.js"; -import type { structure } from "../../../apiStructure/sammoGatewayAPI.js"; -import type { ExtractError, ExtractQuery, ExtractResponse } from "../../../apiStructure/defs.js"; -import { declProcDecorators } from "../../../ProcDecorator/base.js"; -import { ReqLogin } from "../../../ProcDecorator/ReqLogin.js"; -import { StartSession } from "../../../ProcDecorator/StartSession.js"; - -type BaseAPI = typeof structure.Login.ReqNonce; -type RType = ExtractResponse; -type EType = ExtractError; -type QType = ExtractQuery; -const argValidator = undefined; - -export const ReqNonce = GET(argValidator)(declProcDecorators( - StartSession, - ReqLogin, -))( - (query, ctx) => { - throw new Error("Method not implemented."); - } -); \ No newline at end of file diff --git a/server/api/GatewayAPI/Login/LoginByID.ts b/server/api/GatewayAPI/Login/LoginByID.ts deleted file mode 100644 index 05cb719..0000000 --- a/server/api/GatewayAPI/Login/LoginByID.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { POST } from "../../defs.js"; -import type { structure } from "../../../apiStructure/sammoGatewayAPI.js"; -import type { ExtractError, ExtractQuery, ExtractResponse } from "../../../apiStructure/defs.js"; -import { StartSession } from "../../../ProcDecorator/StartSession.js"; -import { delay } from "../../../util/delay.js"; -import { declProcDecorators } from "../../../ProcDecorator/base.js"; -import { z } from "zod"; -import { type LoginCtx, loginCtxSessionKey } from "../../../ProcDecorator/ReqLogin.js"; - -type BaseAPI = typeof structure.Login.LoginByID; -type RType = ExtractResponse; -type EType = ExtractError; -type QType = ExtractQuery; -const LoginByIDReq = z.object({ - id: z.string(), - password: z.string(), -}) satisfies z.ZodType - -export const LoginByID = POST(LoginByIDReq)(declProcDecorators( - StartSession, -))( - async (query, ctx, req, res) => { - const id = query.id; - const password = query.password; - - //TODO: DB에서 뭔가 가져와야 함 - await delay(1); - - if (Math.random() < 0.3) { - return { - result: false, - reason: "로그인 실패", - reqOTP: false, - } - } - - if (Math.random() < 0.5) { - return { - result: false, - reason: "OTP 인증 필요", - reqOTP: true, - } - } - - const userID = 1; - const userName = "test"; - const userLevel = 1; - const nextToken: [number, string] = [1, "1234567890"]; - const loginCtx: LoginCtx = { - userID, - userName, - userLevel, - allowServerAction: new Set(), - loginDate: new Date(), - } - - ctx.session.setItem(loginCtxSessionKey, loginCtx); - - - return { - result: true, - nextToken, - } - }); \ No newline at end of file diff --git a/server/api/GatewayAPI/Login/LoginByToken.ts b/server/api/GatewayAPI/Login/LoginByToken.ts deleted file mode 100644 index 8dcd353..0000000 --- a/server/api/GatewayAPI/Login/LoginByToken.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { POST } from "../../defs.js"; -import type { structure } from "../../../apiStructure/sammoGatewayAPI.js"; -import type { ExtractError, ExtractQuery, ExtractResponse } from "../../../apiStructure/defs.js"; -import { StartSession } from "../../../ProcDecorator/StartSession.js"; -import { delay } from "../../../util/delay.js"; -import { declProcDecorators } from "../../../ProcDecorator/base.js"; -import { type LoginCtx, loginCtxSessionKey } from "../../../ProcDecorator/ReqLogin.js"; -import { z } from "zod"; -type BaseAPI = typeof structure.Login.LoginByToken; -type RType = ExtractResponse; -type EType = ExtractError; -type QType = ExtractQuery; - -const LoginByTokenReq = z.object({ - token_id: z.number(), - hashedToken: z.string(), -}) satisfies z.ZodType - -export const LoginByToken = POST(LoginByTokenReq)(declProcDecorators( - StartSession, -)) - (async (query, ctx) => { - query.hashedToken; - ctx.session.clear(); - - await delay(1); - //무언가 로그인 - //TODO: DB는 어디서 들고옴? - - const userID = 1; - const userName = "test"; - const userLevel = 1; - const nextToken: [number, string] = [1, "1234567890"]; - const loginCtx: LoginCtx = { - userID, - userName, - userLevel, - allowServerAction: new Set(), - loginDate: new Date(), - } - - ctx.session.setItem(loginCtxSessionKey, loginCtx); - - - //throw new Error("Method not implemented."); - return { - result: true, - nextToken, - } - - }); \ No newline at end of file diff --git a/server/api/GatewayAPI/Login/ReqNonce.ts b/server/api/GatewayAPI/Login/ReqNonce.ts deleted file mode 100644 index 58115ab..0000000 --- a/server/api/GatewayAPI/Login/ReqNonce.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { GET } from "../../defs.js"; -import type { structure } from "../../../apiStructure/sammoGatewayAPI.js"; -import type { ExtractError, ExtractQuery, ExtractResponse } from "../../../apiStructure/defs.js"; -import { StartSession } from "../../../ProcDecorator/StartSession.js"; -import { declProcDecorators } from "../../../ProcDecorator/base.js"; - -type BaseAPI = typeof structure.Login.ReqNonce; -type RType = ExtractResponse; -type EType = ExtractError; -type QType = ExtractQuery; - -export const ReqNonceSessionKey = 'loginNonce'; - -export const ReqNonce = GET(undefined)(declProcDecorators( - StartSession, -))( - async (query, ctx) => { - const nonce = ctx.session.getItem(ReqNonceSessionKey); - if (nonce !== undefined) { - return { - loginNonce: nonce, - result: true, - } - } - - const newNonce = "1234567890"; - ctx.session.setItem(ReqNonceSessionKey, newNonce); - return { - loginNonce: newNonce, - result: true, - } - } -) \ No newline at end of file diff --git a/server/api/GatewayAPI/Login/index.ts b/server/api/GatewayAPI/Login/index.ts deleted file mode 100644 index 4fc5a10..0000000 --- a/server/api/GatewayAPI/Login/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { structure } from "../../../apiStructure/sammoGatewayAPI.js"; -import type { APINamespaceType } from "../../defs.js"; -import { LoginByID } from "./LoginByID.js"; -import { LoginByToken } from "./LoginByToken.js"; -import { ReqNonce } from "./ReqNonce.js"; -import { test } from "./test.js"; - -export const Login = { - LoginByID, - LoginByToken, - ReqNonce, - test, -} satisfies APINamespaceType; \ No newline at end of file diff --git a/server/api/GatewayAPI/Login/test.ts b/server/api/GatewayAPI/Login/test.ts deleted file mode 100644 index ef2e835..0000000 --- a/server/api/GatewayAPI/Login/test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { GET } from "../../defs.js"; -import type { structure } from "../../../apiStructure/sammoGatewayAPI.js"; -import type { ExtractError, ExtractQuery, ExtractResponse } from "../../../apiStructure/defs.js"; -import { EmptyProcDecorator } from "../../../ProcDecorator/base.js"; - -type BaseAPI = typeof structure.Login.test; -type RType = ExtractResponse; -type EType = ExtractError; -type QType = ExtractQuery; - -export const test = GET(undefined)(EmptyProcDecorator)( - () => { - throw new Error("Method not implemented."); - } -); \ No newline at end of file diff --git a/server/api/gatewayAPI.ts b/server/api/gatewayAPI.ts deleted file mode 100644 index e75767a..0000000 --- a/server/api/gatewayAPI.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { structure } from "../apiStructure/sammoGatewayAPI.js"; -import type { APINamespaceType } from "./defs.js"; -import { GetGameLoginToken } from "./GatewayAPI/GetGameLoginToken.js"; -import { Login } from "./GatewayAPI/Login/index.js"; - -export const sammoGatewayAPI = { - Login, - GetGameLoginToken -} satisfies APINamespaceType; \ No newline at end of file diff --git a/server/apiStructure/sammoGatewayAPI.ts b/server/apiStructure/sammoGatewayAPI.ts deleted file mode 100644 index db37951..0000000 --- a/server/apiStructure/sammoGatewayAPI.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { type DefAPINamespace, GET, POST } from "./defs.js"; - -export type LoginResponse = { - result: true, - nextToken: [number, string] | undefined, -} - -export type LoginFailed = { - result: false, - reqOTP: boolean, - reason: string, -} - - -export type AutoLoginNonceResponse = { - result: true, - loginNonce: string, -}; - -export type AutoLoginResponse = { - result: true, - nextToken: [number, string] | undefined, -} - - -export type AutoLoginFailed = { - result: false, - silent: boolean, - reason: string, -} - -/** @internal */ -export const structure = { - Login: { - LoginByID: POST<{ - id: string, - password: string, - }, LoginResponse, LoginFailed>(), - LoginByToken: POST<{ - hashedToken: string, - token_id: number, - }, AutoLoginResponse, AutoLoginFailed>(), - ReqNonce: GET(), - test: GET<{result: true, hello:'world'}>(), - }, - GetGameLoginToken: GET<{ - result: true, - gameLoginToken: string, - userID: number, - }>(), - -} satisfies DefAPINamespace; \ No newline at end of file diff --git a/server/util/APIPathGen.d.ts b/server/util/APIPathGen.d.ts deleted file mode 100644 index de2b18a..0000000 --- a/server/util/APIPathGen.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -export function APIPathGen( - obj: T, - callback: (path: string[], tail: V, pathParam?: Record) => unknown, - pathParam?: Record -): T; - -export function StrVar(paramKey: string): (next: NextCall) => { - [v in PathType]: NextCall -}; - -export function NumVar(paramKey: string, next: NextCall): { - [v: number]: NextCall -}; - -/* -const apiPath = { - SomePath: someFunc, - User: StrVar<'a'|'b'>('name')({ - Update: someFunc, - Delete: someFunc, - }), - NationInfo: NumVar('id', { - show: someFunc - }) -} -*/ \ No newline at end of file diff --git a/server/util/APIPathGen.js b/server/util/APIPathGen.js deleted file mode 100644 index 95093de..0000000 --- a/server/util/APIPathGen.js +++ /dev/null @@ -1,68 +0,0 @@ -export function APIPathGen(obj, callback, path, pathParams) { - return new Proxy(obj, { - get(target, key) { - let nextPath; - if (path === undefined) { - nextPath = [key.toString()]; - } - else { - nextPath = [...path, key.toString()]; - } - - if (pathParams !== undefined) { - pathParams = { ...pathParams }; - } - - const varType = target.__nextVarType; - let varKey = target.__nextVarKey; - let next; - if (varType !== undefined && varKey !== undefined) { - if(varType == 'number'){ - if(key != Number(key)){ - throw `${key} is not ${varType}`; - } - key = Number(key); - } - else if ((typeof key) !== varType) { - throw `${key} is not ${varType}, but ${typeof key}`; - } - if(pathParams === undefined){ - pathParams = {} - } - pathParams[varKey] = key; - nextPath.pop(); - next = target.next; - } - else if (key in target) { - next = target[key]; - } - else { - throw `${nextPath} is not exists`; - } - - if (typeof (next) === 'function') { - return callback(nextPath, next, pathParams); - } - return APIPathGen(next, callback, nextPath, pathParams); - } - }) -} - -//generic 인자로 '자동'을 주려면 생략해야하므로 2단 호출 -export function StrVar(key) { - return (next) => { - return { - __nextVarType: 'string', - __nextVarKey: key, - next - } - } -} - -export function NumVar(key, next) { - return { - __nextVarType: 'number', - __nextVarKey: key, - next - } -} \ No newline at end of file diff --git a/server/util/BytesLike.ts b/server/util/BytesLike.ts index abcd557..e69de29 100644 --- a/server/util/BytesLike.ts +++ b/server/util/BytesLike.ts @@ -1,2 +0,0 @@ -export type Bytes = ArrayBuffer | DataView | Uint8Array; -export type BytesLike = Bytes | string; \ No newline at end of file diff --git a/server/util/Nullable.ts b/server/util/Nullable.ts deleted file mode 100644 index 164a705..0000000 --- a/server/util/Nullable.ts +++ /dev/null @@ -1 +0,0 @@ -export type Nullable = T | null | undefined; diff --git a/server/util/defs.ts b/server/util/defs.ts index ffd217c..e69de29 100644 --- a/server/util/defs.ts +++ b/server/util/defs.ts @@ -1,5 +0,0 @@ -export declare type ValuesOf = T[keyof T]; - -export type IDItem = { - id: T; -}; \ No newline at end of file diff --git a/server/util/delay.ts b/server/util/delay.ts deleted file mode 100644 index aabec78..0000000 --- a/server/util/delay.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function delay(ms: number): Promise { - return new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, ms); - }); -} \ No newline at end of file diff --git a/server/util/unwrap.ts b/server/util/unwrap.ts deleted file mode 100644 index cac7a63..0000000 --- a/server/util/unwrap.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Nullable } from './Nullable.js'; -import { NotNullExpected } from "./NotNullExpected.js"; - -export function unwrap(result: Nullable): T { - if (result === null || result === undefined) { - throw new NotNullExpected(); - } - return result; -} diff --git a/server/util/unwrap_any.ts b/server/util/unwrap_any.ts deleted file mode 100644 index 683e614..0000000 --- a/server/util/unwrap_any.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { Nullable } from ".//Nullable.js"; -import { NotNullExpected } from ".//NotNullExpected.js"; - - -export function unwrap_any(result: Nullable): T { - if (result === null || result === undefined) { - throw new NotNullExpected(); - } - return result as T; -} diff --git a/server/util/unwrap_err.ts b/server/util/unwrap_err.ts deleted file mode 100644 index 7e0fe0e..0000000 --- a/server/util/unwrap_err.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { Nullable } from ".//Nullable.js"; - -type ErrType = { new(msg?: string): T } - -export function unwrap_err(result: Nullable, errType: ErrType, errMsg?: string): T { - if (result === null || result === undefined) { - throw new errType(errMsg); - } - return result; -}