Merge branch 'feature' of https://github.com/vanillabrain/vanillameta into feature
This commit is contained in:
196
backend-api/package-lock.json
generated
196
backend-api/package-lock.json
generated
@@ -2932,15 +2932,27 @@
|
||||
}
|
||||
},
|
||||
"@nestjs/swagger": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-6.1.2.tgz",
|
||||
"integrity": "sha512-RU1DeTDyuN/lRXKFWaf7I9LYF34/ale3IIGeY3romAcXL/N9W0+50Ek3ou+Ajd5FqpLqzt7saYhnaQegVuU4UQ==",
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-6.1.4.tgz",
|
||||
"integrity": "sha512-kE8VjR+NaoKqxg8XqM/YYfALScPh4AcoR8Wywga8/OxHsTHY+MKxqvTpWp7IhCUWSA6xT8nQUpcC9Rt7C+r7Hw==",
|
||||
"requires": {
|
||||
"@nestjs/mapped-types": "1.1.0",
|
||||
"@nestjs/mapped-types": "1.2.0",
|
||||
"js-yaml": "4.1.0",
|
||||
"lodash": "4.17.21",
|
||||
"path-to-regexp": "3.2.0",
|
||||
"swagger-ui-dist": "4.14.0"
|
||||
"swagger-ui-dist": "4.15.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/mapped-types": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.2.0.tgz",
|
||||
"integrity": "sha512-NTFwPZkQWsArQH8QSyFWGZvJ08gR+R4TofglqZoihn/vU+ktHEJjMqsIsADwb7XD97DhiD+TVv5ac+jG33BHrg=="
|
||||
},
|
||||
"swagger-ui-dist": {
|
||||
"version": "4.15.5",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.15.5.tgz",
|
||||
"integrity": "sha512-V3eIa28lwB6gg7/wfNvAbjwJYmDXy1Jo1POjyTzlB6wPcHiGlRxq39TSjYGVjQrUSAzpv+a7nzp7mDxgNy57xA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nestjs/testing": {
|
||||
@@ -7928,6 +7940,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"encoding-negotiator": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/encoding-negotiator/-/encoding-negotiator-2.0.1.tgz",
|
||||
"integrity": "sha512-GSK7qphNR4iPcejfAlZxKDoz3xMhnspwImK+Af5WhePS9jUpK/Oh7rUdyENWu+9rgDflOCTmAojBsgsvM8neAQ=="
|
||||
},
|
||||
"end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
@@ -8786,6 +8803,130 @@
|
||||
"integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
|
||||
"dev": true
|
||||
},
|
||||
"fastify-plugin": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.1.tgz",
|
||||
"integrity": "sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA=="
|
||||
},
|
||||
"fastify-static": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.7.0.tgz",
|
||||
"integrity": "sha512-zZhCfJv/hkmud2qhWqpU3K9XVAuy3+IV8Tp9BC5J5U+GyA2XwoB6h8lh9GqpEIqdXOw01WyWQllV7dOWVyAlXg==",
|
||||
"requires": {
|
||||
"fastify-static-deprecated": "npm:fastify-static@4.6.1",
|
||||
"process-warning": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"fastify-static-deprecated": {
|
||||
"version": "npm:fastify-static@4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.6.1.tgz",
|
||||
"integrity": "sha512-vy7N28U4AMhuOim12ZZWHulEE6OQKtzZbHgiB8Zj4llUuUQXPka0WHAQI3njm1jTCx4W6fixUHfpITxweMtAIA==",
|
||||
"requires": {
|
||||
"content-disposition": "^0.5.3",
|
||||
"encoding-negotiator": "^2.0.1",
|
||||
"fastify-plugin": "^3.0.0",
|
||||
"glob": "^7.1.4",
|
||||
"p-limit": "^3.1.0",
|
||||
"readable-stream": "^3.4.0",
|
||||
"send": "^0.17.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg=="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.1"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
"integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
|
||||
"requires": {
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"send": {
|
||||
"version": "0.17.2",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
|
||||
"integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"destroy": "~1.0.4",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "1.8.1",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
}
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"fastify-swagger": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fastify-swagger/-/fastify-swagger-5.2.0.tgz",
|
||||
"integrity": "sha512-yKct50Mev9YIrhd2FRO4AChcJM9JwTBCziIjA4C+AI+hV2ystaIklgHVEwHoyqlaeQ+B4gZ1Z5rgOE87i4llLg==",
|
||||
"requires": {
|
||||
"fastify-swagger-deprecated": "npm:fastify-swagger@5.1.1",
|
||||
"process-warning": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"fastify-swagger-deprecated": {
|
||||
"version": "npm:fastify-swagger@5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fastify-swagger/-/fastify-swagger-5.1.1.tgz",
|
||||
"integrity": "sha512-7DA0zS8CCV5r+gbLgWdeeKEwLrVbbOxLMJVUfOl1H9+wSildSLD8hok2TLX7s3c28wOjF8+iZRxsz/hBDzfdIw==",
|
||||
"requires": {
|
||||
"fastify-plugin": "^3.0.0",
|
||||
"fastify-static": "^4.0.0",
|
||||
"js-yaml": "^4.0.0",
|
||||
"json-schema-resolver": "^1.3.0",
|
||||
"openapi-types": "^10.0.0",
|
||||
"rfdc": "^1.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fastq": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
|
||||
@@ -11487,6 +11628,31 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"json-schema-resolver": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-resolver/-/json-schema-resolver-1.3.0.tgz",
|
||||
"integrity": "sha512-EX7W1r8aZ/T3j8GbbBxPXi60bnsELfT90OiA1QrbGMvwzVSbyMNOAzvMFcFb8m7gKCXZLJpGe+cJOvWgoFl29A==",
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
"rfdc": "^1.1.4",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
@@ -13309,6 +13475,11 @@
|
||||
"is-wsl": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"openapi-types": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-10.0.0.tgz",
|
||||
"integrity": "sha512-Y8xOCT2eiKGYDzMW9R4x5cmfc3vGaaI4EL2pwhDmodWw1HlK18YcZ4uJxc7Rdp7/gGzAygzH9SXr6GKYIXbRcQ=="
|
||||
},
|
||||
"optional": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/optional/-/optional-0.1.4.tgz",
|
||||
@@ -13417,7 +13588,6 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yocto-queue": "^0.1.0"
|
||||
}
|
||||
@@ -14254,6 +14424,11 @@
|
||||
"type": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"process-warning": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz",
|
||||
"integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q=="
|
||||
},
|
||||
"promise-inflight": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
|
||||
@@ -14931,6 +15106,11 @@
|
||||
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||
"dev": true
|
||||
},
|
||||
"rfdc": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
|
||||
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
@@ -17796,7 +17976,6 @@
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
@@ -18375,8 +18554,7 @@
|
||||
"yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
||||
},
|
||||
"zip-stream": {
|
||||
"version": "4.1.0",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"@nestjs/mapped-types": "*",
|
||||
"@nestjs/passport": "^9.0.0",
|
||||
"@nestjs/platform-express": "^9.0.0",
|
||||
"@nestjs/swagger": "^6.1.2",
|
||||
"@nestjs/swagger": "^6.1.4",
|
||||
"@nestjs/typeorm": "^9.0.1",
|
||||
"@nestjsplus/knex": "^1.0.0",
|
||||
"@types/cookie-parser": "^1.4.3",
|
||||
@@ -48,6 +48,7 @@
|
||||
"cookie-parser": "^1.4.6",
|
||||
"cross-env": "^7.0.3",
|
||||
"dylib-node": "^1.0.10",
|
||||
"fastify-swagger": "^5.2.0",
|
||||
"js-joda": "^1.11.0",
|
||||
"knex": "^2.3.0",
|
||||
"knex-bigquery": "^2.0.3",
|
||||
|
||||
@@ -28,10 +28,9 @@ import { ShareUrlModule } from './share-url/share-url.module';
|
||||
port: parseInt(process.env.DB_PORT) || 3306,
|
||||
username: process.env.DB_USERNAME,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: 'vanillameta_auth',
|
||||
database: process.env.DB_NAME,
|
||||
autoLoadEntities: true,
|
||||
entities: [__dirname + '/**/*.entity{.ts,.js}'],
|
||||
// entities: ["dist/common/entities/*{.ts,.js}"],
|
||||
synchronize: false,
|
||||
logging: process.env.NODE_ENV == 'prod',
|
||||
retryAttempts: 1,
|
||||
|
||||
@@ -43,7 +43,7 @@ export class AuthService {
|
||||
// accesstoken이 없을때
|
||||
}
|
||||
|
||||
async setRefreshKey(refreshToken: string, jwt_id: string){
|
||||
async setRefreshKey(refreshToken: string, jwt_id: number){
|
||||
const findToken = await this.refreshTokenRepository.findOne({ where: { id: jwt_id } });
|
||||
const token = refreshToken.replace('Bearer ', '');
|
||||
if(!findToken){
|
||||
@@ -68,12 +68,13 @@ export class AuthService {
|
||||
// 회원이 존재하는지 확인
|
||||
}
|
||||
|
||||
async deleteRefreshToken(Token: string) {
|
||||
const token = Token.replace('Bearer ', '').split('=')[1];
|
||||
async deleteRefreshToken(userId: number) {
|
||||
console.log(userId)
|
||||
const refreshTokenInfo = await this.refreshTokenRepository.findOne({
|
||||
where: { refreshToken: token },
|
||||
where: { id: userId },
|
||||
});
|
||||
refreshTokenInfo.refreshToken = null;
|
||||
console.log(refreshTokenInfo)
|
||||
refreshTokenInfo.refreshToken = '';
|
||||
await this.refreshTokenRepository.save(refreshTokenInfo);
|
||||
}
|
||||
|
||||
@@ -99,8 +100,7 @@ export class AuthService {
|
||||
}
|
||||
} // Refresh 토큰이 유효한지 확인
|
||||
|
||||
async checkAccess(token: string, password: string) {
|
||||
const { accessKeyData } = await this.verifyAccessToken(token);
|
||||
return await this.validateUser(accessKeyData.userId, password)
|
||||
async checkAccess(userId: string, password: string) {
|
||||
return await this.validateUser(userId, password)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Column, Entity, PrimaryColumn } from 'typeorm';
|
||||
@Entity()
|
||||
export class RefreshToken {
|
||||
@PrimaryColumn()
|
||||
id: string;
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
refreshToken: string;
|
||||
|
||||
@@ -15,6 +15,7 @@ export class JwtAuthGuard extends AuthGuard('jwt') {
|
||||
}
|
||||
const token = authorization.replace('Bearer ', '');
|
||||
const userInfo = await this.validate(token);
|
||||
|
||||
if (userInfo) request.user = userInfo;
|
||||
return !!userInfo;
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@ export class DashboardController {
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post()
|
||||
create(@Body() createDashboardDto: CreateDashboardDto, @Req() req) {
|
||||
const { authorization } = req.headers;
|
||||
return this.dashboardService.create(createDashboardDto, authorization);
|
||||
const { accessKeyData } = req.user
|
||||
return this.dashboardService.create(createDashboardDto, accessKeyData.id);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get()
|
||||
findAll(@Req() req) {
|
||||
const { authorization } = req.headers;
|
||||
return this.dashboardService.findAll(authorization);
|
||||
const { accessKeyData } = req.user;
|
||||
return this.dashboardService.findAll(accessKeyData.id);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
||||
@@ -30,11 +30,9 @@ export class DashboardService {
|
||||
private readonly authService: AuthService,
|
||||
) {}
|
||||
|
||||
async create(createDashboardDto: CreateDashboardDto, accessToken: string) {
|
||||
const findUser = await this.authService.verifyAccessToken(accessToken);
|
||||
const { accessKeyData } = findUser;
|
||||
async create(createDashboardDto: CreateDashboardDto, accessToken: number) {
|
||||
const userData = await this.userRepository.findOne({
|
||||
where: { id: accessKeyData.id },
|
||||
where: { id: accessToken },
|
||||
});
|
||||
if (!userData) {
|
||||
return 'Bad Request';
|
||||
@@ -53,7 +51,7 @@ export class DashboardService {
|
||||
|
||||
if (findTitle.title !== createDashboardDto.title) {
|
||||
const share_id = await this.dashboardShareRepository.save({
|
||||
uuid: uuidv4(),
|
||||
uuid: uuidv4(), // uuid의 버전 uuidv1의 결우 mac의 정보등을 담고있음.
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
});
|
||||
@@ -81,6 +79,7 @@ export class DashboardService {
|
||||
// .orUpdate(['title', 'layout'], ['id'])
|
||||
// .execute();
|
||||
// console.log('test', test.generatedMaps[0].id);
|
||||
// 기존 코드
|
||||
|
||||
await this.userService.saveDashboard(newDashboard.id, id);
|
||||
await this.dashboardWidgetService.create(saveObjDW);
|
||||
@@ -91,8 +90,8 @@ export class DashboardService {
|
||||
return 'already exist name title';
|
||||
}
|
||||
|
||||
async findAll(accessToken: string) {
|
||||
const findUser = await this.userService.findDashboardId(accessToken);
|
||||
async findAll(userId: number) {
|
||||
const findUser = await this.userService.findDashboardId(userId);
|
||||
const findId = findUser.map(el =>
|
||||
el['dashboardId']);
|
||||
const find_all = [];
|
||||
@@ -149,6 +148,7 @@ export class DashboardService {
|
||||
dashboardId: id,
|
||||
widgetIds: widgetIds,
|
||||
};
|
||||
// 업데이트할 데이터
|
||||
await this.dashboardWidgetService.update(id, saveObjDW);
|
||||
const updatedDashboard = await this.dashboardRepository.save(find_dashboard);
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@ import { LoginUserDto } from '../login/dto/login-user.dto';
|
||||
import { AuthService } from 'src/auth/auth.service';
|
||||
import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard';
|
||||
import { LocalAuthGuard } from 'src/auth/guards/local-auth.guard';
|
||||
import {ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
|
||||
@ApiTags('로그인 관련 API')
|
||||
@Controller('login')
|
||||
export class LoginController {
|
||||
constructor(
|
||||
@@ -16,6 +19,7 @@ export class LoginController {
|
||||
|
||||
@UsePipes(ValidationPipe)
|
||||
@Post('signin')
|
||||
@ApiOperation({ summary: ' 로그인 ' })
|
||||
async logIn(@Res() res,@Req() req, @Body() loginDto: LoginUserDto){
|
||||
const findUser = await this.loginService.signin(loginDto)
|
||||
// 유저존재여부 확인
|
||||
@@ -27,25 +31,27 @@ export class LoginController {
|
||||
// RefreshToken 저장
|
||||
|
||||
res.cookie('jwt_re', refreshToken, {
|
||||
httpOnly: true,
|
||||
sameSite: 'none',
|
||||
secure: true
|
||||
httpOnly: true, // 브라우저에서 cookie에 에 접근권한 x
|
||||
sameSite: 'Lax', // 다른 도메인의 cookie를 허용한 주소만 가져올 수 있음
|
||||
secure: true // 보안처리된 https만 허
|
||||
})
|
||||
return res.status(201).json({ accessToken: accessToken, message: 'success' })
|
||||
}
|
||||
|
||||
// validationPipe = 들어오는 모든 클라이언트 페이로드에 대한 유효성 검사 규칙을 적용
|
||||
@UsePipes(ValidationPipe)
|
||||
@Post('signup')
|
||||
@ApiOperation({ summary: '회원가입' })
|
||||
create(@Body() createUserDto: CreateLoginDto) {
|
||||
return this.loginService.signup(createUserDto);
|
||||
}
|
||||
|
||||
@UseGuards(LocalAuthGuard)
|
||||
@UseGuards(LocalAuthGuard) //refrshtoken 검사
|
||||
@Post('signout')
|
||||
@ApiOperation({ summary: '로그아웃' })
|
||||
async signOut(@Res() res, @Req() req) {
|
||||
const refreshToken = req.headers.cookie;
|
||||
delete req.headers.authorization;
|
||||
await this.authService.deleteRefreshToken(refreshToken)
|
||||
const { jwtId } = req.user.refreshKeyData;
|
||||
await this.authService.deleteRefreshToken(jwtId)
|
||||
return res.status(201).clearCookie('jwt_re').json({ message: 'success'})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export class LoginService {
|
||||
|
||||
async signin(loginDto: LoginUserDto) {
|
||||
const { userId, password } = loginDto;
|
||||
const findUser = await this.authService.validateUser(userId, password);
|
||||
const findUser = await this.authService.validateUser(userId, password); // 요저의 존재여부 확인
|
||||
if (!findUser) {
|
||||
throw new UnauthorizedException(`Unauthorized`);
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ import { ExpressAdapter } from '@nestjs/platform-express';
|
||||
import { HttpExceptionFilter } from './nest-utils/http-exception.filter';
|
||||
import { ValidationPipe } from '@nestjs/common';
|
||||
import cookieParser from 'cookie-parser';
|
||||
import { setupSwagger } from './utils/swagger.js';
|
||||
|
||||
async function bootstrap() {
|
||||
const expressApp = express();
|
||||
const whiteList = ['https://vanillameta-dev.vanillabrain.com', 'http://localhost:3000']
|
||||
const whiteList = ['https://vanillameta-dev.vanillabrain.com', 'http://localhost:3000', 'http://localhost:4000']
|
||||
const app = await NestFactory.create(AppModule, new ExpressAdapter(expressApp), {
|
||||
logger: console,
|
||||
|
||||
cors: {
|
||||
origin: function (origin, callback){
|
||||
if(whiteList.indexOf(origin) !== -1){
|
||||
@@ -29,8 +29,7 @@ async function bootstrap() {
|
||||
});
|
||||
app.useGlobalFilters(new HttpExceptionFilter());
|
||||
app.use(cookieParser());
|
||||
// app.useGlobalPipes(new ValidationPipe({ transform: true }));
|
||||
// const app = await NestFactory.create(AppModule);
|
||||
setupSwagger(app)
|
||||
await app.listen(4000);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
|
||||
export class ShareUrlOnDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ description: '유저Id'})
|
||||
userId: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ description: '공유 url 공유기간'})
|
||||
endDate: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,28 +3,33 @@ import { ShareUrlService } from './share-url.service';
|
||||
import { ShareUrlOnDto } from './dto/create-share-url.dto';
|
||||
import { UpdateShareUrlDto } from './dto/update-share-url.dto';
|
||||
import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard';
|
||||
import {ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@Controller('share-url')
|
||||
@ApiTags('url공유화 API')
|
||||
export class ShareUrlController {
|
||||
constructor(private readonly shareUrlService: ShareUrlService) {}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('share-on/:dashboardId')
|
||||
@ApiOperation({ summary: '공유 url On' })
|
||||
checkShareUrlOn(@Req() req, @Param() params, @Body() shareUrlOnDto: ShareUrlOnDto) {
|
||||
const { authorization } = req.headers;
|
||||
const { userId } = req.user.accessKeyData;
|
||||
const { dashboardId } = params;
|
||||
return this.shareUrlService.checkShareUrlOn( authorization, dashboardId, shareUrlOnDto )
|
||||
return this.shareUrlService.checkShareUrlOn( userId, dashboardId, shareUrlOnDto )
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('share-off/:dashboardId')
|
||||
@ApiOperation({ summary: '공유 url Off' })
|
||||
checkShareUrlOff(@Req() req, @Param() params, @Body() shareUrlOnDto: ShareUrlOnDto) {
|
||||
const { authorization } = req.headers;
|
||||
const { userId } = req.user.accessKeyData;
|
||||
const { dashboardId } = params;
|
||||
return this.shareUrlService.checkShareUrlOff( authorization, dashboardId, shareUrlOnDto)
|
||||
return this.shareUrlService.checkShareUrlOff( userId, dashboardId, shareUrlOnDto)
|
||||
}
|
||||
|
||||
@Get('share-dashboard/:uuid')
|
||||
@ApiOperation({ summary: '공유 url 접속' })
|
||||
async shareDashboardInfo(@Param() param) {
|
||||
const { shareUrl } = param;
|
||||
return await this.shareUrlService.shareDashboardInfo(shareUrl)
|
||||
|
||||
@@ -22,9 +22,8 @@ export class ShareUrlService {
|
||||
}
|
||||
|
||||
|
||||
async checkShareUrlOn( accessToken:string, dashboardId: number, shareUrlOnDto: ShareUrlOnDto ) {
|
||||
const findpass = await this.userRepository.findOne({ where: { userId: shareUrlOnDto.userId }})
|
||||
const findUser = await this.authService.checkAccess(accessToken, findpass.password);
|
||||
async checkShareUrlOn( userId:string, dashboardId: number, shareUrlOnDto: ShareUrlOnDto ) {
|
||||
const findUser = await this.userRepository.findOne({ where: { userId: userId }})
|
||||
if(!findUser){
|
||||
return 'not exist user'
|
||||
} else {
|
||||
@@ -40,22 +39,23 @@ export class ShareUrlService {
|
||||
return { uuid: findDashboardShare.uuid, message: "success" }
|
||||
}
|
||||
}
|
||||
// 공유기능 on시 공유토큰과 endDate를 저장
|
||||
|
||||
async checkShareUrlOff( accessToken:string, dashboardId: number, shareUrlOnDto: ShareUrlOnDto){
|
||||
const findpass = await this.userRepository.findOne({ where: { userId: shareUrlOnDto.userId }})
|
||||
const findUser = await this.authService.checkAccess(accessToken, findpass.password);
|
||||
async checkShareUrlOff( userId:string, dashboardId: number, shareUrlOnDto: ShareUrlOnDto){
|
||||
const findUser = await this.userRepository.findOne({ where: { userId: userId }})
|
||||
if(!findUser){
|
||||
return 'not exist user'
|
||||
} else {
|
||||
const findDashboard = await this.dashboardRepository.findOne( { where: { id: dashboardId } })
|
||||
const findDashboardShare = await this.dashboardShareRepository.findOne({ where: { id: findDashboard.shareId }})
|
||||
findDashboardShare.shareToken = null;
|
||||
findDashboardShare.shareToken = '';
|
||||
findDashboardShare.shareYn = YesNo.NO;
|
||||
findDashboardShare.endDate = null;
|
||||
await this.dashboardShareRepository.save(findDashboardShare)
|
||||
return { message: "success" }
|
||||
}
|
||||
}
|
||||
// 공유기능 off시 쉐어토큰, endDate을 없애고 사용가능여부를 N으로 저장
|
||||
|
||||
async shareDashboardInfo(uuid: string){
|
||||
const findDashboardShareUrl = await this.dashboardShareRepository.findOne({ where: { uuid: uuid }})
|
||||
@@ -65,4 +65,5 @@ export class ShareUrlService {
|
||||
}
|
||||
return this.dashboardService.findOne(+findDashboard.id)
|
||||
}
|
||||
// 공유url로 접속시 대시보드의 정보를 받아오는 코드
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
import { ApiProperty, ApiTags } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
|
||||
|
||||
@ApiTags('유저생성 Dto')
|
||||
export class CreateUserDto {
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ description: '유저Id'})
|
||||
userId: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ description: '유저password'})
|
||||
password: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ description: '유저email'})
|
||||
email: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsOptional } from 'class-validator';
|
||||
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn} from 'typeorm';
|
||||
import { BaseEntity } from '../../common/entities/base.entity';
|
||||
@@ -5,13 +6,16 @@ import { BaseEntity } from '../../common/entities/base.entity';
|
||||
export class UserMapping extends BaseEntity {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
@ApiProperty({ description: 'id'})
|
||||
id: number;
|
||||
|
||||
@IsOptional()
|
||||
@Column()
|
||||
@ApiProperty({ description: '대시보드id'})
|
||||
dashboardId: number;
|
||||
|
||||
@Column()
|
||||
@ApiProperty({ description: '유저id'})
|
||||
userInfoId: number;
|
||||
|
||||
// @IsOptional()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsOptional } from 'class-validator';
|
||||
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, BaseEntity} from 'typeorm';
|
||||
|
||||
@@ -6,21 +7,26 @@ import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateCol
|
||||
export class User {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
@ApiProperty({ description: 'id'})
|
||||
id: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@Column()
|
||||
@ApiProperty({ description: '유저Id'})
|
||||
userId: string;
|
||||
|
||||
@Column()
|
||||
jwtId: string;
|
||||
@ApiProperty({ description: 'refreshTokenId'})
|
||||
jwtId: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@Column()
|
||||
@ApiProperty({ description: '유저email'})
|
||||
email: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@Column()
|
||||
@ApiProperty({ description: '유저password'})
|
||||
password: string;
|
||||
|
||||
@CreateDateColumn({ default: () => 'CURRENT_TIMESTAMP', type: "timestamp" })
|
||||
|
||||
@@ -4,8 +4,11 @@ import { CreateUserDto } from './dto/create-user.dto';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard';
|
||||
import { AuthService } from 'src/auth/auth.service';
|
||||
import { LocalAuthGuard } from 'src/auth/guards/local-auth.guard';
|
||||
import {ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@Controller('user')
|
||||
@ApiTags('유저 API')
|
||||
export class UserController {
|
||||
constructor(
|
||||
private readonly userService: UserService,
|
||||
@@ -14,38 +17,43 @@ export class UserController {
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('userinfo')
|
||||
@ApiOperation({ summary: '해당유저정보 가져오기' })
|
||||
findOne(@Req() req) {
|
||||
const { authorization } = req.headers;
|
||||
return this.userService.findOne(authorization);
|
||||
const { id } = req.user.accessKeyData;
|
||||
return this.userService.findOne(id);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Patch('change-info')
|
||||
@ApiOperation({ summary: '유저정보 수정' })
|
||||
updateUsername(@Req() req, @Body() updateUserDto: UpdateUserDto) {
|
||||
const { authorization } = req.headers;
|
||||
return this.userService.updateUserInfo(authorization, updateUserDto);
|
||||
const { userId } = req.user.accessKeyData;
|
||||
return this.userService.updateUserInfo(userId, updateUserDto);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Delete('delete-account')
|
||||
@ApiOperation({ summary: ' 해당유저 삭제 ' })
|
||||
deleteUser(@Req() req, @Body() createUserDto: CreateUserDto) {
|
||||
const { authorization } = req.headers;
|
||||
const { userId } = req.user.accessKeyData;
|
||||
const { password } = createUserDto;
|
||||
return this.userService.deleteUser(authorization, password);
|
||||
return this.userService.deleteUser(userId, password);
|
||||
}
|
||||
|
||||
// @UseGuards(JwtAuthGuard)
|
||||
@UseGuards(LocalAuthGuard)
|
||||
@Post('get-access-token')
|
||||
@ApiOperation({ summary: 'AccessToken 재 발급' })
|
||||
async reissuanceAccessToken(@Req() req, @Res() res) {
|
||||
const { cookie } = req.headers;
|
||||
const accessToken = await this.userService.reissuanceAccessToken(cookie);
|
||||
const { userId } = req.user.refreshKeyData;
|
||||
const accessToken = await this.userService.reissuanceAccessToken(userId);
|
||||
return res.status(201).json({ accessToken: accessToken, message: 'success' });
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('get-dashboard')
|
||||
@ApiOperation({ summary: '해당유정의 대시보드 목록 가져오기' })
|
||||
async findDashboardId(@Req() req) {
|
||||
const { authorization } = req.headers;
|
||||
await this.userService.findDashboardId(authorization);
|
||||
const { id } = req.headers.accessKeyData;
|
||||
await this.userService.findDashboardId(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,9 @@ export class UserService {
|
||||
private authService: AuthService,
|
||||
) {}
|
||||
|
||||
async findOne(accessToken: string) {
|
||||
const findUser = await this.authService.verifyAccessToken(accessToken)
|
||||
const { accessKeyData } = findUser;
|
||||
async findOne(userId: number) {
|
||||
const userData = await this.userRepository.findOne({
|
||||
where: { userId: accessKeyData.userId }
|
||||
where: { id: userId }
|
||||
});
|
||||
if(!userData){
|
||||
return 'Bad Request'
|
||||
@@ -32,8 +30,8 @@ export class UserService {
|
||||
}
|
||||
}
|
||||
|
||||
async updateUserInfo(accessToken: string, updateUserDto: UpdateUserDto) {
|
||||
const findUser = await this.authService.checkAccess(accessToken, updateUserDto.password);
|
||||
async updateUserInfo(userId: string, updateUserDto: UpdateUserDto) {
|
||||
const findUser = await this.authService.checkAccess(userId, updateUserDto.password);
|
||||
if(!findUser){
|
||||
throw new HttpException('not exist user', HttpStatus.CONFLICT);
|
||||
} else {
|
||||
@@ -44,8 +42,8 @@ export class UserService {
|
||||
}
|
||||
}
|
||||
|
||||
async deleteUser( accessToken:string, password: string ) {
|
||||
const findUser = await this.authService.checkAccess(accessToken, password);
|
||||
async deleteUser( userId:string, password: string ) {
|
||||
const findUser = await this.authService.checkAccess(userId, password);
|
||||
if(!findUser){
|
||||
return 'Unauthorized'
|
||||
} else {
|
||||
@@ -54,30 +52,27 @@ export class UserService {
|
||||
}
|
||||
}
|
||||
|
||||
async reissuanceAccessToken(cookie: string){
|
||||
const tokenInfo = await this.authService.verifyRefreshToken(cookie)
|
||||
|
||||
const { userId } = tokenInfo.refreshKeyData
|
||||
async reissuanceAccessToken(userId: string){
|
||||
const payload = await this.userRepository.findOne({ where: { userId: userId }})
|
||||
return await this.authService.generateAccessToken(payload)
|
||||
}
|
||||
// AccessToken 만료시 재발급 코드
|
||||
|
||||
async saveDashboard(dashboardId: number, userInfoId: number) {
|
||||
console.log(userInfoId)
|
||||
const saveObj = {
|
||||
dashboardId: dashboardId,
|
||||
userInfoId: userInfoId
|
||||
}
|
||||
await this.userMappingRepository.save(saveObj)
|
||||
}
|
||||
// mapping table 대시보드id, 유저id 저장
|
||||
|
||||
async findDashboardId(accesstoken: string){
|
||||
const findUser = await this.authService.verifyAccessToken(accesstoken)
|
||||
const { accessKeyData } = findUser;
|
||||
async findDashboardId(id: number){
|
||||
const findDashboard = await this.userMappingRepository
|
||||
.createQueryBuilder('user_mapping')
|
||||
.select("dashboardId")
|
||||
.where('user_mapping.userInfoId = :userInfoId', { userInfoId: accessKeyData.id }).getRawMany()
|
||||
.where('user_mapping.userInfoId = :userInfoId', { userInfoId: id }).getRawMany()
|
||||
return findDashboard
|
||||
}
|
||||
// 대시보드id찾는 코드
|
||||
}
|
||||
|
||||
30
backend-api/src/utils/swagger-APIhelper.ts
Normal file
30
backend-api/src/utils/swagger-APIhelper.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { OpenAPIObject } from '@nestjs/swagger';
|
||||
import { PathsObject } from '@nestjs/swagger/dist/interfaces/open-api-spec.interface';
|
||||
|
||||
const arrayIntersect = (array1: string[], array2: string[]): string[] => array1.filter((item) => array2.includes(item));
|
||||
|
||||
export const filterDocumentsPathsByTags = (publicDocument: OpenAPIObject): PathsObject => {
|
||||
const result: PathsObject = {};
|
||||
|
||||
|
||||
const tags = publicDocument.tags.map(({ name }) => name); // 모든 tage의 이름
|
||||
for (const path of Object.keys(publicDocument.paths)) {
|
||||
const pathMethods = {};
|
||||
|
||||
for (const method of Object.keys(publicDocument.paths[path])) {
|
||||
const endpointTags = publicDocument.paths[path][method].tags; //addTag로 경로 설정한 테그이름
|
||||
console.log(publicDocument.components)
|
||||
if (!Array.isArray(endpointTags)) {
|
||||
continue;
|
||||
}
|
||||
if (arrayIntersect(tags, endpointTags).length > 0) {
|
||||
pathMethods[method] = publicDocument.paths[path][method]; // 모든 tag의 이름과 경로 설정한 테그이름이 같은것.
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
result[path] = pathMethods;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
34
backend-api/src/utils/swagger.ts
Normal file
34
backend-api/src/utils/swagger.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
||||
import { filterDocumentsPathsByTags } from './swagger-APIhelper';
|
||||
import { filterDocumentsDtoPathsByTags } from './swagger/Dtohelper'
|
||||
|
||||
/**
|
||||
* Swagger 세팅
|
||||
*
|
||||
* @param {INestApplication} app
|
||||
*/
|
||||
export function setupSwagger(app: INestApplication): void {
|
||||
const options = new DocumentBuilder()
|
||||
.setTitle('NestJS Study API Docs')
|
||||
.setDescription('NestJS Study API description')
|
||||
.setVersion('3.0.3')
|
||||
.addBearerAuth({
|
||||
type: 'http',
|
||||
scheme: 'bearer',
|
||||
bearerFormat: 'JWT',
|
||||
name: 'jwt_ac',
|
||||
description: 'Enter jwt token',
|
||||
in: 'header'
|
||||
},'AccessKey')
|
||||
.addTag('유저 API')
|
||||
.addTag('url공유화 API')
|
||||
.addTag('로그인 관련 API')
|
||||
.build();
|
||||
|
||||
|
||||
const document = SwaggerModule.createDocument(app, options);
|
||||
document.paths = filterDocumentsPathsByTags(document);
|
||||
// document.paths = filterDocumentsDtoPathsByTags(document);
|
||||
SwaggerModule.setup('api-docs', app, document);
|
||||
}
|
||||
30
backend-api/src/utils/swagger/Dtohelper.ts
Normal file
30
backend-api/src/utils/swagger/Dtohelper.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { OpenAPIObject } from '@nestjs/swagger';
|
||||
import { ComponentsObject } from '@nestjs/swagger/dist/interfaces/open-api-spec.interface';
|
||||
|
||||
const arrayIntersect = (array1: string[], array2: string[]): string[] => array1.filter((item) => array2.includes(item));
|
||||
|
||||
export const filterDocumentsDtoPathsByTags = (publicDocument: OpenAPIObject): ComponentsObject => {
|
||||
const result: ComponentsObject = {};
|
||||
|
||||
const tags = publicDocument.tags.map(({ name }) => name); // 모든 tage의 이름
|
||||
console.log(tags)
|
||||
for (const path of Object.keys(publicDocument.paths)) {
|
||||
const pathMethods = {};
|
||||
|
||||
for (const method of Object.keys(publicDocument.paths[path])) {
|
||||
const endpointTags = publicDocument.paths[path][method].tags; //addTag로 경로 설정한 테그이름
|
||||
|
||||
if (!Array.isArray(endpointTags)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arrayIntersect(tags, endpointTags).length > 0) {
|
||||
pathMethods[method] = publicDocument.paths[path][method]; // 모든 tag의 이름과 경로 설정한 테그이름이 같은것.
|
||||
}
|
||||
}
|
||||
console.log(result)
|
||||
result[path] = pathMethods;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
16
landing-page/Jenkinsfile
vendored
Normal file
16
landing-page/Jenkinsfile
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
pipeline {
|
||||
agent any
|
||||
tools {
|
||||
git "git"
|
||||
}
|
||||
stages {
|
||||
stage('deploy') {
|
||||
steps {
|
||||
sh "aws configure set region $AWS_DEFAULT_REGION"
|
||||
sh "aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID"
|
||||
sh "aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY"
|
||||
sh "aws s3 cp landing-page s3://vanillameta.net --recursive --acl public-read"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user