Skip to content

Commit

Permalink
Merge pull request #313 from 42-world/develop
Browse files Browse the repository at this point in the history
🔥 Main Merge 🏃‍♀️🏃‍♂️🏃
  • Loading branch information
Skyrich2000 authored Sep 16, 2022
2 parents b57a550 + a743f94 commit dd24f11
Show file tree
Hide file tree
Showing 45 changed files with 1,008 additions and 248 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js → .eslintrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
ignorePatterns: ['.eslintrc.ts'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/auto-label.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: 'Auto Label'

on:
pull_request:
types: [labeled, unlabeled, opened, synchronize, reopened]

permissions:
pull-requests: write

jobs:
auto-label:
runs-on: ubuntu-latest
steps:
- uses: Yaminyam/auto-label-in-issue@1.1.0
69 changes: 38 additions & 31 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,27 @@
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
name: 'CodeQL'

on:
push:
branches: [ develop ]
branches: [develop]
pull_request:
# The branches below must be a subset of the branches above
branches: [ develop ]
branches: [develop]
paths-ignore:
- '**/*.md'
- '**/*.txt'
- '**/*.md'
- '**/*.txt'
schedule:
- cron: '17 16 * * 5'

# Cancel previous workflows if they are the same workflow on same ref (branch/tags)
# with the same event (push/pull_request) even they are in progress.
# This setting will help reduce the number of duplicated workflows.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true

jobs:
analyze:
name: Analyze
Expand All @@ -35,39 +42,39 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
language: ['javascript']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support

steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

#- run: |
# make bootstrap
# make release
#- run: |
# make bootstrap
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
18 changes: 11 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@ name: Test CI
on:
pull_request:
branches: ['**']
types: [labeled, unlabeled, opened, synchronize, reopened]

# Cancel previous workflows if they are the same workflow on same ref (branch/tags)
# with the same event (push/pull_request) even they are in progress.
# This setting will help reduce the number of duplicated workflows.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true

jobs:
test:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
runs-on: ubuntu-latest

env:
Expand All @@ -25,17 +34,12 @@ jobs:
ACCESS_TOKEN_KEY: ${{secrets.ACCESS_TOKEN_KEY}}
FRONT_URL: ${{secrets.FRONT_URL}}

strategy:
matrix:
node-version: [16.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
- name: Use Node.js 16.x
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
node-version: 16.x
cache: 'yarn'
- run: yarn
- run: make test
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AppController } from '@api/app.controller';
import { ArticleModule } from '@api/article/article.module';
import { AuthModule } from '@api/auth/auth.module';
import { JwtAuthGuard } from '@api/auth/jwt-auth.guard';
import { JwtAuthGuard } from '@api/auth/jwt-auth/jwt-auth.guard';
import { BestModule } from '@api/best/best.module';
import { CategoryModule } from '@api/category/category.module';
import { CommentModule } from '@api/comment/comment.module';
Expand Down
10 changes: 6 additions & 4 deletions apps/api/src/article/repositories/article.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ export class ArticleRepository extends Repository<Article> {
})
.andWhere(
new Brackets((qb) => {
qb.where('article.title like :q', { q: `%${options.q}%` }).orWhere('article.content like :q', {
q: `%${options.q}%`,
});
qb.where('article.title like :q', { q: `%${options.q}%` }).orWhere(
'regexp_replace(`article`.`content`, "!\\[[[:print:]]+\\]\\([[:print:]]+\\)", "") like :q',
{
q: `%${options.q}%`,
},
);
}),
)
.skip(getPaginationSkip(options))
Expand All @@ -52,7 +55,6 @@ export class ArticleRepository extends Repository<Article> {

const totalCount = await query.getCount();
const articles = await query.getMany();

return { articles, totalCount };
}

Expand Down
57 changes: 57 additions & 0 deletions apps/api/src/auth/__test__/auth.controller.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { ConfigService } from '@nestjs/config';
import { Response } from 'express';
import { mock, mockFn } from 'jest-mock-extended';
import { AuthController } from '../auth.controller';
import { AuthService } from '../auth.service';
import { GithubProfile } from '../types';

describe('AuthController', () => {
const mockAuthService = mock<AuthService>({
login: mockFn().mockResolvedValue({ id: 1 }),
getJwt: mockFn().mockReturnValue('jwt'),
getCookieOption: mockFn().mockReturnValue({ cookie: 'test' }),
});
const mockConfigService = mock<ConfigService>({
get: mockFn().mockReturnValue('access-token-key'),
});
const authController = new AuthController(mockAuthService, mockConfigService);

beforeEach(() => {
jest.clearAllTimers();
});

describe('githubLogin', () => {
test('정상 호출', async () => {
const actual = () => authController.githubLogin();

expect(actual).not.toThrow();
});
});

describe('githubCallback', () => {
test('로그인하면 쿠키를 세팅한다', async () => {
const githubProfile: GithubProfile = { id: '1', username: 'test' };
const mockResponse = mock<Response>({
cookie: mockFn().mockReturnThis(),
});

await authController.githubCallback(githubProfile, mockResponse);

expect(mockResponse.cookie).toBeCalledTimes(1);
expect(mockResponse.cookie).toBeCalledWith('access-token-key', 'jwt', { cookie: 'test' });
});
});

describe('signout', () => {
test('로그아웃하면 쿠키를 비운다', async () => {
const mockResponse = mock<Response>({
clearCookie: mockFn().mockReturnThis(),
});

authController.signout(mockResponse);

expect(mockResponse.clearCookie).toBeCalledTimes(1);
expect(mockResponse.clearCookie).toBeCalledWith('access-token-key', { cookie: 'test' });
});
});
});
128 changes: 128 additions & 0 deletions apps/api/src/auth/__test__/auth.decorator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { UserRole } from '@app/entity/user/interfaces/userrole.interface';
import { User } from '@app/entity/user/user.entity';
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
import 'reflect-metadata';
import { Auth, AuthUser, ReqGithubProfile } from '../auth.decorator';
import { REQUIRE_ROLES } from '../constant';
import { getParamDecorator } from './getParamDecoratorFactory';

describe('AuthDecorator', () => {
describe('Auth', () => {
test('Auth를 사용하지 않으면 권한이 설정이 되지 않는다.', async () => {
class TestClass {
testMethod() {}
}

const result = Reflect.getMetadata(REQUIRE_ROLES, new TestClass().testMethod);

expect(result).toBeUndefined();
});

test(`Auth('allow', UserRole.GUEST, UserRole.ADMIN) 는 GUEST, ADMIN 둘다 허락한다`, async () => {
class TestClass {
@Auth('allow', UserRole.GUEST, UserRole.ADMIN)
testMethod() {}
}

const result = Reflect.getMetadata(REQUIRE_ROLES, new TestClass().testMethod);

expect(result).toStrictEqual(['allow', UserRole.GUEST, UserRole.ADMIN]);
});

test(`Auth('allow') 는 아무권한도 허락하지 않는다.`, async () => {
class TestClass {
@Auth('allow')
testMethod() {}
}

const result = Reflect.getMetadata(REQUIRE_ROLES, new TestClass().testMethod);

expect(result).toStrictEqual(['allow']);
});

test(`Auth('deny', UserRole.GUEST, UserRole.ADMIN) 는 GUEST, ADMIN 둘다 허락한다`, async () => {
class TestClass {
@Auth('deny', UserRole.GUEST, UserRole.ADMIN)
testMethod() {}
}

const result = Reflect.getMetadata(REQUIRE_ROLES, new TestClass().testMethod);

expect(result).toStrictEqual(['deny', UserRole.GUEST, UserRole.ADMIN]);
});

test(`Auth('deny') 는 모든 권한을 허락한다.`, async () => {
class TestClass {
@Auth('deny')
testMethod() {}
}

const result = Reflect.getMetadata(REQUIRE_ROLES, new TestClass().testMethod);

expect(result).toStrictEqual(['deny']);
});

test(`Auth('public') 은 모든 권한을 허락한다.`, async () => {
class TestClass {
@Auth('public')
testMethod() {}
}

const result = Reflect.getMetadata(REQUIRE_ROLES, new TestClass().testMethod);

expect(result).toStrictEqual(['deny']);
});

test(`Auth() 은 GUEST를 제외한 권한을 허락한다.`, async () => {
class TestClass {
@Auth()
testMethod() {}
}

const result = Reflect.getMetadata(REQUIRE_ROLES, new TestClass().testMethod);

expect(result).toStrictEqual(['deny', UserRole.GUEST]);
});
});

describe('AuthUser', () => {
test('Request 에 담긴 user를 가져온다', async () => {
const user = new User();
const context = new ExecutionContextHost([{ user }, {}]);

const result = getParamDecorator(AuthUser)(null, context);

expect(result).toStrictEqual(user);
});

test('Request 에 담긴 user의 id를 가져온다', async () => {
const user = new User();
user.id = 1;
const context = new ExecutionContextHost([{ user }, {}]);

const result = getParamDecorator(AuthUser)('id', context);

expect(result).toStrictEqual(user.id);
});

test('Request 에 담긴 user의 id가 없는경우', async () => {
const user = new User();
const context = new ExecutionContextHost([{ user }, {}]);

const result = getParamDecorator(AuthUser)('id', context);

expect(result).toBeUndefined();
});
});

describe('ReqGithubProfile', () => {
test('Request 에 담긴 githubprofile를 가져온다', async () => {
const user = { id: 1, username: 'test' };
const context = new ExecutionContextHost([{ user }, {}]);

const result = getParamDecorator(ReqGithubProfile)(null, context);

expect(result).toStrictEqual(user);
});
});
});
13 changes: 13 additions & 0 deletions apps/api/src/auth/__test__/auth.module.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AuthModule } from '../auth.module';

describe('AuthModule', () => {
test('모듈이 잘 컴파일된다.', async () => {
// TODO: Test.createTestingModule 로 complie 할것
// const module = await Test.createTestingModule({
// imports: [AuthModule],
// }).compile();
const module = new AuthModule();

expect(module).toBeDefined();
});
});
Loading

0 comments on commit dd24f11

Please sign in to comment.