Peace 2 months ago
parent 3864eaa965
commit 3daefc7b1b
  1. 1
      backend/dist/app.controller.d.ts
  2. 10
      backend/dist/app.controller.js
  3. 2
      backend/dist/app.controller.js.map
  4. 10
      backend/dist/auth/auth.controller.d.ts
  5. 61
      backend/dist/auth/auth.controller.js
  6. 2
      backend/dist/auth/auth.controller.js.map
  7. 2
      backend/dist/auth/auth.service.d.ts
  8. 8
      backend/dist/auth/auth.service.js
  9. 2
      backend/dist/auth/auth.service.js.map
  10. 2
      backend/dist/tsconfig.build.tsbuildinfo
  11. 7
      backend/dist/users/dto/user-info-response.dto.d.ts
  12. 35
      backend/dist/users/dto/user-info-response.dto.js
  13. 2
      backend/dist/users/dto/user-info-response.dto.js.map
  14. 3
      backend/dist/users/user.entity.d.ts
  15. 7
      backend/dist/users/user.entity.js
  16. 2
      backend/dist/users/user.entity.js.map
  17. 5
      backend/dist/users/users.service.d.ts
  18. 6
      backend/dist/users/users.service.js
  19. 2
      backend/dist/users/users.service.js.map
  20. 7
      backend/src/app.controller.ts
  21. 52
      backend/src/auth/auth.controller.ts
  22. 10
      backend/src/auth/auth.service.ts
  23. 6
      backend/src/auth/dto/check-availability-response.dto.ts
  24. 9
      backend/src/auth/dto/check-email.dto.ts
  25. 9
      backend/src/auth/dto/check-name.dto.ts
  26. 14
      backend/src/profiles/dto/create-profile.dto.ts
  27. 9
      backend/src/profiles/dto/profile-response.dto.ts
  28. 6
      backend/src/profiles/profile.entity.ts
  29. 18
      backend/src/profiles/profiles.controller.spec.ts
  30. 26
      backend/src/profiles/profiles.controller.ts
  31. 12
      backend/src/profiles/profiles.module.ts
  32. 18
      backend/src/profiles/profiles.service.spec.ts
  33. 38
      backend/src/profiles/profiles.service.ts
  34. 13
      backend/src/users/dto/user-info-response.dto.ts
  35. 14
      backend/src/users/user.entity.ts
  36. 11
      backend/src/users/users.service.ts

@ -2,5 +2,4 @@ import { AppService } from './app.service';
export declare class AppController {
private readonly appService;
constructor(appService: AppService);
getHello(): string;
}

@ -18,18 +18,8 @@ let AppController = class AppController {
constructor(appService) {
this.appService = appService;
}
getHello() {
return this.appService.getHello();
}
};
exports.AppController = AppController;
__decorate([
(0, common_1.Get)(),
openapi.ApiResponse({ status: 200, type: String }),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", String)
], AppController.prototype, "getHello", null);
exports.AppController = AppController = __decorate([
(0, common_1.Controller)(),
__metadata("design:paramtypes", [app_service_1.AppService])

@ -1 +1 @@
{"version":3,"file":"app.controller.js","sourceRoot":"","sources":["../src/app.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAiD;AACjD,+CAA2C;AAGpC,IAAM,aAAa,GAAnB,MAAM,aAAa;IACK;IAA7B,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAGvD,QAAQ;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;IACpC,CAAC;CACF,CAAA;AAPY,sCAAa;AAIxB;IADC,IAAA,YAAG,GAAE;;;;;6CAGL;wBANU,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAE8B,wBAAU;GADxC,aAAa,CAOzB"}
{"version":3,"file":"app.controller.js","sourceRoot":"","sources":["../src/app.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,+CAA2C;AAGpC,IAAM,aAAa,GAAnB,MAAM,aAAa;IACK;IAA7B,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;CACxD,CAAA;AAFY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAE8B,wBAAU;GADxC,aAAa,CAEzB"}

@ -3,14 +3,20 @@ import { CreateUserDto } from 'src/users/dto/create-user.dto';
import { LoginUserDto } from 'src/auth/dto/login-user.dto';
import { LoginResponseDto } from './dto/login-response.dto';
import { UsersService } from 'src/users/users.service';
import { UserWithProfileResponseDto } from 'src/users/dto/user-info-response.dto';
import { UserInfoResponseDto } from 'src/users/dto/user-info-response.dto';
import { AuthRequest } from 'src/common/interfaces/auth-request.interface';
import { CreateUserResponse } from 'src/users/dto/create-user-response.dto';
import { CheckAvailabilityResponseDto } from './dto/check-availability-response.dto';
import { CheckNameDto } from './dto/check-name.dto';
import { CheckEmailDto } from './dto/check-email.dto';
export declare class AuthController {
private readonly authService;
private userService;
constructor(authService: AuthService, userService: UsersService);
signup(dto: CreateUserDto): Promise<CreateUserResponse>;
login(dto: LoginUserDto): Promise<LoginResponseDto>;
getMe(req: AuthRequest): Promise<UserWithProfileResponseDto>;
getMe(req: AuthRequest): Promise<UserInfoResponseDto>;
checkName(dto: CheckNameDto): Promise<CheckAvailabilityResponseDto>;
checkEmail(dto: CheckEmailDto): Promise<CheckAvailabilityResponseDto>;
deleteMe(req: AuthRequest): Promise<void>;
}

@ -24,6 +24,9 @@ const jwt_auth_guard_1 = require("./jwt-auth.guard");
const user_info_response_dto_1 = require("../users/dto/user-info-response.dto");
const swagger_1 = require("@nestjs/swagger");
const create_user_response_dto_1 = require("../users/dto/create-user-response.dto");
const check_availability_response_dto_1 = require("./dto/check-availability-response.dto");
const check_name_dto_1 = require("./dto/check-name.dto");
const check_email_dto_1 = require("./dto/check-email.dto");
let AuthController = class AuthController {
authService;
userService;
@ -44,13 +47,25 @@ let AuthController = class AuthController {
async getMe(req) {
return await this.userService.findUserWithProfileByIdOrFail(req.user.userId);
}
async checkName(dto) {
const available = await this.authService.isNameAvailable(dto.name);
return { available };
}
async checkEmail(dto) {
const available = await this.authService.isEmailAvailabe(dto.email);
return { available };
}
async deleteMe(req) {
await this.userService.softDelete(req.user.userId);
}
};
exports.AuthController = AuthController;
__decorate([
(0, common_1.Post)('signup'),
(0, common_1.HttpCode)(200),
(0, swagger_1.ApiOperation)({ summary: '회원가입' }),
(0, swagger_1.ApiOkResponse)({ description: '성공', type: create_user_response_dto_1.CreateUserResponse }),
openapi.ApiResponse({ status: 201, type: require("../users/dto/create-user-response.dto").CreateUserResponse }),
openapi.ApiResponse({ status: 200, type: require("../users/dto/create-user-response.dto").CreateUserResponse }),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [create_user_dto_1.CreateUserDto]),
@ -58,9 +73,10 @@ __decorate([
], AuthController.prototype, "signup", null);
__decorate([
(0, common_1.Post)('login'),
(0, common_1.HttpCode)(200),
(0, swagger_1.ApiOperation)({ summary: '로그인' }),
(0, swagger_1.ApiOkResponse)({ description: '성공', type: login_response_dto_1.LoginResponseDto }),
openapi.ApiResponse({ status: 201, type: require("./dto/login-response.dto").LoginResponseDto }),
openapi.ApiResponse({ status: 200, type: require("./dto/login-response.dto").LoginResponseDto }),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [login_user_dto_1.LoginUserDto]),
@ -70,13 +86,50 @@ __decorate([
(0, common_1.Get)('me'),
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
(0, swagger_1.ApiOkResponse)({ description: '성공', type: user_info_response_dto_1.UserWithProfileResponseDto }),
openapi.ApiResponse({ status: 200, type: require("../users/dto/user-info-response.dto").UserWithProfileResponseDto }),
(0, swagger_1.ApiOperation)({ summary: '정보 확인' }),
(0, swagger_1.ApiOkResponse)({ description: '성공', type: user_info_response_dto_1.UserInfoResponseDto }),
openapi.ApiResponse({ status: 200, type: require("../users/dto/user-info-response.dto").UserInfoResponseDto }),
__param(0, (0, common_1.Request)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], AuthController.prototype, "getMe", null);
__decorate([
(0, common_1.Post)('check-name'),
(0, common_1.HttpCode)(200),
(0, swagger_1.ApiOperation)({ summary: '사용자 이름 중복 확인' }),
(0, swagger_1.ApiOkResponse)({ description: '성공', type: check_availability_response_dto_1.CheckAvailabilityResponseDto }),
openapi.ApiResponse({ status: 200, type: require("./dto/check-availability-response.dto").CheckAvailabilityResponseDto }),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [check_name_dto_1.CheckNameDto]),
__metadata("design:returntype", Promise)
], AuthController.prototype, "checkName", null);
__decorate([
(0, common_1.Post)('check-email'),
(0, common_1.HttpCode)(200),
(0, swagger_1.ApiOperation)({ summary: '사용자 이메일 중복 확인' }),
(0, swagger_1.ApiOkResponse)({ description: '성공', type: check_availability_response_dto_1.CheckAvailabilityResponseDto }),
openapi.ApiResponse({ status: 200, type: require("./dto/check-availability-response.dto").CheckAvailabilityResponseDto }),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [check_email_dto_1.CheckEmailDto]),
__metadata("design:returntype", Promise)
], AuthController.prototype, "checkEmail", null);
__decorate([
(0, common_1.Delete)('me'),
(0, common_1.HttpCode)(204),
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
(0, swagger_1.ApiOperation)({ summary: '회원 탈퇴' }),
(0, swagger_1.ApiNoContentResponse)({ description: '탈퇴 완료' }),
(0, swagger_1.ApiNotFoundResponse)({ description: '존재하지 않는 사용자' }),
openapi.ApiResponse({ status: 204 }),
__param(0, (0, common_1.Request)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], AuthController.prototype, "deleteMe", null);
exports.AuthController = AuthController = __decorate([
(0, swagger_1.ApiTags)('인증'),
(0, common_1.Controller)('auth'),

@ -1 +1 @@
{"version":3,"file":"auth.controller.js","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAiF;AACjF,iDAA6C;AAC7C,kEAA8D;AAC9D,yDAA2D;AAC3D,iEAA4D;AAC5D,0DAAuD;AACvD,qDAAgD;AAChD,gFAAkF;AAElF,6CAAsF;AACtF,oFAA4E;AAIrE,IAAM,cAAc,GAApB,MAAM,cAAc;IAEN;IACT;IAFV,YACmB,WAAwB,EACjC,WAAyB;QADhB,gBAAW,GAAX,WAAW,CAAa;QACjC,gBAAW,GAAX,WAAW,CAAc;IAChC,CAAC;IAKE,AAAN,KAAK,CAAC,MAAM,CAAS,GAAkB;QACrC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC;IACJ,CAAC;IAKK,AAAN,KAAK,CAAC,KAAK,CAAS,GAAiB;QACnC,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IAMK,AAAN,KAAK,CAAC,KAAK,CAAY,GAAgB;QACrC,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,6BAA6B,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/E,CAAC;CACF,CAAA;AA/BY,wCAAc;AASnB;IAHL,IAAA,aAAI,EAAC,QAAQ,CAAC;IACd,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IACjC,IAAA,uBAAa,EAAC,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,6CAAkB,EAAE,CAAC;;IACjD,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,+BAAa;;4CAMtC;AAKK;IAHL,IAAA,aAAI,EAAC,OAAO,CAAC;IACb,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAChC,IAAA,uBAAa,EAAC,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,qCAAgB,EAAE,CAAC;;IAChD,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,6BAAY;;2CAEpC;AAMK;IAJL,IAAA,YAAG,EAAC,IAAI,CAAC;IACT,IAAA,kBAAS,EAAC,6BAAY,CAAC;IACvB,IAAA,uBAAa,GAAE;IACf,IAAA,uBAAa,EAAC,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,mDAA0B,EAAE,CAAC;;IAC1D,WAAA,IAAA,gBAAO,GAAE,CAAA;;;;2CAErB;yBA9BU,cAAc;IAF1B,IAAA,iBAAO,EAAC,IAAI,CAAC;IACb,IAAA,mBAAU,EAAC,MAAM,CAAC;qCAGe,0BAAW;QACpB,4BAAY;GAHxB,cAAc,CA+B1B"}
{"version":3,"file":"auth.controller.js","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":"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"}

@ -9,4 +9,6 @@ export declare class AuthService {
constructor(userService: UsersService, jwtService: JwtService);
signup(dto: CreateUserDto): Promise<import("../users/user.entity").User>;
login(dto: LoginUserDto): Promise<LoginResponseDto>;
isNameAvailable(name: string): Promise<boolean>;
isEmailAvailabe(email: string): Promise<boolean>;
}

@ -40,6 +40,14 @@ let AuthService = class AuthService {
},
};
}
async isNameAvailable(name) {
const user = await this.userService.findByName(name);
return !user;
}
async isEmailAvailabe(email) {
const user = await this.userService.findByEmail(email);
return !user;
}
};
exports.AuthService = AuthService;
exports.AuthService = AuthService = __decorate([

@ -1 +1 @@
{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/auth/auth.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAmE;AACnE,qCAAyC;AACzC,0DAAuD;AACvD,mCAAmC;AAM5B,IAAM,WAAW,GAAjB,MAAM,WAAW;IAEZ;IACA;IAFV,YACU,WAAyB,EACzB,UAAsB;QADtB,gBAAW,GAAX,WAAW,CAAc;QACzB,eAAU,GAAV,UAAU,CAAY;IAC7B,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,GAAkB;QAC7B,MAAM,MAAM,GAAW,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAiB;QAC3B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/D,MAAM,IAAI,8BAAqB,CAAC,cAAc,CAAC,CAAC;QAElD,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE5C,OAAO;YACL,YAAY,EAAE,KAAK;YACnB,IAAI,EAAE;gBACJ,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AA5BY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAGY,4BAAY;QACb,gBAAU;GAHrB,WAAW,CA4BvB"}
{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/auth/auth.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAmE;AACnE,qCAAyC;AACzC,0DAAuD;AACvD,mCAAmC;AAM5B,IAAM,WAAW,GAAjB,MAAM,WAAW;IAEZ;IACA;IAFV,YACU,WAAyB,EACzB,UAAsB;QADtB,gBAAW,GAAX,WAAW,CAAc;QACzB,eAAU,GAAV,UAAU,CAAY;IAC7B,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,GAAkB;QAC7B,MAAM,MAAM,GAAW,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAiB;QAC3B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/D,MAAM,IAAI,8BAAqB,CAAC,cAAc,CAAC,CAAC;QAElD,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE5C,OAAO;YACL,YAAY,EAAE,KAAK;YACnB,IAAI,EAAE;gBACJ,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAY;QAChC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC;IACf,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,KAAa;QACjC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC;IACf,CAAC;CACF,CAAA;AAtCY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAGY,4BAAY;QACb,gBAAU;GAHrB,WAAW,CAsCvB"}

File diff suppressed because one or more lines are too long

@ -1,12 +1,7 @@
import { ProfileResponseDto } from 'src/profiles/dto/profile-response.dto';
export declare class UserInfoResponseDto {
id: number;
name: string;
email?: string;
}
export declare class ProfileResponseDto {
bio?: string;
avatarUrl?: string;
}
export declare class UserWithProfileResponseDto extends UserInfoResponseDto {
profile?: ProfileResponseDto;
}

@ -9,15 +9,17 @@ var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserWithProfileResponseDto = exports.ProfileResponseDto = exports.UserInfoResponseDto = void 0;
exports.UserInfoResponseDto = void 0;
const openapi = require("@nestjs/swagger");
const swagger_1 = require("@nestjs/swagger");
const profile_response_dto_1 = require("../../profiles/dto/profile-response.dto");
class UserInfoResponseDto {
id;
name;
email;
profile;
static _OPENAPI_METADATA_FACTORY() {
return { id: { required: true, type: () => Number }, name: { required: true, type: () => String }, email: { required: false, type: () => String } };
return { id: { required: true, type: () => Number }, name: { required: true, type: () => String }, email: { required: false, type: () => String }, profile: { required: false, type: () => require("../../profiles/dto/profile-response.dto").ProfileResponseDto } };
}
}
exports.UserInfoResponseDto = UserInfoResponseDto;
@ -33,31 +35,8 @@ __decorate([
(0, swagger_1.ApiProperty)({ description: '사용자 이메일', example: 'user@email.com' }),
__metadata("design:type", String)
], UserInfoResponseDto.prototype, "email", void 0);
class ProfileResponseDto {
bio;
avatarUrl;
static _OPENAPI_METADATA_FACTORY() {
return { bio: { required: false, type: () => String }, avatarUrl: { required: false, type: () => String } };
}
}
exports.ProfileResponseDto = ProfileResponseDto;
__decorate([
(0, swagger_1.ApiProperty)({ description: '프로필 내용', example: 'bio...' }),
__metadata("design:type", String)
], ProfileResponseDto.prototype, "bio", void 0);
__decorate([
(0, swagger_1.ApiProperty)({ description: '프로필 아바타 주소', example: 'http://...' }),
__metadata("design:type", String)
], ProfileResponseDto.prototype, "avatarUrl", void 0);
class UserWithProfileResponseDto extends UserInfoResponseDto {
profile;
static _OPENAPI_METADATA_FACTORY() {
return { profile: { required: false, type: () => require("./user-info-response.dto").ProfileResponseDto } };
}
}
exports.UserWithProfileResponseDto = UserWithProfileResponseDto;
__decorate([
(0, swagger_1.ApiProperty)({ description: '프로필', type: ProfileResponseDto }),
__metadata("design:type", ProfileResponseDto)
], UserWithProfileResponseDto.prototype, "profile", void 0);
(0, swagger_1.ApiProperty)({ description: '프로필', required: false, type: () => profile_response_dto_1.ProfileResponseDto }),
__metadata("design:type", profile_response_dto_1.ProfileResponseDto)
], UserInfoResponseDto.prototype, "profile", void 0);
//# sourceMappingURL=user-info-response.dto.js.map

@ -1 +1 @@
{"version":3,"file":"user-info-response.dto.js","sourceRoot":"","sources":["../../../src/users/dto/user-info-response.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,6CAA8C;AAE9C,MAAa,mBAAmB;IAE9B,EAAE,CAAS;IAGX,IAAI,CAAS;IAGb,KAAK,CAAU;;;;CAChB;AATD,kDASC;AAPC;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;+CACzC;AAGX;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;;iDAC/C;AAGb;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;;kDACpD;AAGjB,MAAa,kBAAkB;IAE7B,GAAG,CAAU;IAGb,SAAS,CAAU;;;;CACpB;AAND,gDAMC;AAJC;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;;+CAC7C;AAGb;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;;qDAC/C;AAGrB,MAAa,0BAA2B,SAAQ,mBAAmB;IAEjE,OAAO,CAAsB;;;;CAC9B;AAHD,gEAGC;AADC;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;8BACpD,kBAAkB;2DAAC"}
{"version":3,"file":"user-info-response.dto.js","sourceRoot":"","sources":["../../../src/users/dto/user-info-response.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,6CAA8C;AAC9C,kFAA2E;AAE3E,MAAa,mBAAmB;IAE9B,EAAE,CAAS;IAGX,IAAI,CAAS;IAGb,KAAK,CAAU;IAGf,OAAO,CAAsB;;;;CAC9B;AAZD,kDAYC;AAVC;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;+CACzC;AAGX;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;;iDAC/C;AAGb;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;;kDACpD;AAGf;IADC,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,yCAAkB,EAAE,CAAC;8BAC3E,yCAAkB;oDAAC"}

@ -5,5 +5,6 @@ export declare class User extends TimestampedEntity {
name: string;
email?: string;
password: string;
profile: Profile;
profile?: Profile;
deletedAt?: Date;
}

@ -20,8 +20,9 @@ let User = class User extends timestamped_entity_1.TimestampedEntity {
email;
password;
profile;
deletedAt;
static _OPENAPI_METADATA_FACTORY() {
return { id: { required: true, type: () => Number }, name: { required: true, type: () => String }, email: { required: false, type: () => String }, password: { required: true, type: () => String }, profile: { required: true, type: () => require("../profiles/profile.entity").Profile } };
return { id: { required: true, type: () => Number }, name: { required: true, type: () => String }, email: { required: false, type: () => String }, password: { required: true, type: () => String }, profile: { required: false, type: () => require("../profiles/profile.entity").Profile }, deletedAt: { required: false, type: () => Date } };
}
};
exports.User = User;
@ -46,6 +47,10 @@ __decorate([
(0, typeorm_1.JoinColumn)(),
__metadata("design:type", profile_entity_1.Profile)
], User.prototype, "profile", void 0);
__decorate([
(0, typeorm_1.DeleteDateColumn)({ type: 'timestamp' }),
__metadata("design:type", Date)
], User.prototype, "deletedAt", void 0);
exports.User = User = __decorate([
(0, typeorm_1.Entity)()
], User);

@ -1 +1 @@
{"version":3,"file":"user.entity.js","sourceRoot":"","sources":["../../src/users/user.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,8EAA2E;AAC3E,+DAAsD;AACtD,qCAAuF;AAGhF,IAAM,IAAI,GAAV,MAAM,IAAK,SAAQ,sCAAiB;IAEzC,EAAE,CAAS;IAGX,IAAI,CAAS;IAGb,KAAK,CAAU;IAGf,QAAQ,CAAS;IAIjB,OAAO,CAAU;;;;CAClB,CAAA;AAhBY,oBAAI;AAEf;IADC,IAAA,gCAAsB,GAAE;;gCACd;AAGX;IADC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;;kCACZ;AAGb;IADC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;mCAC1B;AAGf;IADC,IAAA,gBAAM,GAAE;;sCACQ;AAIjB;IAFC,IAAA,kBAAQ,EAAC,GAAG,EAAE,CAAC,wBAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACrE,IAAA,oBAAU,GAAE;8BACJ,wBAAO;qCAAC;eAfN,IAAI;IADhB,IAAA,gBAAM,GAAE;GACI,IAAI,CAgBhB"}
{"version":3,"file":"user.entity.js","sourceRoot":"","sources":["../../src/users/user.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,8EAA2E;AAC3E,+DAAsD;AACtD,qCAOiB;AAGV,IAAM,IAAI,GAAV,MAAM,IAAK,SAAQ,sCAAiB;IAEzC,EAAE,CAAS;IAGX,IAAI,CAAS;IAGb,KAAK,CAAU;IAGf,QAAQ,CAAS;IAIjB,OAAO,CAAW;IAGlB,SAAS,CAAQ;;;;CAClB,CAAA;AAnBY,oBAAI;AAEf;IADC,IAAA,gCAAsB,GAAE;;gCACd;AAGX;IADC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;;kCACZ;AAGb;IADC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;mCAC1B;AAGf;IADC,IAAA,gBAAM,GAAE;;sCACQ;AAIjB;IAFC,IAAA,kBAAQ,EAAC,GAAG,EAAE,CAAC,wBAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACrE,IAAA,oBAAU,GAAE;8BACH,wBAAO;qCAAC;AAGlB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;8BAC5B,IAAI;uCAAC;eAlBN,IAAI;IADhB,IAAA,gBAAM,GAAE;GACI,IAAI,CAmBhB"}

@ -2,7 +2,7 @@ import { User } from './user.entity';
import { Repository } from 'typeorm';
import { CreateUserDto } from './dto/create-user.dto';
import { ChangePasswordDto } from './dto/change-password.dto';
import { UserInfoResponseDto, UserWithProfileResponseDto } from './dto/user-info-response.dto';
import { UserInfoResponseDto } from './dto/user-info-response.dto';
export declare class UsersService {
private repo;
constructor(repo: Repository<User>);
@ -11,6 +11,7 @@ export declare class UsersService {
findByEmail(email: string): Promise<User | null>;
create(dto: CreateUserDto): Promise<User>;
changePassword(userId: number, dto: ChangePasswordDto): Promise<void>;
softDelete(userId: number): Promise<void>;
findUserInfoByIdOrFail(id: number): Promise<UserInfoResponseDto>;
findUserWithProfileByIdOrFail(id: number): Promise<UserWithProfileResponseDto>;
findUserWithProfileByIdOrFail(id: number): Promise<UserInfoResponseDto>;
}

@ -50,6 +50,12 @@ let UsersService = class UsersService {
user.password = hashed;
await this.repo.save(user);
}
async softDelete(userId) {
const user = await this.repo.findOne({ where: { id: userId } });
if (!user)
throw new common_1.NotFoundException('User not found');
await this.repo.softDelete(userId);
}
async findUserInfoByIdOrFail(id) {
const user = await this.findById(id);
if (!user)

@ -1 +1 @@
{"version":3,"file":"users.service.js","sourceRoot":"","sources":["../../src/users/users.service.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"users.service.js","sourceRoot":"","sources":["../../src/users/users.service.ts"],"names":[],"mappings":"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"}

@ -1,12 +1,7 @@
import { Controller, Get } from '@nestjs/common';
import { Controller } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}

@ -1,14 +1,24 @@
import { Body, Controller, Get, Post, Request, UseGuards } from '@nestjs/common';
import { Body, Controller, Delete, Get, HttpCode, Post, Request, UseGuards } from '@nestjs/common';
import { AuthService } from './auth.service';
import { CreateUserDto } from 'src/users/dto/create-user.dto';
import { LoginUserDto } from 'src/auth/dto/login-user.dto';
import { LoginResponseDto } from './dto/login-response.dto';
import { UsersService } from 'src/users/users.service';
import { JwtAuthGuard } from './jwt-auth.guard';
import { UserWithProfileResponseDto } from 'src/users/dto/user-info-response.dto';
import { UserInfoResponseDto } from 'src/users/dto/user-info-response.dto';
import { AuthRequest } from 'src/common/interfaces/auth-request.interface';
import { ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
import {
ApiBearerAuth,
ApiNoContentResponse,
ApiNotFoundResponse,
ApiOkResponse,
ApiOperation,
ApiTags,
} from '@nestjs/swagger';
import { CreateUserResponse } from 'src/users/dto/create-user-response.dto';
import { CheckAvailabilityResponseDto } from './dto/check-availability-response.dto';
import { CheckNameDto } from './dto/check-name.dto';
import { CheckEmailDto } from './dto/check-email.dto';
@ApiTags('인증')
@Controller('auth')
@ -19,6 +29,7 @@ export class AuthController {
) {}
@Post('signup')
@HttpCode(200)
@ApiOperation({ summary: '회원가입' })
@ApiOkResponse({ description: '성공', type: CreateUserResponse })
async signup(@Body() dto: CreateUserDto): Promise<CreateUserResponse> {
@ -30,6 +41,7 @@ export class AuthController {
}
@Post('login')
@HttpCode(200)
@ApiOperation({ summary: '로그인' })
@ApiOkResponse({ description: '성공', type: LoginResponseDto })
async login(@Body() dto: LoginUserDto): Promise<LoginResponseDto> {
@ -39,8 +51,38 @@ export class AuthController {
@Get('me')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponse({ description: '성공', type: UserWithProfileResponseDto })
async getMe(@Request() req: AuthRequest): Promise<UserWithProfileResponseDto> {
@ApiOperation({ summary: '정보 확인' })
@ApiOkResponse({ description: '성공', type: UserInfoResponseDto })
async getMe(@Request() req: AuthRequest): Promise<UserInfoResponseDto> {
return await this.userService.findUserWithProfileByIdOrFail(req.user.userId);
}
@Post('check-name')
@HttpCode(200)
@ApiOperation({ summary: '사용자 이름 중복 확인' })
@ApiOkResponse({ description: '성공', type: CheckAvailabilityResponseDto })
async checkName(@Body() dto: CheckNameDto): Promise<CheckAvailabilityResponseDto> {
const available = await this.authService.isNameAvailable(dto.name);
return { available };
}
@Post('check-email')
@HttpCode(200)
@ApiOperation({ summary: '사용자 이메일 중복 확인' })
@ApiOkResponse({ description: '성공', type: CheckAvailabilityResponseDto })
async checkEmail(@Body() dto: CheckEmailDto): Promise<CheckAvailabilityResponseDto> {
const available = await this.authService.isEmailAvailabe(dto.email);
return { available };
}
@Delete('me')
@HttpCode(204)
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOperation({ summary: '회원 탈퇴' })
@ApiNoContentResponse({ description: '탈퇴 완료' })
@ApiNotFoundResponse({ description: '존재하지 않는 사용자' })
async deleteMe(@Request() req: AuthRequest): Promise<void> {
await this.userService.softDelete(req.user.userId);
}
}

@ -35,4 +35,14 @@ export class AuthService {
},
};
}
async isNameAvailable(name: string): Promise<boolean> {
const user = await this.userService.findByName(name);
return !user;
}
async isEmailAvailabe(email: string): Promise<boolean> {
const user = await this.userService.findByEmail(email);
return !user;
}
}

@ -0,0 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
export class CheckAvailabilityResponseDto {
@ApiProperty({ description: '사용 가능 여부', example: true })
available: boolean;
}

@ -0,0 +1,9 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsNotEmpty } from 'class-validator';
export class CheckEmailDto {
@ApiProperty({ description: '사용자 이메일', example: 'user@email.com' })
@IsEmail()
@IsNotEmpty()
readonly email: string;
}

@ -0,0 +1,9 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
export class CheckNameDto {
@ApiProperty({ description: '사용자 이름', example: 'username' })
@IsString()
@IsNotEmpty()
readonly name: string;
}

@ -0,0 +1,14 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';
export class CreateProfileDto {
@ApiProperty({ description: '프로필 내용', example: 'bio...' })
@IsOptional()
@IsString()
bio?: string;
@ApiProperty({ description: '프로필 아바타 주소', example: 'http://...' })
@IsOptional()
@IsString()
avatarUrl?: string;
}

@ -0,0 +1,9 @@
import { ApiProperty } from '@nestjs/swagger';
export class ProfileResponseDto {
@ApiProperty({ description: '프로필 내용', example: 'bio...' })
bio?: string;
@ApiProperty({ description: '프로필 아바타 주소', example: 'http://...' })
avatarUrl?: string;
}

@ -7,12 +7,12 @@ export class Profile extends TimestampedEntity {
@PrimaryGeneratedColumn()
id: number;
@Column({ nullable: true })
@Column({ nullable: false, default: '' })
bio?: string;
@Column({ nullable: true })
@Column({ nullable: false, default: '' })
avatarUrl?: string;
@OneToOne(() => User, (user) => user.profile)
@OneToOne(() => User, (user) => user.profile, { onDelete: 'CASCADE' })
user: User;
}

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ProfilesController } from './profiles.controller';
describe('ProfilesController', () => {
let controller: ProfilesController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ProfilesController],
}).compile();
controller = module.get<ProfilesController>(ProfilesController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

@ -0,0 +1,26 @@
import { Body, Controller, HttpCode, Patch, Post, Request, UseGuards } from '@nestjs/common';
import { ProfilesService } from './profiles.service';
import { CreateProfileDto } from './dto/create-profile.dto';
import { ProfileResponseDto } from './dto/profile-response.dto';
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
import { ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
import { AuthRequest } from 'src/common/interfaces/auth-request.interface';
@ApiTags('사용자 프로필')
@Controller('profiles')
export class ProfilesController {
constructor(private readonly profileService: ProfilesService) {}
@Post()
@HttpCode(200)
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOperation({ summary: '프로필 생성 또는 수정' })
@ApiOkResponse({ description: '성공', type: ProfileResponseDto })
async create(
@Request() req: AuthRequest,
@Body() dto: CreateProfileDto,
): Promise<ProfileResponseDto> {
return this.profileService.createProfile(req.user.userId, dto);
}
}

@ -1,4 +1,14 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Profile } from './profile.entity';
import { ProfilesController } from './profiles.controller';
import { ProfilesService } from './profiles.service';
import { User } from 'src/users/user.entity';
@Module({})
@Module({
imports: [TypeOrmModule.forFeature([Profile, User])],
exports: [TypeOrmModule],
controllers: [ProfilesController],
providers: [ProfilesService],
})
export class ProfilesModule {}

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ProfilesService } from './profiles.service';
describe('ProfilesService', () => {
let service: ProfilesService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ProfilesService],
}).compile();
service = module.get<ProfilesService>(ProfilesService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

@ -0,0 +1,38 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Profile } from './profile.entity';
import { Repository } from 'typeorm';
import { CreateProfileDto } from './dto/create-profile.dto';
import { ProfileResponseDto } from './dto/profile-response.dto';
import { User } from 'src/users/user.entity';
@Injectable()
export class ProfilesService {
constructor(
@InjectRepository(Profile) private profileRepo: Repository<Profile>,
@InjectRepository(User) private userRepo: Repository<User>,
) {}
async createProfile(userId: number, dto: CreateProfileDto): Promise<ProfileResponseDto> {
const user = await this.userRepo.findOne({ where: { id: userId }, relations: ['profile'] });
if (!user) throw new NotFoundException('User not found');
let profile = user.profile;
if (!profile) {
profile = this.profileRepo.create({
bio: dto.bio ?? '',
avatarUrl: dto.avatarUrl ?? '',
user,
});
} else {
profile.bio = dto.bio ?? profile.bio;
profile.avatarUrl = dto.avatarUrl ?? profile.bio;
}
const saved = await this.profileRepo.save(profile);
return {
bio: saved.bio,
avatarUrl: saved.avatarUrl,
};
}
}

@ -1,4 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { ProfileResponseDto } from 'src/profiles/dto/profile-response.dto';
export class UserInfoResponseDto {
@ApiProperty({ description: '사용자 아이디', example: 1 })
@ -9,17 +10,7 @@ export class UserInfoResponseDto {
@ApiProperty({ description: '사용자 이메일', example: 'user@email.com' })
email?: string;
}
export class ProfileResponseDto {
@ApiProperty({ description: '프로필 내용', example: 'bio...' })
bio?: string;
@ApiProperty({ description: '프로필 아바타 주소', example: 'http://...' })
avatarUrl?: string;
}
export class UserWithProfileResponseDto extends UserInfoResponseDto {
@ApiProperty({ description: '프로필', type: ProfileResponseDto })
@ApiProperty({ description: '프로필', required: false, type: () => ProfileResponseDto })
profile?: ProfileResponseDto;
}

@ -1,6 +1,13 @@
import { TimestampedEntity } from 'src/common/entities/timestamped.entity';
import { Profile } from 'src/profiles/profile.entity';
import { Column, Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
import {
Column,
DeleteDateColumn,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
@Entity()
export class User extends TimestampedEntity {
@ -18,5 +25,8 @@ export class User extends TimestampedEntity {
@OneToOne(() => Profile, (profile) => profile.user, { cascade: true })
@JoinColumn() // FK Owner
profile: Profile;
profile?: Profile;
@DeleteDateColumn({ type: 'timestamp' })
deletedAt?: Date;
}

@ -10,7 +10,7 @@ import { Repository } from 'typeorm';
import { CreateUserDto } from './dto/create-user.dto';
import { ChangePasswordDto } from './dto/change-password.dto';
import * as bcrypt from 'bcryptjs';
import { UserInfoResponseDto, UserWithProfileResponseDto } from './dto/user-info-response.dto';
import { UserInfoResponseDto } from './dto/user-info-response.dto';
@Injectable()
export class UsersService {
@ -49,6 +49,13 @@ export class UsersService {
await this.repo.save(user);
}
async softDelete(userId: number): Promise<void> {
const user = await this.repo.findOne({ where: { id: userId } });
if (!user) throw new NotFoundException('User not found');
await this.repo.softDelete(userId);
}
async findUserInfoByIdOrFail(id: number): Promise<UserInfoResponseDto> {
const user = await this.findById(id);
if (!user) throw new NotFoundException('User not found');
@ -60,7 +67,7 @@ export class UsersService {
};
}
async findUserWithProfileByIdOrFail(id: number): Promise<UserWithProfileResponseDto> {
async findUserWithProfileByIdOrFail(id: number): Promise<UserInfoResponseDto> {
const user = await this.repo.findOne({ where: { id }, relations: ['profile'] });
if (!user) throw new NotFoundException('User not found');

Loading…
Cancel
Save