Skip to content

Commit

Permalink
API: create admin user
Browse files Browse the repository at this point in the history
  • Loading branch information
Byunk committed Jan 9, 2024
1 parent 28ad0b7 commit e3fa998
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/controller/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ class UserController {
res.json(users);
};

createAdmin = async (req: Request, res: Response, next: NextFunction) => {
logger.info('UserController: createAdmin called');

const email = req.body.email;
const password = req.body.password;
const user = await this.userService.createAdmin(email, password);
res.json(user);
};

createUser = async (req: Request, res: Response, next: NextFunction) => {
logger.info('UserController: createUser called');

Expand Down
8 changes: 8 additions & 0 deletions src/repository/user.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ class UserRepository {
OrganizationId: organizationId,
});
}

async createAdmin(email: string, password: string) {
return User.create({
email,
password,
role: 'admin',
});
}
}

export { UserRepository };
7 changes: 7 additions & 0 deletions src/routes/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ export function createUsersRouter() {
wrapAsync(userController.findAll),
);

// 관리자 계정 생성
router.post(
'/admin',
wrapAsync(validateIsAdmin),
wrapAsync(userController.createAdmin),
);

// 계정 생성
// TODO: email sanitize (kaist email만 가능하도록)
router.post('/', wrapAsync(userController.createUser));
Expand Down
28 changes: 28 additions & 0 deletions src/service/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,24 @@ class UserService {
return userReponse;
}

async createAdmin(email: string, password: string) {
const user = await this.userRepository.findByEmail(email);
if (user) {
throw new DuplicateError('이미 등록된 이메일이 존재합니다.');
}

const encryptedPassword = await this.passwordService.encrypt(password);
const admin = await this.userRepository.createAdmin(
email,
encryptedPassword,
);
logger.info(`Admin: ${email} created`);
return {
email: admin.email,
role: admin.role,
};
}

async create(dto: CreateUserDto) {
await this.checkDuplicate(dto);

Expand Down Expand Up @@ -111,11 +129,21 @@ class UserService {

async login(dto: LoginDto) {
const user = await this.findUserByEmailOrThrow(dto.email);
if (user.isDisabled) {
throw new UnauthorizedError('비활성화된 계정입니다.');
}

await this.matchPassword(dto.password, user.password);

logger.info(`User: ${dto.email} logged in`);

if (user.role === 'admin') {
return {
id: user.id,
email: user.email,
role: user.role,
};
}
const organization = await this.findOrganizationByIdOrThrow(
user.OrganizationId,
);
Expand Down
39 changes: 39 additions & 0 deletions swagger/routes/user.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,45 @@ paths:
description: BadRequestError. 비밀번호는 8자 이상 12자 이하여야 합니다.
'409':
description: ValidationError. 이미 존재하는 이메일입니다.
/users/admin:
post:
description: 관리자 계정 생성 (관리자만 호출 가능)
tags:
- 계정
requestBody:
content:
application/json:
schema:
type: object
properties:
email:
type: string
description: 이메일
example: [email protected]
password:
type: string
description: 비밀번호
example: password
required:
- email
- password
responses:
'200':
content:
application/json:
schema:
type: object
properties:
email:
type: string
description: 이메일
example: [email protected]
role:
type: string
description: 권한
example: admin
'409':
description: DuplicateError. 이미 존재하는 이메일입니다.
/users/login:
post:
description: 로그인. 세션 생성.
Expand Down
8 changes: 8 additions & 0 deletions test/mock/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,11 @@ export function createMockUser3(organizationId: number | string) {
OrganizationId: organizationId,
};
}

export function createMockAdmin() {
return {
email: '[email protected]',
password: mockPassword,
role: 'admin',
};
}
16 changes: 16 additions & 0 deletions test/routes/user.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,22 @@ describe('API /users', function () {
expect(res.body.organization_id).to.equal(organization.id);
});

it('새로운 관리자 계정을 추가할 수 있다.', async function () {
let res = await chai.request(app).post('/users/admin').send({
email: Mock.mockEmail1,
password: Mock.mockPassword,
});
expect(res.status).to.equal(200);
expect(res.body.email).to.equal(Mock.mockEmail1);
expect(res.body.role).to.equal('admin');

res = await chai.request(app).post('/users/login').send({
email: Mock.mockEmail1,
password: Mock.mockPassword,
});
expect(res.status).to.equal(200);
});

it('이미 등록된 피감기구의 계정을 추가할 수 없다.', async function () {
const organization = await model.Organization.create(
Mock.mockOrganization1,
Expand Down

0 comments on commit e3fa998

Please sign in to comment.