Merged PR 489: API作成(利用規約情報取得API)
## 概要 [Task2808: API作成(利用規約情報取得API)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2808) 利用規約情報取得APIを作成しました。 ## レビューポイント なし ## UIの変更 なし ## 動作確認状況 UT、ローカルで動作確認済み ## 補足 なし
This commit is contained in:
parent
69ff6f3432
commit
162470838d
@ -34,6 +34,9 @@ import { TemplatesService } from '../../features/templates/templates.service';
|
||||
import { TemplatesModule } from '../../features/templates/templates.module';
|
||||
import { WorkflowsService } from '../../features/workflows/workflows.service';
|
||||
import { WorkflowsModule } from '../../features/workflows/workflows.module';
|
||||
import { TermsService } from '../../features/terms/terms.service';
|
||||
import { TermsRepositoryModule } from '../../repositories/terms/terms.repository.module';
|
||||
import { TermsModule } from '../../features/terms/terms.module';
|
||||
|
||||
export const makeTestingModule = async (
|
||||
datasource: DataSource,
|
||||
@ -56,6 +59,7 @@ export const makeTestingModule = async (
|
||||
LicensesModule,
|
||||
TemplatesModule,
|
||||
WorkflowsModule,
|
||||
TermsModule,
|
||||
AccountsRepositoryModule,
|
||||
UsersRepositoryModule,
|
||||
LicensesRepositoryModule,
|
||||
@ -71,6 +75,7 @@ export const makeTestingModule = async (
|
||||
AuthGuardsModule,
|
||||
SortCriteriaRepositoryModule,
|
||||
WorktypesRepositoryModule,
|
||||
TermsRepositoryModule,
|
||||
],
|
||||
providers: [
|
||||
AuthService,
|
||||
@ -82,6 +87,7 @@ export const makeTestingModule = async (
|
||||
LicensesService,
|
||||
TemplatesService,
|
||||
WorkflowsService,
|
||||
TermsService,
|
||||
],
|
||||
})
|
||||
.useMocker(async (token) => {
|
||||
|
||||
@ -6,11 +6,14 @@ describe('TermsController', () => {
|
||||
let controller: TermsController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockTermsService = {};
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [TermsController],
|
||||
providers: [TermsService],
|
||||
}).compile();
|
||||
|
||||
})
|
||||
.overrideProvider(TermsService)
|
||||
.useValue(mockTermsService)
|
||||
.compile();
|
||||
controller = module.get<TermsController>(TermsController);
|
||||
});
|
||||
|
||||
|
||||
@ -28,12 +28,7 @@ export class TermsController {
|
||||
async getTermsInfo(): Promise<GetTermsInfoResponse> {
|
||||
const context = makeContext(uuidv4());
|
||||
|
||||
// TODO 仮実装。API実装タスクで本実装する。
|
||||
// const termInfo = await this.termsService.getTermsInfo(context);
|
||||
const termsInfo = [
|
||||
{ documentType: 'EULA', version: '1.0' },
|
||||
{ documentType: 'DPA', version: '1.1' },
|
||||
] as TermInfo[];
|
||||
const termsInfo = await this.termsService.getTermsInfo(context);
|
||||
|
||||
return { termsInfo };
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TermsController } from './terms.controller';
|
||||
import { TermsService } from './terms.service';
|
||||
import { TermsRepositoryModule } from '../../repositories/terms/terms.repository.module';
|
||||
|
||||
@Module({
|
||||
imports: [TermsRepositoryModule],
|
||||
controllers: [TermsController],
|
||||
providers: [TermsService]
|
||||
providers: [TermsService],
|
||||
})
|
||||
export class TermsModule {}
|
||||
|
||||
@ -1,18 +1,83 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { TermsService } from './terms.service';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { makeTestingModule } from '../../common/test/modules';
|
||||
import { createTermInfo } from '../auth/test/utility';
|
||||
import { makeContext } from '../../common/log';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
|
||||
describe('TermsService', () => {
|
||||
let service: TermsService;
|
||||
|
||||
describe('利用規約取得', () => {
|
||||
let source: DataSource = null;
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [TermsService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<TermsService>(TermsService);
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
database: ':memory:',
|
||||
logging: false,
|
||||
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
|
||||
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
|
||||
});
|
||||
return source.initialize();
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
afterEach(async () => {
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('最新の利用規約情報が取得できる', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
const service = module.get<TermsService>(TermsService);
|
||||
|
||||
await createTermInfo(source, 'EULA', 'v1.0');
|
||||
await createTermInfo(source, 'EULA', 'v1.1');
|
||||
await createTermInfo(source, 'DPA', 'v1.0');
|
||||
await createTermInfo(source, 'DPA', 'v1.2');
|
||||
|
||||
const context = makeContext(uuidv4());
|
||||
const result = await service.getTermsInfo(context);
|
||||
|
||||
expect(result[0].documentType).toBe('EULA');
|
||||
expect(result[0].version).toBe('v1.1');
|
||||
expect(result[1].documentType).toBe('DPA');
|
||||
expect(result[1].version).toBe('v1.2');
|
||||
});
|
||||
|
||||
it('利用規約情報(EULA、DPA両方)が存在しない場合エラーとなる', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
const service = module.get<TermsService>(TermsService);
|
||||
const context = makeContext(uuidv4());
|
||||
await expect(service.getTermsInfo(context)).rejects.toEqual(
|
||||
new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('利用規約情報(EULAのみ)が存在しない場合エラーとなる', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
const service = module.get<TermsService>(TermsService);
|
||||
await createTermInfo(source, 'DPA', 'v1.0');
|
||||
const context = makeContext(uuidv4());
|
||||
await expect(service.getTermsInfo(context)).rejects.toEqual(
|
||||
new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('利用規約情報(DPAのみ)が存在しない場合エラーとなる', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
const service = module.get<TermsService>(TermsService);
|
||||
await createTermInfo(source, 'EULA', 'v1.0');
|
||||
const context = makeContext(uuidv4());
|
||||
await expect(service.getTermsInfo(context)).rejects.toEqual(
|
||||
new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,44 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
|
||||
import { Context } from '../../common/log';
|
||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
import { TermInfo } from './types/types';
|
||||
import { TermsRepositoryService } from '../../repositories/terms/terms.repository.service';
|
||||
import { TERM_TYPE } from '../../constants';
|
||||
|
||||
@Injectable()
|
||||
export class TermsService {}
|
||||
export class TermsService {
|
||||
constructor(private readonly termsRepository: TermsRepositoryService) {}
|
||||
private readonly logger = new Logger(TermsService.name);
|
||||
|
||||
/**
|
||||
* 利用規約情報を取得する
|
||||
* return termsInfo
|
||||
*/
|
||||
async getTermsInfo(context: Context): Promise<TermInfo[]> {
|
||||
this.logger.log(`[IN] [${context.trackingId}] ${this.getTermsInfo.name}`);
|
||||
try {
|
||||
const { eulaVersion, dpaVersion } =
|
||||
await this.termsRepository.getLatestTermsInfo();
|
||||
return [
|
||||
{
|
||||
documentType: TERM_TYPE.EULA,
|
||||
version: eulaVersion,
|
||||
},
|
||||
{
|
||||
documentType: TERM_TYPE.DPA,
|
||||
version: dpaVersion,
|
||||
},
|
||||
];
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
} finally {
|
||||
this.logger.log(
|
||||
`[OUT] [${context.trackingId}] ${this.getTermsInfo.name}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,3 +10,8 @@ export class GetTermsInfoResponse {
|
||||
@ApiProperty({ type: [TermInfo] })
|
||||
termsInfo: TermInfo[];
|
||||
}
|
||||
|
||||
export type TermsVersion = {
|
||||
eulaVersion: string;
|
||||
dpaVersion: string;
|
||||
};
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Term } from './entity/term.entity';
|
||||
import { TermsRepositoryService } from './terms.repository.service';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Term])],
|
||||
providers: [TermsRepositoryService],
|
||||
exports: [TermsRepositoryService],
|
||||
})
|
||||
export class TermsRepositoryModule {}
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { TermsVersion } from '../../features/terms/types/types';
|
||||
import { Term } from './entity/term.entity';
|
||||
import { TERM_TYPE } from '../../constants';
|
||||
import { TermInfoNotFoundError } from '../users/errors/types';
|
||||
|
||||
@Injectable()
|
||||
export class TermsRepositoryService {
|
||||
constructor(private dataSource: DataSource) {}
|
||||
|
||||
/*
|
||||
* 利用規約の最新バージョンを取得する
|
||||
* @returns Term[]
|
||||
*/
|
||||
async getLatestTermsInfo(): Promise<TermsVersion> {
|
||||
return await this.dataSource.transaction(async (entityManager) => {
|
||||
const termRepo = entityManager.getRepository(Term);
|
||||
const latestEulaInfo = await termRepo.findOne({
|
||||
where: {
|
||||
document_type: TERM_TYPE.EULA,
|
||||
},
|
||||
order: {
|
||||
id: 'DESC',
|
||||
},
|
||||
});
|
||||
const latestDpaInfo = await termRepo.findOne({
|
||||
where: {
|
||||
document_type: TERM_TYPE.DPA,
|
||||
},
|
||||
order: {
|
||||
id: 'DESC',
|
||||
},
|
||||
});
|
||||
|
||||
if (!latestEulaInfo || !latestDpaInfo) {
|
||||
throw new TermInfoNotFoundError(
|
||||
`Terms info is not found. latestEulaInfo: ${latestEulaInfo}, latestDpaInfo: ${latestDpaInfo}`,
|
||||
);
|
||||
}
|
||||
return {
|
||||
eulaVersion: latestEulaInfo.version,
|
||||
dpaVersion: latestDpaInfo.version,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user