Merged PR 323: アカウント登録APIを修正
## 概要 [Task2353: アカウント登録APIを修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2353) - アカウント登録時にコンテナを作成するように修正 - ログ追加 - リクエストのバリデータを追加 ## レビューポイント - 処理の流れに問題はないか - テストケースに不足はないか - バリデータに問題はないか ## UIの変更 - なし ## 動作確認状況 - ローカルで確認
This commit is contained in:
parent
ba81bc5cb8
commit
ad969bd2cf
@ -1,7 +1,7 @@
|
||||
import { Context } from './types';
|
||||
|
||||
export const makeContext = (externaiId: string): Context => {
|
||||
export const makeContext = (externalId: string): Context => {
|
||||
return {
|
||||
trackingId: externaiId,
|
||||
trackingId: externalId,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { Context } from '../log';
|
||||
import {
|
||||
AdB2cService,
|
||||
ConflictError,
|
||||
@ -5,6 +6,7 @@ import {
|
||||
import { SendGridService } from '../../gateways/sendgrid/sendgrid.service';
|
||||
import { User, newUser } from '../../repositories/users/entity/user.entity';
|
||||
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
|
||||
import { BlobstorageService } from '../../gateways/blobstorage/blobstorage.service';
|
||||
|
||||
// ### ユニットテスト用コード以外では絶対に使用してはいけないダーティな手段を使用しているが、他の箇所では使用しないこと ###
|
||||
|
||||
@ -18,6 +20,7 @@ export const overrideAdB2cService = <TService>(
|
||||
service: TService,
|
||||
overrides: {
|
||||
createUser?: (
|
||||
context: Context,
|
||||
email: string,
|
||||
password: string,
|
||||
username: string,
|
||||
@ -44,6 +47,7 @@ export const overrideSendgridService = <TService>(
|
||||
service: TService,
|
||||
overrides: {
|
||||
createMailContentFromEmailConfirm?: (
|
||||
context: Context,
|
||||
accountId: number,
|
||||
userId: number,
|
||||
email: string,
|
||||
@ -54,6 +58,7 @@ export const overrideSendgridService = <TService>(
|
||||
email: string,
|
||||
) => Promise<{ subject: string; text: string; html: string }>;
|
||||
sendMail?: (
|
||||
context: Context,
|
||||
to: string,
|
||||
from: string,
|
||||
subject: string,
|
||||
@ -121,3 +126,29 @@ export const overrideUsersRepositoryService = <TService>(
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* blobStorageServiceのモックを作成して、TServiceが依存するサービス(blobStorageService)の参照を上書きする
|
||||
* ※ serviceに指定するオブジェクトは`blobstorageService: blobStorageService`メンバ変数を持つ必要がある
|
||||
* @param service 上書きしたいTService
|
||||
* @param overrides blobStorageServiceの各種メソッドのモックが返す値(省略した場合は既定のダミーの値)
|
||||
*/
|
||||
export const overrideBlobstorageService = <TService>(
|
||||
service: TService,
|
||||
overrides: {
|
||||
createContainer?: (
|
||||
context: Context,
|
||||
accountId: number,
|
||||
country: string,
|
||||
) => Promise<void>;
|
||||
},
|
||||
): void => {
|
||||
// テストコードでのみ許される強引な方法でprivateメンバ変数の参照を取得
|
||||
const obj = (service as any).blobStorageService as BlobstorageService;
|
||||
if (overrides.createContainer) {
|
||||
Object.defineProperty(obj, obj.createContainer.name, {
|
||||
value: overrides.createContainer,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
31
dictation_server/src/common/validators/admin.validator.ts
Normal file
31
dictation_server/src/common/validators/admin.validator.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { registerDecorator, ValidationOptions } from 'class-validator';
|
||||
|
||||
export const IsAdminPasswordvalid = (validationOptions?: ValidationOptions) => {
|
||||
return (object: any, propertyName: string) => {
|
||||
registerDecorator({
|
||||
name: 'IsAdminPasswordvalid',
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
constraints: [],
|
||||
options: validationOptions,
|
||||
validator: {
|
||||
validate: (value: string) => {
|
||||
// 8文字~64文字でなければ早期に不合格
|
||||
const minLength = 8;
|
||||
const maxLength = 64;
|
||||
if (value.length < minLength || value.length > maxLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 英字の大文字、英字の小文字、アラビア数字、記号(@#$%^&*\-_+=[]{}|\:',.?/`~"();!)から2種類以上組み合わせ
|
||||
const charaTypePattern =
|
||||
/^((?=.*[a-z])(?=.*[A-Z])|(?=.*[a-z])(?=.*[\d])|(?=.*[a-z])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!])|(?=.*[A-Z])(?=.*[\d])|(?=.*[A-Z])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!])|(?=.*[\d])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!]))[a-zA-Z\d@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!]/;
|
||||
return new RegExp(charaTypePattern).test(value);
|
||||
},
|
||||
defaultMessage: () => {
|
||||
return 'Admin password rule not satisfied';
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
};
|
||||
@ -41,6 +41,7 @@ import { retrieveAuthorizationToken } from '../../common/http/helper';
|
||||
import { AccessToken } from '../../common/token';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { makeContext } from '../../common/log';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
@ApiTags('accounts')
|
||||
@Controller('accounts')
|
||||
@ -80,7 +81,10 @@ export class AccountsController {
|
||||
} = body;
|
||||
const role = USER_ROLES.NONE;
|
||||
|
||||
const context = makeContext(uuidv4());
|
||||
|
||||
await this.accountService.createAccount(
|
||||
context,
|
||||
companyName,
|
||||
country,
|
||||
dealerAccountId,
|
||||
@ -277,7 +281,10 @@ export class AccountsController {
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
|
||||
const context = makeContext(payload.userId);
|
||||
|
||||
await this.accountService.createPartnerAccount(
|
||||
context,
|
||||
companyName,
|
||||
country,
|
||||
email,
|
||||
|
||||
@ -7,6 +7,7 @@ import { AccountsController } from './accounts.controller';
|
||||
import { AccountsService } from './accounts.service';
|
||||
import { AdB2cModule } from '../../gateways/adb2c/adb2c.module';
|
||||
import { UserGroupsRepositoryModule } from '../../repositories/user_groups/user_groups.repository.module';
|
||||
import { BlobstorageModule } from '../../gateways/blobstorage/blobstorage.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -16,6 +17,7 @@ import { UserGroupsRepositoryModule } from '../../repositories/user_groups/user_
|
||||
UserGroupsRepositoryModule,
|
||||
SendGridModule,
|
||||
AdB2cModule,
|
||||
BlobstorageModule,
|
||||
],
|
||||
controllers: [AccountsController],
|
||||
providers: [AccountsService],
|
||||
|
||||
@ -2,6 +2,7 @@ import { HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
import {
|
||||
makeAccountsServiceMock,
|
||||
makeBlobStorageServiceMockValue,
|
||||
makeDefaultAccountsRepositoryMockValue,
|
||||
makeDefaultAdB2cMockValue,
|
||||
makeDefaultLicensesRepositoryMockValue,
|
||||
@ -29,6 +30,7 @@ import { TIERS } from '../../constants';
|
||||
import { License } from '../../repositories/licenses/entity/license.entity';
|
||||
import {
|
||||
overrideAdB2cService,
|
||||
overrideBlobstorageService,
|
||||
overrideSendgridService,
|
||||
} from '../../common/test/overrides';
|
||||
|
||||
@ -61,7 +63,7 @@ describe('createAccount', () => {
|
||||
const email = 'dummy@dummy.dummy';
|
||||
const password = 'dummy_password';
|
||||
const username = 'dummy_username';
|
||||
const role = 'admin none';
|
||||
const role = 'none';
|
||||
const acceptedTermsVersion = '1.0.0';
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
@ -69,6 +71,7 @@ describe('createAccount', () => {
|
||||
return { sub: externalId };
|
||||
},
|
||||
});
|
||||
|
||||
overrideSendgridService(service, {
|
||||
sendMail: async () => {
|
||||
return;
|
||||
@ -77,8 +80,12 @@ describe('createAccount', () => {
|
||||
return { html: '', text: '', subject: '' };
|
||||
},
|
||||
});
|
||||
overrideBlobstorageService(service, {
|
||||
createContainer: async () => {},
|
||||
});
|
||||
|
||||
const { accountId, externalUserId, userId } = await service.createAccount(
|
||||
makeContext('uuid'),
|
||||
companyName,
|
||||
country,
|
||||
dealerAccountId,
|
||||
@ -135,8 +142,17 @@ describe('createAccount', () => {
|
||||
const role = 'admin none';
|
||||
const acceptedTermsVersion = '1.0.0';
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async () => {
|
||||
throw new Error();
|
||||
},
|
||||
});
|
||||
overrideSendgridService(service, {});
|
||||
overrideBlobstorageService(service, {});
|
||||
|
||||
try {
|
||||
await service.createAccount(
|
||||
makeContext('uuid'),
|
||||
companyName,
|
||||
country,
|
||||
dealerAccountId,
|
||||
@ -191,8 +207,18 @@ describe('createAccount', () => {
|
||||
const role = 'admin none';
|
||||
const acceptedTermsVersion = '1.0.0';
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async () => {
|
||||
// EmailのConflictエラーを返す
|
||||
return { reason: 'email', message: 'dummy' };
|
||||
},
|
||||
});
|
||||
overrideSendgridService(service, {});
|
||||
overrideBlobstorageService(service, {});
|
||||
|
||||
try {
|
||||
await service.createAccount(
|
||||
makeContext('uuid'),
|
||||
companyName,
|
||||
country,
|
||||
dealerAccountId,
|
||||
@ -217,6 +243,54 @@ describe('createAccount', () => {
|
||||
const users = await getUsers(source);
|
||||
expect(users.length).toBe(0);
|
||||
});
|
||||
|
||||
it('アカウントを作成がBlobStorageへの通信失敗によって失敗すると500エラーが発生する', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
|
||||
const externalId = 'test_external_id';
|
||||
const companyName = 'test_company_name';
|
||||
const country = 'US';
|
||||
const dealerAccountId = 1;
|
||||
const email = 'dummy@dummy.dummy';
|
||||
const password = 'dummy_password';
|
||||
const username = 'dummy_username';
|
||||
const role = 'none';
|
||||
const acceptedTermsVersion = '1.0.0';
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async () => {
|
||||
return { sub: externalId };
|
||||
},
|
||||
});
|
||||
overrideSendgridService(service, {});
|
||||
overrideBlobstorageService(service, {
|
||||
createContainer: async () => {
|
||||
throw new Error();
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await service.createAccount(
|
||||
makeContext('uuid'),
|
||||
companyName,
|
||||
country,
|
||||
dealerAccountId,
|
||||
email,
|
||||
password,
|
||||
username,
|
||||
role,
|
||||
acceptedTermsVersion,
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
|
||||
} else {
|
||||
expect(true).toBe(false); // ここには来てはいけない
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('AccountsService', () => {
|
||||
@ -230,6 +304,7 @@ describe('AccountsService', () => {
|
||||
makeDefaultAccountsRepositoryMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -239,6 +314,7 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
expect(await service.getLicenseSummary(accountId)).toEqual(
|
||||
@ -257,6 +333,7 @@ describe('AccountsService', () => {
|
||||
accountsRepositoryMockValue.getLicenseSummaryInfo = null;
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -266,6 +343,7 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
await expect(service.getLicenseSummary(accountId)).rejects.toEqual(
|
||||
@ -286,6 +364,7 @@ describe('AccountsService', () => {
|
||||
makeDefaultAccountsRepositoryMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -295,6 +374,7 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
expect(await service.getTypists(externalId)).toEqual([
|
||||
@ -314,6 +394,7 @@ describe('AccountsService', () => {
|
||||
makeDefaultAccountsRepositoryMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -323,6 +404,7 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
await expect(service.getTypists(externalId)).rejects.toEqual(
|
||||
@ -343,6 +425,7 @@ describe('AccountsService', () => {
|
||||
makeDefaultAccountsRepositoryMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -352,6 +435,7 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
await expect(service.getTypists(externalId)).rejects.toEqual(
|
||||
@ -372,6 +456,7 @@ describe('AccountsService', () => {
|
||||
makeDefaultUserGroupsRepositoryMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -381,6 +466,7 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
|
||||
@ -400,6 +486,7 @@ describe('AccountsService', () => {
|
||||
makeDefaultUserGroupsRepositoryMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -409,6 +496,7 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
|
||||
@ -430,6 +518,7 @@ describe('AccountsService', () => {
|
||||
userGroupsRepositoryMockValue.getUserGroups = new Error('DB failed');
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -439,6 +528,7 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
|
||||
@ -464,6 +554,7 @@ describe('AccountsService', () => {
|
||||
makeDefaultAccountsRepositoryMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -473,10 +564,12 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
expect(
|
||||
await service.createPartnerAccount(
|
||||
makeContext('uuid'),
|
||||
companyName,
|
||||
country,
|
||||
email,
|
||||
@ -502,6 +595,7 @@ describe('AccountsService', () => {
|
||||
accountsRepositoryMockValue.createAccount = new Error('DB failed');
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
const service = await makeAccountsServiceMock(
|
||||
@ -511,10 +605,12 @@ describe('AccountsService', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
await expect(
|
||||
service.createPartnerAccount(
|
||||
makeContext('external_id'),
|
||||
companyName,
|
||||
country,
|
||||
email,
|
||||
@ -867,6 +963,7 @@ describe('getOrderHistories', () => {
|
||||
makeDefaultAccountsRepositoryMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const sendGridMockValue = makeDefaultSendGridlValue();
|
||||
const blobStorageMockValue = makeBlobStorageServiceMockValue();
|
||||
const licensesRepositoryMockValue =
|
||||
makeDefaultLicensesRepositoryMockValue();
|
||||
licensesRepositoryMockValue.getLicenseOrderHistoryInfo = new Error(
|
||||
@ -879,6 +976,7 @@ describe('getOrderHistories', () => {
|
||||
adb2cParam,
|
||||
configMockValue,
|
||||
sendGridMockValue,
|
||||
blobStorageMockValue,
|
||||
licensesRepositoryMockValue,
|
||||
);
|
||||
await expect(
|
||||
@ -1145,3 +1243,9 @@ describe('getDealers', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createAccount', () => {
|
||||
it('新規にアカウントを作成できる', async () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
@ -39,6 +39,8 @@ import {
|
||||
AlreadyIssuedError,
|
||||
OrderNotFoundError,
|
||||
} from '../../repositories/licenses/errors/types';
|
||||
import { BlobstorageService } from '../../gateways/blobstorage/blobstorage.service';
|
||||
|
||||
@Injectable()
|
||||
export class AccountsService {
|
||||
constructor(
|
||||
@ -48,6 +50,7 @@ export class AccountsService {
|
||||
private readonly userGroupsRepository: UserGroupsRepositoryService,
|
||||
private readonly adB2cService: AdB2cService,
|
||||
private readonly sendgridService: SendGridService,
|
||||
private readonly blobStorageService: BlobstorageService,
|
||||
private readonly configService: ConfigService,
|
||||
) {}
|
||||
private readonly logger = new Logger(AccountsService.name);
|
||||
@ -119,6 +122,7 @@ export class AccountsService {
|
||||
* @returns account
|
||||
*/
|
||||
async createAccount(
|
||||
context: Context,
|
||||
companyName: string,
|
||||
country: string,
|
||||
dealerAccountId: number | null,
|
||||
@ -128,91 +132,131 @@ export class AccountsService {
|
||||
role: string,
|
||||
acceptedTermsVersion: string,
|
||||
): Promise<{ accountId: number; userId: number; externalUserId: string }> {
|
||||
let externalUser: { sub: string } | ConflictError;
|
||||
this.logger.log(`[IN] [${context.trackingId}] ${this.createAccount.name}`);
|
||||
try {
|
||||
// idpにユーザーを作成
|
||||
externalUser = await this.adB2cService.createUser(
|
||||
email,
|
||||
password,
|
||||
username,
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log('create externalUser failed');
|
||||
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
// メールアドレス重複エラー
|
||||
if (isConflictError(externalUser)) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E010301'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
let account: Account;
|
||||
let user: User;
|
||||
try {
|
||||
// アカウントと管理者をセットで作成
|
||||
const { newAccount, adminUser } =
|
||||
await this.accountRepository.createAccount(
|
||||
companyName,
|
||||
country,
|
||||
dealerAccountId,
|
||||
TIERS.TIER5,
|
||||
externalUser.sub,
|
||||
role,
|
||||
acceptedTermsVersion,
|
||||
);
|
||||
account = newAccount;
|
||||
user = adminUser;
|
||||
} catch (e) {
|
||||
console.log('create account failed');
|
||||
console.log(
|
||||
`[NOT IMPLEMENT] [RECOVER] delete account: ${externalUser.sub}`,
|
||||
);
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// メールの送信元を取得
|
||||
const from = this.configService.get<string>('MAIL_FROM') ?? '';
|
||||
|
||||
// メールの内容を構成
|
||||
const { subject, text, html } =
|
||||
await this.sendgridService.createMailContentFromEmailConfirm(
|
||||
account.id,
|
||||
user.id,
|
||||
let externalUser: { sub: string } | ConflictError;
|
||||
try {
|
||||
// idpにユーザーを作成
|
||||
externalUser = await this.adB2cService.createUser(
|
||||
context,
|
||||
email,
|
||||
password,
|
||||
username,
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
this.logger.error('create externalUser failed');
|
||||
|
||||
// メールを送信
|
||||
await this.sendgridService.sendMail(email, from, subject, text, html);
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
// メールアドレス重複エラー
|
||||
if (isConflictError(externalUser)) {
|
||||
this.logger.error(`email conflict. externalUser: ${externalUser}`);
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E010301'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
let account: Account;
|
||||
let user: User;
|
||||
try {
|
||||
// アカウントと管理者をセットで作成
|
||||
const { newAccount, adminUser } =
|
||||
await this.accountRepository.createAccount(
|
||||
companyName,
|
||||
country,
|
||||
dealerAccountId,
|
||||
TIERS.TIER5,
|
||||
externalUser.sub,
|
||||
role,
|
||||
acceptedTermsVersion,
|
||||
);
|
||||
account = newAccount;
|
||||
user = adminUser;
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
this.logger.error('create account failed');
|
||||
this.logger.error(
|
||||
`[NOT IMPLEMENT] [RECOVER] delete account: ${externalUser.sub}`,
|
||||
);
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
// 新規作成アカウント用のBlobコンテナを作成
|
||||
try {
|
||||
await this.blobStorageService.createContainer(
|
||||
context,
|
||||
account.id,
|
||||
country,
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
this.logger.error('create container failed');
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// メールの送信元を取得
|
||||
const from = this.configService.get<string>('MAIL_FROM') ?? '';
|
||||
|
||||
// メールの内容を構成
|
||||
const { subject, text, html } =
|
||||
await this.sendgridService.createMailContentFromEmailConfirm(
|
||||
context,
|
||||
account.id,
|
||||
user.id,
|
||||
email,
|
||||
);
|
||||
|
||||
// メールを送信
|
||||
await this.sendgridService.sendMail(
|
||||
context,
|
||||
email,
|
||||
from,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
this.logger.error(`error=${e}`);
|
||||
this.logger.error('create user failed');
|
||||
this.logger.error(
|
||||
`[NOT IMPLEMENT] [RECOVER] delete account: ${account.id}`,
|
||||
);
|
||||
this.logger.error(
|
||||
`[NOT IMPLEMENT] [RECOVER] delete externalUser: ${externalUser.sub}`,
|
||||
);
|
||||
this.logger.error(`[NOT IMPLEMENT] [RECOVER] delete user: ${user.id}`);
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
accountId: account.id,
|
||||
userId: user.id,
|
||||
externalUserId: user.external_id,
|
||||
};
|
||||
} catch (e) {
|
||||
console.log('create user failed');
|
||||
console.log(`[NOT IMPLEMENT] [RECOVER] delete account: ${account.id}`);
|
||||
console.log(
|
||||
`[NOT IMPLEMENT] [RECOVER] delete externalUser: ${externalUser.sub}`,
|
||||
);
|
||||
console.log(`[NOT IMPLEMENT] [RECOVER] delete user: ${user.id}`);
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
throw e;
|
||||
} finally {
|
||||
this.logger.log(
|
||||
`[OUT] [${context.trackingId}] ${this.createAccount.name}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
accountId: account.id,
|
||||
userId: user.id,
|
||||
externalUserId: user.external_id,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,6 +388,7 @@ export class AccountsService {
|
||||
* @param tier
|
||||
*/
|
||||
async createPartnerAccount(
|
||||
context: Context,
|
||||
companyName: string,
|
||||
country: string,
|
||||
email: string,
|
||||
@ -351,7 +396,9 @@ export class AccountsService {
|
||||
userId: string,
|
||||
tier: number,
|
||||
): Promise<void> {
|
||||
this.logger.log(`[IN] ${this.createPartnerAccount.name}`);
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.createPartnerAccount.name}`,
|
||||
);
|
||||
|
||||
let myAccountId: number;
|
||||
|
||||
@ -381,6 +428,7 @@ export class AccountsService {
|
||||
try {
|
||||
// 管理者ユーザを作成し、AzureADB2C IDを取得する
|
||||
externalUser = await this.adB2cService.createUser(
|
||||
context,
|
||||
email,
|
||||
ramdomPassword,
|
||||
adminName,
|
||||
@ -420,7 +468,14 @@ export class AccountsService {
|
||||
adminUser.id,
|
||||
email,
|
||||
);
|
||||
await this.sendgridService.sendMail(email, from, subject, text, html);
|
||||
await this.sendgridService.sendMail(
|
||||
context,
|
||||
email,
|
||||
from,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
this.logger.error('create partner account failed');
|
||||
|
||||
@ -15,6 +15,7 @@ import { UserGroupsRepositoryService } from '../../../repositories/user_groups/u
|
||||
import { AdB2cUser } from '../../../gateways/adb2c/types/types';
|
||||
import { LicensesRepositoryService } from '../../../repositories/licenses/licenses.repository.service';
|
||||
import { Context } from '../../../common/log';
|
||||
import { BlobstorageService } from '../../../gateways/blobstorage/blobstorage.service';
|
||||
|
||||
export type LicensesRepositoryMockValue = {
|
||||
getLicenseOrderHistoryInfo:
|
||||
@ -60,6 +61,15 @@ export type AccountsRepositoryMockValue = {
|
||||
};
|
||||
createAccount: { newAccount: Account; adminUser: User } | Error;
|
||||
};
|
||||
|
||||
export type BlobStorageServiceMockValue = {
|
||||
createContainer: void | Error;
|
||||
containerExists: boolean | Error;
|
||||
fileExists: boolean | Error;
|
||||
publishUploadSas: string | Error;
|
||||
publishDownloadSas: string | Error;
|
||||
};
|
||||
|
||||
export const makeAccountsServiceMock = async (
|
||||
accountsRepositoryMockValue: AccountsRepositoryMockValue,
|
||||
usersRepositoryMockValue: UsersRepositoryMockValue,
|
||||
@ -67,6 +77,7 @@ export const makeAccountsServiceMock = async (
|
||||
adB2cMockValue: AdB2cMockValue,
|
||||
configMockValue: ConfigMockValue,
|
||||
sendGridMockValue: SendGridMockValue,
|
||||
blobStorageMockValue: BlobStorageServiceMockValue,
|
||||
licensesRepositoryMockValue: LicensesRepositoryMockValue,
|
||||
): Promise<AccountsService> => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
@ -92,6 +103,8 @@ export const makeAccountsServiceMock = async (
|
||||
return makeConfigMock(configMockValue);
|
||||
case SendGridService:
|
||||
return makeSendGridServiceMock(sendGridMockValue);
|
||||
case BlobstorageService:
|
||||
return makeBlobStorageServiceMock(blobStorageMockValue);
|
||||
case LicensesRepositoryService:
|
||||
return makeLicensesRepositoryMock(licensesRepositoryMockValue);
|
||||
}
|
||||
@ -245,6 +258,42 @@ export const makeSendGridServiceMock = (value: SendGridMockValue) => {
|
||||
: jest.fn<Promise<void>, []>().mockResolvedValue(sendMail),
|
||||
};
|
||||
};
|
||||
|
||||
export const makeBlobStorageServiceMock = (
|
||||
value: BlobStorageServiceMockValue,
|
||||
) => {
|
||||
const {
|
||||
containerExists,
|
||||
fileExists,
|
||||
createContainer,
|
||||
publishUploadSas,
|
||||
publishDownloadSas,
|
||||
} = value;
|
||||
|
||||
return {
|
||||
containerExists:
|
||||
containerExists instanceof Error
|
||||
? jest.fn<Promise<void>, []>().mockRejectedValue(containerExists)
|
||||
: jest.fn<Promise<boolean>, []>().mockResolvedValue(containerExists),
|
||||
fileExists:
|
||||
fileExists instanceof Error
|
||||
? jest.fn<Promise<void>, []>().mockRejectedValue(fileExists)
|
||||
: jest.fn<Promise<boolean>, []>().mockResolvedValue(fileExists),
|
||||
createContainer:
|
||||
createContainer instanceof Error
|
||||
? jest.fn<Promise<void>, []>().mockRejectedValue(createContainer)
|
||||
: jest.fn<Promise<void>, []>().mockResolvedValue(createContainer),
|
||||
publishUploadSas:
|
||||
publishUploadSas instanceof Error
|
||||
? jest.fn<Promise<void>, []>().mockRejectedValue(publishUploadSas)
|
||||
: jest.fn<Promise<string>, []>().mockResolvedValue(publishUploadSas),
|
||||
publishDownloadSas:
|
||||
publishDownloadSas instanceof Error
|
||||
? jest.fn<Promise<void>, []>().mockRejectedValue(publishDownloadSas)
|
||||
: jest.fn<Promise<string>, []>().mockResolvedValue(publishDownloadSas),
|
||||
};
|
||||
};
|
||||
|
||||
// 個別のテストケースに対応してそれぞれのMockを用意するのは無駄が多いのでテストケース内で個別の値を設定する
|
||||
export const makeDefaultAccountsRepositoryMockValue =
|
||||
(): AccountsRepositoryMockValue => {
|
||||
@ -422,3 +471,14 @@ export const makeDefaultLicensesRepositoryMockValue =
|
||||
issueLicense: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
export const makeBlobStorageServiceMockValue =
|
||||
(): BlobStorageServiceMockValue => {
|
||||
return {
|
||||
containerExists: true,
|
||||
fileExists: true,
|
||||
publishUploadSas: 'https://blob-storage?sas-token',
|
||||
publishDownloadSas: 'https://blob-storage?sas-token',
|
||||
createContainer: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
import { User } from '../../../repositories/users/entity/user.entity';
|
||||
import { Account } from '../../../repositories/accounts/entity/account.entity';
|
||||
import {
|
||||
License,
|
||||
LicenseOrder,
|
||||
} from '../../../repositories/licenses/entity/license.entity';
|
||||
import { User } from '../../../repositories/users/entity/user.entity';
|
||||
|
||||
export const createAccount = async (
|
||||
datasource: DataSource,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsEmail, IsInt, IsOptional, Matches, Min } from 'class-validator';
|
||||
import { IsAdminPasswordvalid } from '../../../common/validators/admin.validator';
|
||||
|
||||
export class CreateAccountRequest {
|
||||
@ApiProperty()
|
||||
@ -20,6 +21,7 @@ export class CreateAccountRequest {
|
||||
@IsEmail()
|
||||
adminMail: string;
|
||||
@ApiProperty()
|
||||
@IsAdminPasswordvalid()
|
||||
adminPassword: string;
|
||||
@ApiProperty({ description: '同意済み利用規約のバージョン' })
|
||||
acceptedTermsVersion: string;
|
||||
|
||||
@ -237,10 +237,6 @@ export class FilesService {
|
||||
accountId,
|
||||
country,
|
||||
);
|
||||
//TODO [Task2241] コンテナが無ければ作成しているが、アカウント登録時に作成するので本処理は削除予定。
|
||||
if (!isContainerExist) {
|
||||
await this.blobStorageService.createContainer(accountId, country);
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
this.logger.log(
|
||||
|
||||
@ -47,6 +47,7 @@ import { ADMIN_ROLES, TIERS } from '../../constants';
|
||||
import { RoleGuard } from '../../common/guards/role/roleguards';
|
||||
import { makeContext } from '../../common/log';
|
||||
import { UserRoles } from '../../common/types/role';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
@ApiTags('users')
|
||||
@Controller('users')
|
||||
@ -95,8 +96,8 @@ export class UsersController {
|
||||
async confirmUserAndInitPassword(
|
||||
@Body() body: ConfirmRequest,
|
||||
): Promise<ConfirmResponse> {
|
||||
console.log(body);
|
||||
await this.usersService.confirmUserAndInitPassword(body.token);
|
||||
const context = makeContext(uuidv4());
|
||||
await this.usersService.confirmUserAndInitPassword(context, body.token);
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -173,8 +174,11 @@ export class UsersController {
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
|
||||
const context = makeContext(payload.userId);
|
||||
|
||||
//ユーザ作成処理
|
||||
await this.usersService.createUser(
|
||||
context,
|
||||
payload,
|
||||
name,
|
||||
role as UserRoles,
|
||||
|
||||
@ -33,6 +33,7 @@ import {
|
||||
USER_ROLES,
|
||||
} from '../../constants';
|
||||
import { makeTestingModule } from '../../common/test/modules';
|
||||
import { Context, makeContext } from '../../common/log';
|
||||
import {
|
||||
overrideAdB2cService,
|
||||
overrideSendgridService,
|
||||
@ -219,7 +220,12 @@ describe('UsersService.confirmUserAndInitPassword', () => {
|
||||
|
||||
const token =
|
||||
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw';
|
||||
expect(await service.confirmUserAndInitPassword(token)).toEqual(undefined);
|
||||
expect(
|
||||
await service.confirmUserAndInitPassword(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
),
|
||||
).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('トークンの形式が不正な場合、形式不正エラーとなる。(メール認証API)', async () => {
|
||||
@ -256,7 +262,9 @@ describe('UsersService.confirmUserAndInitPassword', () => {
|
||||
sortCriteriaRepositoryMockValue,
|
||||
);
|
||||
const token = 'invalid.id.token';
|
||||
await expect(service.confirmUserAndInitPassword(token)).rejects.toEqual(
|
||||
await expect(
|
||||
service.confirmUserAndInitPassword(makeContext('trackingId'), token),
|
||||
).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E000101'), HttpStatus.BAD_REQUEST),
|
||||
);
|
||||
});
|
||||
@ -298,7 +306,9 @@ describe('UsersService.confirmUserAndInitPassword', () => {
|
||||
);
|
||||
const token =
|
||||
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw';
|
||||
await expect(service.confirmUserAndInitPassword(token)).rejects.toEqual(
|
||||
await expect(
|
||||
service.confirmUserAndInitPassword(makeContext('trackingId'), token),
|
||||
).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E010202'), HttpStatus.BAD_REQUEST),
|
||||
);
|
||||
});
|
||||
@ -338,7 +348,9 @@ describe('UsersService.confirmUserAndInitPassword', () => {
|
||||
);
|
||||
const token =
|
||||
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw';
|
||||
await expect(service.confirmUserAndInitPassword(token)).rejects.toEqual(
|
||||
await expect(
|
||||
service.confirmUserAndInitPassword(makeContext('trackingId'), token),
|
||||
).rejects.toEqual(
|
||||
new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
@ -392,6 +404,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -414,6 +427,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
expect(
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
@ -474,6 +488,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -496,6 +511,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
expect(
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
@ -559,6 +575,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -581,6 +598,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
expect(
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
@ -641,6 +659,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -663,6 +682,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
expect(
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
@ -718,6 +738,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -747,6 +768,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
try {
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
@ -789,6 +811,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -811,6 +834,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
try {
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
@ -857,6 +881,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -883,6 +908,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
try {
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
@ -935,6 +961,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -957,6 +984,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
expect(
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
@ -982,6 +1010,7 @@ describe('UsersService.createUser', () => {
|
||||
const externalId_2 = '0001';
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -996,6 +1025,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
try {
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
@ -1054,6 +1084,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
overrideAdB2cService(service, {
|
||||
createUser: async (
|
||||
_context: Context,
|
||||
_email: string,
|
||||
_password: string,
|
||||
_username: string,
|
||||
@ -1083,6 +1114,7 @@ describe('UsersService.createUser', () => {
|
||||
|
||||
try {
|
||||
await service.createUser(
|
||||
makeContext('trackingId'),
|
||||
token,
|
||||
name,
|
||||
role,
|
||||
|
||||
@ -123,6 +123,7 @@ export class UsersService {
|
||||
* @returns void
|
||||
*/
|
||||
async createUser(
|
||||
context: Context,
|
||||
accessToken: AccessToken,
|
||||
name: string,
|
||||
role: UserRoles,
|
||||
@ -135,7 +136,7 @@ export class UsersService {
|
||||
encryptionPassword?: string | undefined,
|
||||
prompt?: boolean | undefined,
|
||||
): Promise<void> {
|
||||
this.logger.log(`[IN] ${this.createUser.name}`);
|
||||
this.logger.log(`[IN] [${context.trackingId}] ${this.createUser.name}`);
|
||||
|
||||
//DBよりアクセス者の所属するアカウントIDを取得する
|
||||
let adminUser: EntityUser;
|
||||
@ -184,6 +185,7 @@ export class UsersService {
|
||||
try {
|
||||
// idpにユーザーを作成
|
||||
externalUser = await this.adB2cService.createUser(
|
||||
context,
|
||||
email,
|
||||
ramdomPassword,
|
||||
name,
|
||||
@ -256,7 +258,14 @@ export class UsersService {
|
||||
);
|
||||
|
||||
//SendGridAPIを呼び出してメールを送信する
|
||||
await this.sendgridService.sendMail(email, from, subject, text, html);
|
||||
await this.sendgridService.sendMail(
|
||||
context,
|
||||
email,
|
||||
from,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
this.logger.error('create user failed');
|
||||
@ -321,8 +330,13 @@ export class UsersService {
|
||||
* confirm User And Init Password
|
||||
* @param token ユーザ仮登録時に払いだされるトークン
|
||||
*/
|
||||
async confirmUserAndInitPassword(token: string): Promise<void> {
|
||||
this.logger.log(`[IN] ${this.confirmUserAndInitPassword.name}`);
|
||||
async confirmUserAndInitPassword(
|
||||
context: Context,
|
||||
token: string,
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.confirmUserAndInitPassword.name}`,
|
||||
);
|
||||
|
||||
const pubKey = getPublicKey(this.configService);
|
||||
|
||||
@ -359,7 +373,14 @@ export class UsersService {
|
||||
const html = `<p>OMDS TOP PAGE URL.<p><a href="${domains}">${domains}"</a><br>temporary password: ${ramdomPassword}`;
|
||||
|
||||
// メールを送信
|
||||
await this.sendgridService.sendMail(email, from, subject, text, html);
|
||||
await this.sendgridService.sendMail(
|
||||
context,
|
||||
email,
|
||||
from,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
if (e instanceof Error) {
|
||||
|
||||
@ -56,11 +56,12 @@ export class AdB2cService {
|
||||
* @returns user
|
||||
*/
|
||||
async createUser(
|
||||
context: Context,
|
||||
email: string,
|
||||
password: string,
|
||||
username: string,
|
||||
): Promise<{ sub: string } | ConflictError> {
|
||||
this.logger.log(`[IN] ${this.createUser.name}`);
|
||||
this.logger.log(`[IN] [${context.trackingId}] ${this.createUser.name}`);
|
||||
try {
|
||||
// ユーザをADB2Cに登録
|
||||
const newUser = await this.graphClient.api('users/').post({
|
||||
@ -93,7 +94,7 @@ export class AdB2cService {
|
||||
|
||||
throw e;
|
||||
} finally {
|
||||
this.logger.log(`[OUT] ${this.createUser.name}`);
|
||||
this.logger.log(`[OUT] [${context.trackingId}] ${this.createUser.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -51,13 +51,22 @@ export class BlobstorageService {
|
||||
this.sharedKeyCredentialEU,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates container
|
||||
* @param companyName
|
||||
* @param context
|
||||
* @param accountId
|
||||
* @param country
|
||||
* @returns container
|
||||
*/
|
||||
async createContainer(accountId: number, country: string): Promise<void> {
|
||||
this.logger.log(`[IN] ${this.createContainer.name}`);
|
||||
async createContainer(
|
||||
context: Context,
|
||||
accountId: number,
|
||||
country: string,
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.createContainer.name}`,
|
||||
);
|
||||
|
||||
// 国に応じたリージョンでコンテナ名を指定してClientを取得
|
||||
const containerClient = this.getContainerClient(accountId, country);
|
||||
@ -69,7 +78,9 @@ export class BlobstorageService {
|
||||
this.logger.error(`error=${e}`);
|
||||
throw e;
|
||||
} finally {
|
||||
this.logger.log(`[OUT] ${this.createContainer.name}`);
|
||||
this.logger.log(
|
||||
`[OUT] [${context.trackingId}] ${this.createContainer.name}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
||||
@ -3,6 +3,7 @@ import { ConfigService } from '@nestjs/config';
|
||||
import { sign } from '../../common/jwt';
|
||||
import sendgrid from '@sendgrid/mail';
|
||||
import { getPrivateKey } from '../../common/jwt/jwt';
|
||||
import { Context } from '../../common/log';
|
||||
|
||||
@Injectable()
|
||||
export class SendGridService {
|
||||
@ -20,10 +21,15 @@ export class SendGridService {
|
||||
* @returns メールのサブジェクトとコンテンツ
|
||||
*/
|
||||
async createMailContentFromEmailConfirm(
|
||||
context: Context,
|
||||
accountId: number,
|
||||
userId: number,
|
||||
email: string,
|
||||
): Promise<{ subject: string; text: string; html: string }> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.createMailContentFromEmailConfirm.name}`,
|
||||
);
|
||||
|
||||
const lifetime =
|
||||
this.configService.get<number>('EMAIL_CONFIRM_LIFETIME') ?? 0;
|
||||
const privateKey = getPrivateKey(this.configService);
|
||||
@ -39,6 +45,9 @@ export class SendGridService {
|
||||
const domains = this.configService.get<string>('APP_DOMAIN');
|
||||
const path = 'mail-confirm/';
|
||||
|
||||
this.logger.log(
|
||||
`[OUT] [${context.trackingId}] ${this.createMailContentFromEmailConfirm.name}`,
|
||||
);
|
||||
return {
|
||||
subject: 'Verify your new account',
|
||||
text: `The verification URL. ${domains}${path}?verify=${token}`,
|
||||
@ -85,17 +94,23 @@ export class SendGridService {
|
||||
|
||||
/**
|
||||
* メールを送信する
|
||||
* @param accountId アカウントID
|
||||
* @param userId ユーザーID
|
||||
* @returns user confirm token
|
||||
* @param context
|
||||
* @param to
|
||||
* @param from
|
||||
* @param subject
|
||||
* @param text
|
||||
* @param html
|
||||
* @returns mail
|
||||
*/
|
||||
async sendMail(
|
||||
context: Context,
|
||||
to: string,
|
||||
from: string,
|
||||
subject: string,
|
||||
text: string,
|
||||
html: string,
|
||||
): Promise<void> {
|
||||
this.logger.log(`[IN] [${context.trackingId}] ${this.sendMail.name}`);
|
||||
try {
|
||||
const res = await sendgrid
|
||||
.send({
|
||||
@ -114,8 +129,10 @@ export class SendGridService {
|
||||
`status code: ${res.statusCode} body: ${JSON.stringify(res.body)}`,
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(JSON.stringify(e));
|
||||
this.logger.error(e);
|
||||
throw e;
|
||||
} finally {
|
||||
this.logger.log(`[OUT] [${context.trackingId}] ${this.sendMail.name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user