Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 778 auth 관련 api 무조건 200 리턴 버그 #780

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"jest": true
},
"root": true,
"extends": ["airbnb-base", "plugin:@typescript-eslint/recommended"],
"extends": ["airbnb-base", "plugin:@typescript-eslint/recommended", "prettier"],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "import"],
"parserOptions": {
Expand Down
19 changes: 10 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@ name: Test
on:
pull_request:

defaults:
run:
shell: bash

jobs:
test:
name: Test PR
runs-on: ubuntu-latest
environment: development

steps:
- uses: reviewdog/action-setup@v1

- name: Checkout
uses: actions/checkout@v3

Expand Down Expand Up @@ -40,12 +46,7 @@ jobs:
pnpm install --frozen-lockfile
pnpm --filter='@jiphyeonjeon-42/contracts' build

- if: always()
name: check types (backend)
working-directory: backend
run: pnpm check

- if: always()
name: check types (contracts)
working-directory: contracts
run: pnpm check
- name: check types
if: always()
run: |
pnpm -r --no-bail --parallel run check | sed -r 's|(.*)( check: )(.*)|\1/\3|'
7 changes: 7 additions & 0 deletions .prettierrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
semi: true
singleQuote: true
useTabs: false
tabWidth: 2
trailingComma: all
printWidth: 100
arrowParens: always
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ FROM node:18-alpine as pnpm-installed
# https://github.com/pnpm/pnpm/issues/4495#issuecomment-1317831712
ENV PNPM_HOME="/root/.local/share/pnpm"
ENV PATH="${PATH}:${PNPM_HOME}"
ENV PYTHONUNBUFFERED=1
RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python
RUN python3 -m ensurepip
RUN pip3 install --no-cache --upgrade pip setuptools
RUN apk add --no-cache make
RUN apk add build-base
RUN npm install --global pnpm
RUN pnpm config set store-dir .pnpm-store
RUN pnpm install --global node-pre-gyp
Expand Down
24 changes: 13 additions & 11 deletions backend/src/config/JwtOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ import { Mode } from './modeOption';
import { match } from 'ts-pattern';

type getJwtOption = (mode: Mode) => (option: OauthUrlOption) => JwtOption;
export const getJwtOption: getJwtOption = (mode) => ({ redirectURL, clientURL }) => {
const redirectDomain = new URL(redirectURL).hostname;
const clientDomain = new URL(clientURL).hostname;
const secure = mode === 'prod' || mode === 'https';
export const getJwtOption: getJwtOption =
(mode) =>
({ redirectURL, clientURL }) => {
const redirectDomain = new URL(redirectURL).hostname;
const clientDomain = new URL(clientURL).hostname;
const secure = mode === 'prod' || mode === 'https';

const issuer = secure ? redirectDomain : 'localhost';
const domain = match(mode)
.with('prod', () => clientDomain)
.with('https', () => undefined)
.otherwise(() => 'localhost');
const issuer = secure ? redirectDomain : 'localhost';
const domain = match(mode)
.with('prod', () => clientDomain)
.with('https', () => undefined)
.otherwise(() => 'localhost');

return { issuer, domain, secure };
};
return { issuer, domain, secure };
};

export const jwtSecretSchema = z.object({ JWT_SECRET: nonempty }).transform((v) => v.JWT_SECRET);

Expand Down
10 changes: 5 additions & 5 deletions backend/src/config/config.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type NaverBookApiOption = {

/** 네이버 도서 검색 API 시크릿 */
secret: string;
}
};

/** DB 연결 옵션 */
export type ConnectOption = {
Expand All @@ -34,7 +34,7 @@ export type ConnectOption = {

/** DB 이름 */
database: string;
}
};

/** OAuth URL 옵션 */
export type OauthUrlOption = {
Expand All @@ -43,7 +43,7 @@ export type OauthUrlOption = {

/** 집현전 프론트엔드 URL */
clientURL: string;
}
};

/** 42 API OAuth 클라이언트 인증 정보 */
export type Oauth42ApiOption = {
Expand All @@ -52,7 +52,7 @@ export type Oauth42ApiOption = {

/** 42 API OAuth 클라이언트 시크릿 */
secret: string;
}
};

/** npm 로깅 레벨 */
export type LogLevel = keyof typeof levels;
Expand All @@ -64,4 +64,4 @@ export type LogLevelOption = {

/** 콘솔 로깅 레벨 */
readonly consoleLogLevel: 'error' | 'debug';
}
};
18 changes: 11 additions & 7 deletions backend/src/config/dbSchema.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { envObject, nonempty } from './envObject';

/** RDS 연결 옵션 파싱을 위한 스키마 */
export const rdsSchema = envObject('RDS_HOSTNAME', 'RDS_USERNAME', 'RDS_PASSWORD', 'RDS_DB_NAME')
.transform((v) => ({
host: v.RDS_HOSTNAME,
username: v.RDS_USERNAME,
password: v.RDS_PASSWORD,
database: v.RDS_DB_NAME,
}));
export const rdsSchema = envObject(
'RDS_HOSTNAME',
'RDS_USERNAME',
'RDS_PASSWORD',
'RDS_DB_NAME',
).transform((v) => ({
host: v.RDS_HOSTNAME,
username: v.RDS_USERNAME,
password: v.RDS_PASSWORD,
database: v.RDS_DB_NAME,
}));

/** MYSQL 연결 옵션 파싱을 위한 스키마 */
const mysqlSchema = envObject('MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DATABASE')
Expand Down
2 changes: 1 addition & 1 deletion backend/src/config/envObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const url = z.string().trim().url();
* @param keys 환경변수 키 목록
*/
export const envObject = <T extends readonly string[]>(...keys: T) => {
type Keys = T[ number ];
type Keys = T[number];
const env = Object.fromEntries(keys.map((key) => [key, nonempty]));

return z.object(env as Record<Keys, typeof nonempty>);
Expand Down
10 changes: 6 additions & 4 deletions backend/src/config/getConnectOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ const getConnectOptionSchema = (mode: Mode) => {
/**
* 환경변수에서 DB 연결 옵션을 파싱하는 함수
*/
export const getConnectOption = (mode: Mode) => (processEnv: NodeJS.ProcessEnv): ConnectOption => {
const connectOptionSchema = getConnectOptionSchema(mode);
export const getConnectOption =
(mode: Mode) =>
(processEnv: NodeJS.ProcessEnv): ConnectOption => {
const connectOptionSchema = getConnectOptionSchema(mode);

return connectOptionSchema.parse(processEnv);
};
return connectOptionSchema.parse(processEnv);
};
4 changes: 2 additions & 2 deletions backend/src/config/logOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export const colors: Record<LogLevel, string> = {
} as const;

export const getLogLevelOption = (mode: RuntimeMode): LogLevelOption => {
const logLevel = (mode === 'production' ? 'http' : 'debug');
const consoleLogLevel = (mode === 'production' ? 'error' : 'debug');
const logLevel = mode === 'production' ? 'http' : 'debug';
const consoleLogLevel = mode === 'production' ? 'error' : 'debug';

return { logLevel, consoleLogLevel } as const;
};
12 changes: 7 additions & 5 deletions backend/src/config/naverBookApiOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import { NaverBookApiOption } from './config.type';
import { envObject } from './envObject';

const naverBookApiSchema = envObject('NAVER_BOOK_SEARCH_CLIENT_ID', 'NAVER_BOOK_SEARCH_SECRET')
.transform((v) => ({
client: v.NAVER_BOOK_SEARCH_CLIENT_ID,
secret: v.NAVER_BOOK_SEARCH_SECRET,
}));
const naverBookApiSchema = envObject(
'NAVER_BOOK_SEARCH_CLIENT_ID',
'NAVER_BOOK_SEARCH_SECRET',
).transform((v) => ({
client: v.NAVER_BOOK_SEARCH_CLIENT_ID,
secret: v.NAVER_BOOK_SEARCH_SECRET,
}));

export const getNaverBookApiOption = (processEnv: NodeJS.ProcessEnv): NaverBookApiOption => {
const option = naverBookApiSchema.parse(processEnv);
Expand Down
24 changes: 14 additions & 10 deletions backend/src/config/oauthOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@ export const oauth42Schema = z.object({
CLIENT_SECRET: nonempty,
});

export const getOauthUrlOption = (processEnv: NodeJS.ProcessEnv): OauthUrlOption => oauthUrlSchema
.transform((v) => ({
redirectURL: v.REDIRECT_URL,
clientURL: v.CLIENT_URL,
})).parse(processEnv);
export const getOauthUrlOption = (processEnv: NodeJS.ProcessEnv): OauthUrlOption =>
oauthUrlSchema
.transform((v) => ({
redirectURL: v.REDIRECT_URL,
clientURL: v.CLIENT_URL,
}))
.parse(processEnv);

// eslint-disable-next-line max-len
export const getOauth42ApiOption = (processEnv: NodeJS.ProcessEnv): Oauth42ApiOption => oauth42Schema
.transform((v) => ({
id: v.CLIENT_ID,
secret: v.CLIENT_SECRET,
})).parse(processEnv);
export const getOauth42ApiOption = (processEnv: NodeJS.ProcessEnv): Oauth42ApiOption =>
oauth42Schema
.transform((v) => ({
id: v.CLIENT_ID,
secret: v.CLIENT_SECRET,
}))
.parse(processEnv);
33 changes: 19 additions & 14 deletions backend/src/entity/entities/Book.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import {
Column, Entity, Index, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn,
Column,
Entity,
Index,
JoinColumn,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
} from 'typeorm';
import { BookInfo } from './BookInfo';
import { User } from './User';
Expand All @@ -8,55 +14,54 @@ import { Reservation } from './Reservation';

@Index('FK_donator_id_from_user', ['donatorId'], {})
@Entity('book')

export class Book {
@PrimaryGeneratedColumn({ type: 'int', name: 'id' })
id?: number;
id?: number;

@Column('varchar', { name: 'donator', nullable: true, length: 255 })
donator: string | null;
donator: string | null;

@Column('varchar', { name: 'callSign', length: 255 })
callSign: string;
callSign: string;

@Column('int', { name: 'status' })
status: number;
status: number;

@Column('datetime', {
name: 'createdAt',
default: () => "'CURRENT_TIMESTAMP(6)'",
})
createdAt?: Date;
createdAt?: Date;

@Column('int')
infoId: number;
infoId: number;

@Column('datetime', {
name: 'updatedAt',
default: () => "'CURRENT_TIMESTAMP(6)'",
})
updatedAt?: Date;
updatedAt?: Date;

@Column('int', { name: 'donatorId', nullable: true })
donatorId: number | null;
donatorId: number | null;

@ManyToOne(() => BookInfo, (bookInfo) => bookInfo.books, {
onDelete: 'NO ACTION',
onUpdate: 'NO ACTION',
})
@JoinColumn([{ name: 'infoId', referencedColumnName: 'id' }])
info?: BookInfo;
info?: BookInfo;

@ManyToOne(() => User, (user) => user.books, {
onDelete: 'NO ACTION',
onUpdate: 'NO ACTION',
})
@JoinColumn([{ name: 'donatorId', referencedColumnName: 'id' }])
donator2?: User;
donator2?: User;

@OneToMany(() => Lending, (lending) => lending.book)
lendings?: Lending[];
lendings?: Lending[];

@OneToMany(() => Reservation, (reservation) => reservation.book)
reservations?: Reservation[];
reservations?: Reservation[];
}
Loading
Loading