Merged PR 495: API作成(バージョン更新API)
## 概要 [Task2804: API作成(バージョン更新API)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2804) 同意済み利用規約バージョン更新APIを実装しました。 ## レビューポイント なし ## UIの変更 なし ## 動作確認状況 UT,ローカルで動作確認済み ## 補足 なし
This commit is contained in:
parent
162470838d
commit
273ba588ce
@ -2,10 +2,12 @@ import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { UsersController } from './users.controller';
|
||||
import { UsersService } from './users.service';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { AuthService } from '../auth/auth.service';
|
||||
|
||||
describe('UsersController', () => {
|
||||
let controller: UsersController;
|
||||
const mockUserService = {};
|
||||
const mockAuthService = {};
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
@ -16,10 +18,12 @@ describe('UsersController', () => {
|
||||
}),
|
||||
],
|
||||
controllers: [UsersController],
|
||||
providers: [UsersService],
|
||||
providers: [UsersService, AuthService],
|
||||
})
|
||||
.overrideProvider(UsersService)
|
||||
.useValue(mockUserService)
|
||||
.overrideProvider(AuthService)
|
||||
.useValue(mockAuthService)
|
||||
.compile();
|
||||
|
||||
controller = module.get<UsersController>(UsersController);
|
||||
|
||||
@ -41,6 +41,7 @@ import {
|
||||
UpdateAcceptedVersionResponse,
|
||||
} from './types/types';
|
||||
import { UsersService } from './users.service';
|
||||
import { AuthService } from '../auth/auth.service';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { AuthGuard } from '../../common/guards/auth/authguards';
|
||||
import {
|
||||
@ -56,7 +57,10 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
@ApiTags('users')
|
||||
@Controller('users')
|
||||
export class UsersController {
|
||||
constructor(private readonly usersService: UsersService) {}
|
||||
constructor(
|
||||
private readonly usersService: UsersService,
|
||||
private readonly authService: AuthService,
|
||||
) {}
|
||||
|
||||
@ApiResponse({
|
||||
status: HttpStatus.OK,
|
||||
@ -495,11 +499,24 @@ export class UsersController {
|
||||
async updateAcceptedVersion(
|
||||
@Body() body: UpdateAcceptedVersionRequest,
|
||||
): Promise<UpdateAcceptedVersionResponse> {
|
||||
const context = makeContext(uuidv4());
|
||||
const { idToken, acceptedEULAVersion, acceptedDPAVersion } = body;
|
||||
|
||||
// TODO 仮実装。API実装タスクで本実装する。
|
||||
// const idToken = await this.authService.getVerifiedIdToken(body.idToken);
|
||||
// await this.usersService.updateAcceptedVersion(context, idToken);
|
||||
const verifiedIdToken = await this.authService.getVerifiedIdToken(idToken);
|
||||
const context = makeContext(verifiedIdToken.sub);
|
||||
|
||||
const isVerified = await this.authService.isVerifiedUser(verifiedIdToken);
|
||||
if (!isVerified) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E010201'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
await this.usersService.updateAcceptedVersion(
|
||||
context,
|
||||
verifiedIdToken.sub,
|
||||
acceptedEULAVersion,
|
||||
acceptedDPAVersion,
|
||||
);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import { UsersRepositoryModule } from '../../repositories/users/users.repository
|
||||
import { LicensesRepositoryModule } from '../../repositories/licenses/licenses.repository.module';
|
||||
import { UsersController } from './users.controller';
|
||||
import { UsersService } from './users.service';
|
||||
import { AuthService } from '../auth/auth.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -18,6 +19,6 @@ import { UsersService } from './users.service';
|
||||
ConfigModule,
|
||||
],
|
||||
controllers: [UsersController],
|
||||
providers: [UsersService],
|
||||
providers: [UsersService, AuthService],
|
||||
})
|
||||
export class UsersModule {}
|
||||
|
||||
@ -43,6 +43,7 @@ import {
|
||||
makeTestSimpleAccount,
|
||||
makeTestUser,
|
||||
} from '../../common/test/utility';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
describe('UsersService.confirmUser', () => {
|
||||
let source: DataSource = null;
|
||||
@ -2480,3 +2481,91 @@ describe('UsersService.updateUser', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('UsersService.updateAcceptedVersion', () => {
|
||||
let source: DataSource = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
database: ':memory:',
|
||||
logging: false,
|
||||
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
|
||||
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
|
||||
});
|
||||
return source.initialize();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('同意済み利用規約バージョンを更新できる(第五)', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
const { admin } = await makeTestAccount(source, {
|
||||
tier: 5,
|
||||
});
|
||||
const context = makeContext(uuidv4());
|
||||
|
||||
const service = module.get<UsersService>(UsersService);
|
||||
await service.updateAcceptedVersion(context, admin.external_id, 'v2.0');
|
||||
const user = await getUser(source, admin.id);
|
||||
|
||||
expect(user.accepted_eula_version).toBe('v2.0');
|
||||
});
|
||||
|
||||
it('同意済み利用規約バージョンを更新できる(第一~第四)', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
const { admin } = await makeTestAccount(source, {
|
||||
tier: 4,
|
||||
});
|
||||
const context = makeContext(uuidv4());
|
||||
|
||||
const service = module.get<UsersService>(UsersService);
|
||||
await service.updateAcceptedVersion(
|
||||
context,
|
||||
admin.external_id,
|
||||
'v2.0',
|
||||
'v3.0',
|
||||
);
|
||||
const user = await getUser(source, admin.id);
|
||||
|
||||
expect(user.accepted_eula_version).toBe('v2.0');
|
||||
expect(user.accepted_dpa_version).toBe('v3.0');
|
||||
});
|
||||
|
||||
it('パラメータが不在のときエラーとなる(第五)', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
const { admin } = await makeTestAccount(source, {
|
||||
tier: 5,
|
||||
});
|
||||
const context = makeContext(uuidv4());
|
||||
|
||||
const service = module.get<UsersService>(UsersService);
|
||||
await expect(
|
||||
service.updateAcceptedVersion(context, admin.external_id, undefined),
|
||||
).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E010001'), HttpStatus.BAD_REQUEST),
|
||||
);
|
||||
});
|
||||
|
||||
it('パラメータが不在のときエラーとなる(第一~第四)', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
const { admin } = await makeTestAccount(source, {
|
||||
tier: 4,
|
||||
});
|
||||
const context = makeContext(uuidv4());
|
||||
|
||||
const service = module.get<UsersService>(UsersService);
|
||||
await expect(
|
||||
service.updateAcceptedVersion(
|
||||
context,
|
||||
admin.external_id,
|
||||
'v2.0',
|
||||
undefined,
|
||||
),
|
||||
).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E010001'), HttpStatus.BAD_REQUEST),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -4,7 +4,7 @@ import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
import { isVerifyError, verify } from '../../common/jwt';
|
||||
import { getPublicKey } from '../../common/jwt/jwt';
|
||||
import { makePassword } from '../../common/password/password';
|
||||
import { AccessToken } from '../../common/token';
|
||||
import { AccessToken, IDToken } from '../../common/token';
|
||||
import {
|
||||
SortDirection,
|
||||
TaskListSortableAttribute,
|
||||
@ -30,6 +30,7 @@ import {
|
||||
EmailAlreadyVerifiedError,
|
||||
EncryptionPasswordNeedError,
|
||||
InvalidRoleChangeError,
|
||||
UpdateTermsVersionNotSetError,
|
||||
UserNotFoundError,
|
||||
} from '../../repositories/users/errors/types';
|
||||
import {
|
||||
@ -967,4 +968,58 @@ export class UsersService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意済み利用規約バージョンを更新する
|
||||
* @param context
|
||||
* @param idToken
|
||||
* @param eulaVersion
|
||||
* @param dpaVersion
|
||||
*/
|
||||
async updateAcceptedVersion(
|
||||
context: Context,
|
||||
externalId: string,
|
||||
eulaVersion: string,
|
||||
dpaVersion?: string,
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.updateAcceptedVersion.name} | params: { ` +
|
||||
`externalId: ${externalId}, ` +
|
||||
`eulaVersion: ${eulaVersion}, ` +
|
||||
`dpaVersion: ${dpaVersion}, };`,
|
||||
);
|
||||
|
||||
try {
|
||||
await this.usersRepository.updateAcceptedTermsVersion(
|
||||
externalId,
|
||||
eulaVersion,
|
||||
dpaVersion,
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.error(`[${context.trackingId}] error=${e}`);
|
||||
if (e instanceof Error) {
|
||||
switch (e.constructor) {
|
||||
case UserNotFoundError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E010204'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
case UpdateTermsVersionNotSetError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E010001'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
default:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.logger.log(
|
||||
`[OUT] [${context.trackingId}] ${this.updateAcceptedVersion.name}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,3 +10,5 @@ export class InvalidRoleChangeError extends Error {}
|
||||
export class EncryptionPasswordNeedError extends Error {}
|
||||
// 利用規約バージョン情報不在エラー
|
||||
export class TermInfoNotFoundError extends Error {}
|
||||
// 利用規約バージョンパラメータ不在エラー
|
||||
export class UpdateTermsVersionNotSetError extends Error {}
|
||||
|
||||
@ -13,6 +13,7 @@ import {
|
||||
InvalidRoleChangeError,
|
||||
EncryptionPasswordNeedError,
|
||||
TermInfoNotFoundError,
|
||||
UpdateTermsVersionNotSetError,
|
||||
} from './errors/types';
|
||||
import {
|
||||
LICENSE_ALLOCATED_STATUS,
|
||||
@ -475,4 +476,49 @@ export class UsersRepositoryService {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意済み利用規約のバージョンを更新する
|
||||
* @param externalId
|
||||
* @param eulaVersion
|
||||
* @param dpaVersion
|
||||
* @returns update
|
||||
*/
|
||||
async updateAcceptedTermsVersion(
|
||||
externalId: string,
|
||||
eulaVersion: string,
|
||||
dpaVersion: string | undefined,
|
||||
): Promise<void> {
|
||||
await this.dataSource.transaction(async (entityManager) => {
|
||||
const userRepo = entityManager.getRepository(User);
|
||||
const user = await userRepo.findOne({
|
||||
where: {
|
||||
external_id: externalId,
|
||||
},
|
||||
relations: {
|
||||
account: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new UserNotFoundError(
|
||||
`User not found. externalId: ${externalId}`,
|
||||
);
|
||||
}
|
||||
|
||||
// パラメータが不在の場合はエラーを返却
|
||||
if (!eulaVersion) {
|
||||
throw new UpdateTermsVersionNotSetError(`EULA version param not set.`);
|
||||
}
|
||||
if (user.account.tier !== TIERS.TIER5 && !dpaVersion) {
|
||||
throw new UpdateTermsVersionNotSetError(
|
||||
`DPA version param not set. User's tier: ${user.account.tier}`,
|
||||
);
|
||||
}
|
||||
|
||||
user.accepted_eula_version = eulaVersion;
|
||||
user.accepted_dpa_version = dpaVersion ?? user.accepted_dpa_version;
|
||||
await userRepo.update({ id: user.id }, user);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user