Merged PR 501: strictNullChecks修正①(accounts,auth,Repositoiesのaccounts,common)
## 概要 [Task2835: 修正①(accounts,auth,Repositoiesのaccounts,common)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2835) - features - accounts - auth - common - repositories - accounts - 各entity - Nullableの項目の`@Column`デコレータに`type`を追加しないとTypeORMがエラーになりテストが通らないので追加 - https://qiita.com/maruware/items/08c9ad594e14e4ea1497#%E5%95%8F%E9%A1%8C ## レビューポイント - コメントとして記載 ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## 動作確認状況 - ローカルで確認、develop環境で確認など ## 補足 - レビュー完了後、TODOコメント(strictNullChecks対応)は削除します
This commit is contained in:
parent
9323cd02e4
commit
f553bfc95b
@ -92,13 +92,15 @@ export class RoleGuard implements CanActivate {
|
||||
* @returns true/false
|
||||
*/
|
||||
checkRole(role: string): boolean {
|
||||
const { roles } = this.settings;
|
||||
|
||||
const settings = this.settings;
|
||||
if (!settings || !settings.roles) {
|
||||
return true;
|
||||
}
|
||||
const userRoles = role.split(' ');
|
||||
|
||||
// Role毎にAccessTokenの権限チェックを行う
|
||||
for (let i = 0; i < roles.length; i++) {
|
||||
const role = roles[i];
|
||||
for (let i = 0; i < settings.roles.length; i++) {
|
||||
const role = settings.roles[i];
|
||||
let isValid = false;
|
||||
if (Array.isArray(role)) {
|
||||
isValid = role.every((x) => userRoles.includes(x));
|
||||
@ -172,9 +174,12 @@ export class RoleGuard implements CanActivate {
|
||||
* @returns true/false
|
||||
*/
|
||||
checkTier(tier: number): boolean {
|
||||
const { tiers } = this.settings;
|
||||
const settings = this.settings;
|
||||
if (!settings || !settings.tiers) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 宣言された階層中にパラメータの内容が含まれていればtrue
|
||||
return tiers.includes(tier as (typeof TIERS)[keyof typeof TIERS]);
|
||||
return settings.tiers.includes(tier as (typeof TIERS)[keyof typeof TIERS]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,10 +15,9 @@ export const makePassword = (): string => {
|
||||
|
||||
// autoGeneratedPasswordが以上の条件を満たせばvalidがtrueになる
|
||||
let valid = false;
|
||||
let autoGeneratedPassword: string;
|
||||
let autoGeneratedPassword: string = '';
|
||||
|
||||
while (!valid) {
|
||||
autoGeneratedPassword = '';
|
||||
// パスワードをランダムに決定
|
||||
while (autoGeneratedPassword.length < passLength) {
|
||||
// 上で決定したcharsの中からランダムに1文字ずつ追加
|
||||
|
||||
@ -58,11 +58,11 @@ export const makeHierarchicalAccounts = async (
|
||||
}
|
||||
// 第2階層を作成
|
||||
{
|
||||
const { account: tier1 } = state.tier1Accounts.slice().shift();
|
||||
const tier1 = state.tier1Accounts.slice().shift();
|
||||
{
|
||||
const { account, admin } = await makeTestAccount(datasource, {
|
||||
tier: 2,
|
||||
parent_account_id: tier1.id,
|
||||
parent_account_id: tier1?.account.id,
|
||||
company_name: 'OMDS_US',
|
||||
});
|
||||
state.tier2Accounts.push({
|
||||
@ -73,7 +73,7 @@ export const makeHierarchicalAccounts = async (
|
||||
{
|
||||
const { account, admin } = await makeTestAccount(datasource, {
|
||||
tier: 2,
|
||||
parent_account_id: tier1.id,
|
||||
parent_account_id: tier1?.account.id,
|
||||
company_name: 'OMDS_EU',
|
||||
});
|
||||
state.tier2Accounts.push({
|
||||
@ -202,7 +202,7 @@ export const makeTestAccount = async (
|
||||
}
|
||||
|
||||
// Accountの管理者を設定する
|
||||
let secondaryAdminUserId = null;
|
||||
let secondaryAdminUserId: number | null = null;
|
||||
if (isPrimaryAdminNotExist && !isSecondaryAdminNotExist) {
|
||||
secondaryAdminUserId = userId;
|
||||
}
|
||||
@ -225,6 +225,9 @@ export const makeTestAccount = async (
|
||||
id: userId,
|
||||
},
|
||||
});
|
||||
if (!account || !admin) {
|
||||
throw new Error('Unexpected null');
|
||||
}
|
||||
|
||||
return {
|
||||
account: account,
|
||||
@ -264,7 +267,9 @@ export const makeTestSimpleAccount = async (
|
||||
id: result.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!account) {
|
||||
throw new Error('Unexpected null');
|
||||
}
|
||||
return account;
|
||||
};
|
||||
|
||||
@ -300,11 +305,15 @@ export const makeTestUser = async (
|
||||
});
|
||||
const result = identifiers.pop() as User;
|
||||
|
||||
return await datasource.getRepository(User).findOne({
|
||||
const user = await datasource.getRepository(User).findOne({
|
||||
where: {
|
||||
id: result.id,
|
||||
},
|
||||
});
|
||||
if (!user) {
|
||||
throw new Error('Unexpected null');
|
||||
}
|
||||
return user;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -313,7 +322,10 @@ export const makeTestUser = async (
|
||||
* @param id アカウントID
|
||||
* @returns 該当アカウント
|
||||
*/
|
||||
export const getAccount = async (dataSource: DataSource, id: number) => {
|
||||
export const getAccount = async (
|
||||
dataSource: DataSource,
|
||||
id: number,
|
||||
): Promise<Account | null> => {
|
||||
return await dataSource.getRepository(Account).findOne({
|
||||
where: { id: id },
|
||||
});
|
||||
@ -354,7 +366,7 @@ export const getUserFromExternalId = async (
|
||||
export const getUser = async (
|
||||
datasource: DataSource,
|
||||
id: number,
|
||||
): Promise<User> => {
|
||||
): Promise<User | null> => {
|
||||
const user = await datasource.getRepository(User).findOne({
|
||||
where: {
|
||||
id: id,
|
||||
|
||||
@ -244,7 +244,7 @@ export const OPTION_ITEM_VALUE_TYPE = {
|
||||
* @const {string[]}
|
||||
*/
|
||||
export const ADB2C_SIGN_IN_TYPE = {
|
||||
EAMILADDRESS: 'emailAddress',
|
||||
EMAILADDRESS: 'emailAddress',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
|
||||
@ -200,14 +200,26 @@ export class AccountsController {
|
||||
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
|
||||
@Get('me')
|
||||
async getMyAccount(@Req() req: Request): Promise<GetMyAccountResponse> {
|
||||
// アクセストークン取得
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
const context = makeContext(payload.userId);
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
const context = makeContext(userId);
|
||||
//アカウントID取得処理
|
||||
const accountInfo = await this.accountService.getAccountInfo(
|
||||
context,
|
||||
payload.userId,
|
||||
userId,
|
||||
);
|
||||
return accountInfo;
|
||||
}
|
||||
@ -237,8 +249,21 @@ export class AccountsController {
|
||||
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
|
||||
@Get('authors')
|
||||
async getAuthors(@Req() req: Request): Promise<GetAuthorsResponse> {
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
const context = makeContext(userId);
|
||||
|
||||
const authors = await this.accountService.getAuthors(context, userId);
|
||||
@ -270,10 +295,23 @@ export class AccountsController {
|
||||
@UseGuards(AuthGuard)
|
||||
@Get('typists')
|
||||
async getTypists(@Req() req: Request): Promise<GetTypistsResponse> {
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const typists = await this.accountService.getTypists(payload.userId);
|
||||
const typists = await this.accountService.getTypists(userId);
|
||||
|
||||
return { typists };
|
||||
}
|
||||
@ -302,12 +340,23 @@ export class AccountsController {
|
||||
@UseGuards(AuthGuard)
|
||||
@Get('typist-groups')
|
||||
async getTypistGroups(@Req() req: Request): Promise<GetTypistGroupsResponse> {
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const typistGroups = await this.accountService.getTypistGroups(
|
||||
payload.userId,
|
||||
);
|
||||
const typistGroups = await this.accountService.getTypistGroups(userId);
|
||||
|
||||
return { typistGroups };
|
||||
}
|
||||
@ -348,8 +397,22 @@ export class AccountsController {
|
||||
const { typistGroupId } = param;
|
||||
|
||||
// アクセストークン取得
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
@ -397,8 +460,22 @@ export class AccountsController {
|
||||
): Promise<CreateTypistGroupResponse> {
|
||||
const { typistGroupName, typistIds } = body;
|
||||
// アクセストークン取得
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
const context = makeContext(userId);
|
||||
await this.accountService.createTypistGroup(
|
||||
context,
|
||||
@ -447,8 +524,22 @@ export class AccountsController {
|
||||
const { typistGroupId } = param;
|
||||
|
||||
// アクセストークン取得
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
@ -498,10 +589,24 @@ export class AccountsController {
|
||||
@Body() body: CreatePartnerAccountRequest,
|
||||
): Promise<CreatePartnerAccountResponse> {
|
||||
const { companyName, country, email, adminName } = body;
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
|
||||
const context = makeContext(payload.userId);
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId, tier } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
await this.accountService.createPartnerAccount(
|
||||
context,
|
||||
@ -509,8 +614,8 @@ export class AccountsController {
|
||||
country,
|
||||
email,
|
||||
adminName,
|
||||
payload.userId,
|
||||
payload.tier,
|
||||
userId,
|
||||
tier,
|
||||
);
|
||||
|
||||
return {};
|
||||
@ -626,15 +731,28 @@ export class AccountsController {
|
||||
): Promise<IssueLicenseResponse> {
|
||||
const { orderedAccountId, poNumber } = body;
|
||||
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId, tier } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(accessToken.userId);
|
||||
const context = makeContext(userId);
|
||||
await this.accountService.issueLicense(
|
||||
context,
|
||||
orderedAccountId,
|
||||
accessToken.userId,
|
||||
accessToken.tier,
|
||||
userId,
|
||||
tier,
|
||||
poNumber,
|
||||
);
|
||||
return {};
|
||||
@ -694,14 +812,27 @@ export class AccountsController {
|
||||
@Req() req: Request,
|
||||
@Body() body: CancelIssueRequest,
|
||||
): Promise<CancelIssueResponse> {
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(token, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(payload.userId);
|
||||
const context = makeContext(userId);
|
||||
|
||||
await this.accountService.cancelIssue(
|
||||
context,
|
||||
payload.userId,
|
||||
userId,
|
||||
body.poNumber,
|
||||
body.orderedAccountId,
|
||||
);
|
||||
@ -729,8 +860,21 @@ export class AccountsController {
|
||||
@UseGuards(AuthGuard)
|
||||
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
|
||||
async getWorktypes(@Req() req: Request): Promise<GetWorktypesResponse> {
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
const worktypes = await this.accountService.getWorktypes(context, userId);
|
||||
@ -768,8 +912,22 @@ export class AccountsController {
|
||||
@Body() body: CreateWorktypesRequest,
|
||||
): Promise<CreateWorktypeResponse> {
|
||||
const { worktypeId, description } = body;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
await this.accountService.createWorktype(
|
||||
@ -814,8 +972,22 @@ export class AccountsController {
|
||||
): Promise<UpdateWorktypeResponse> {
|
||||
const { worktypeId, description } = body;
|
||||
const { id } = param;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
@ -860,8 +1032,22 @@ export class AccountsController {
|
||||
@Param() param: DeleteWorktypeRequestParam,
|
||||
): Promise<DeleteWorktypeResponse> {
|
||||
const { id } = param;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
@ -899,8 +1085,22 @@ export class AccountsController {
|
||||
@Param() param: GetOptionItemsRequestParam,
|
||||
): Promise<GetOptionItemsResponse> {
|
||||
const { id } = param;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
@ -945,8 +1145,22 @@ export class AccountsController {
|
||||
): Promise<UpdateOptionItemsResponse> {
|
||||
const { optionItems } = body;
|
||||
const { id } = param;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
@ -990,8 +1204,22 @@ export class AccountsController {
|
||||
@Body() body: PostActiveWorktypeRequest,
|
||||
): Promise<PostActiveWorktypeResponse> {
|
||||
const { id } = body;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
@ -1034,8 +1262,22 @@ export class AccountsController {
|
||||
@Query() query: GetPartnersRequest,
|
||||
): Promise<GetPartnersResponse> {
|
||||
const { limit, offset } = query;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
const response = await this.accountService.getPartners(
|
||||
@ -1087,8 +1329,22 @@ export class AccountsController {
|
||||
primaryAdminUserId,
|
||||
secondryAdminUserId,
|
||||
} = body;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId, tier } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId, tier } = decodedAccessToken as AccessToken;
|
||||
const context = makeContext(userId);
|
||||
|
||||
await this.accountService.updateAccountInfo(
|
||||
@ -1101,7 +1357,7 @@ export class AccountsController {
|
||||
secondryAdminUserId,
|
||||
);
|
||||
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
@Post('/delete')
|
||||
@ -1133,12 +1389,26 @@ export class AccountsController {
|
||||
@Body() body: DeleteAccountRequest,
|
||||
): Promise<DeleteAccountResponse> {
|
||||
const { accountId } = body;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
const context = makeContext(userId);
|
||||
|
||||
await this.accountService.deleteAccountAndData(context, userId, accountId);
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
@Post('/minimal-access')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -33,6 +33,7 @@ import {
|
||||
GetPartnersResponse,
|
||||
PostWorktypeOptionItem,
|
||||
Author,
|
||||
Partner,
|
||||
} from './types/types';
|
||||
import {
|
||||
DateWithZeroTime,
|
||||
@ -72,6 +73,8 @@ import {
|
||||
|
||||
@Injectable()
|
||||
export class AccountsService {
|
||||
private readonly mailFrom =
|
||||
this.configService.getOrThrow<string>('MAIL_FROM');
|
||||
constructor(
|
||||
private readonly accountRepository: AccountsRepositoryService,
|
||||
private readonly licensesRepository: LicensesRepositoryService,
|
||||
@ -257,9 +260,6 @@ export class AccountsService {
|
||||
}
|
||||
|
||||
try {
|
||||
// メールの送信元を取得
|
||||
const from = this.configService.get<string>('MAIL_FROM') ?? '';
|
||||
|
||||
// メールの内容を構成
|
||||
const { subject, text, html } =
|
||||
await this.sendgridService.createMailContentFromEmailConfirm(
|
||||
@ -273,7 +273,7 @@ export class AccountsService {
|
||||
await this.sendgridService.sendMail(
|
||||
context,
|
||||
email,
|
||||
from,
|
||||
this.mailFrom,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
@ -394,7 +394,7 @@ export class AccountsService {
|
||||
userInfo.account_id,
|
||||
);
|
||||
|
||||
let parentInfo: Account;
|
||||
let parentInfo: Account | undefined;
|
||||
if (accountInfo.parent_account_id) {
|
||||
parentInfo = await this.accountRepository.findAccountById(
|
||||
accountInfo.parent_account_id,
|
||||
@ -481,14 +481,20 @@ export class AccountsService {
|
||||
const { account_id } = await this.usersRepository.findUserByExternalId(
|
||||
externalId,
|
||||
);
|
||||
const userGroup = await this.userGroupsRepository.getTypistGroup(
|
||||
account_id,
|
||||
typistGroupId,
|
||||
);
|
||||
const { name, userGroupMembers } =
|
||||
await this.userGroupsRepository.getTypistGroup(
|
||||
account_id,
|
||||
typistGroupId,
|
||||
);
|
||||
if (!userGroupMembers) {
|
||||
throw new TypistGroupNotExistError(
|
||||
`Typist Group is not exist. typistGroupId: ${typistGroupId}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
typistGroupName: userGroup.name,
|
||||
typistIds: userGroup.userGroupMembers.map((x) => x.user_id),
|
||||
typistGroupName: name,
|
||||
typistIds: userGroupMembers.map((x) => x.user_id),
|
||||
};
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
@ -541,6 +547,11 @@ export class AccountsService {
|
||||
|
||||
const typists = typistUsers.map((x) => {
|
||||
const user = adb2cUsers.find((adb2c) => adb2c.id === x.external_id);
|
||||
if (!user) {
|
||||
throw new Error(
|
||||
`user not found. externalId: ${x.external_id}, userId: ${x.id}`,
|
||||
);
|
||||
}
|
||||
return {
|
||||
id: x.id,
|
||||
name: user.displayName,
|
||||
@ -586,6 +597,11 @@ export class AccountsService {
|
||||
);
|
||||
|
||||
const authors = authorUsers.map((x) => {
|
||||
if (!x.author_id) {
|
||||
throw new Error(
|
||||
`author_id is Not Found. externalId: ${x.external_id}, userId: ${x.id}`,
|
||||
);
|
||||
}
|
||||
return {
|
||||
id: x.id,
|
||||
authorId: x.author_id,
|
||||
@ -701,8 +717,8 @@ export class AccountsService {
|
||||
creatorAccountTier + 1,
|
||||
externalUser.sub,
|
||||
USER_ROLES.NONE,
|
||||
null,
|
||||
null,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
account = newAccount;
|
||||
user = adminUser;
|
||||
@ -743,7 +759,6 @@ export class AccountsService {
|
||||
}
|
||||
|
||||
try {
|
||||
const from = this.configService.get<string>('MAIL_FROM') || '';
|
||||
const { subject, text, html } =
|
||||
await this.sendgridService.createMailContentFromEmailConfirmForNormalUser(
|
||||
account.id,
|
||||
@ -753,7 +768,7 @@ export class AccountsService {
|
||||
await this.sendgridService.sendMail(
|
||||
context,
|
||||
email,
|
||||
from,
|
||||
this.mailFrom,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
@ -836,11 +851,19 @@ export class AccountsService {
|
||||
// 各子アカウントのShortageを算出してreturn用の変数にマージする
|
||||
const childrenPartnerLicenses: PartnerLicenseInfo[] = [];
|
||||
for (const childPartnerLicenseFromRepository of getPartnerLicenseResult.childPartnerLicensesFromRepository) {
|
||||
let childShortage;
|
||||
const { allocatableLicenseWithMargin, expiringSoonLicense } =
|
||||
childPartnerLicenseFromRepository;
|
||||
let childShortage: number = 0;
|
||||
if (childPartnerLicenseFromRepository.tier === TIERS.TIER5) {
|
||||
childShortage =
|
||||
childPartnerLicenseFromRepository.allocatableLicenseWithMargin -
|
||||
childPartnerLicenseFromRepository.expiringSoonLicense;
|
||||
if (
|
||||
allocatableLicenseWithMargin === undefined ||
|
||||
expiringSoonLicense === undefined
|
||||
) {
|
||||
throw new Error(
|
||||
`Tier5 account has no allocatableLicenseWithMargin or expiringSoonLicense. accountId: ${accountId}`,
|
||||
);
|
||||
}
|
||||
childShortage = allocatableLicenseWithMargin - expiringSoonLicense;
|
||||
} else {
|
||||
childShortage =
|
||||
childPartnerLicenseFromRepository.stockLicense -
|
||||
@ -907,13 +930,13 @@ export class AccountsService {
|
||||
licenseOrder.issued_at !== null
|
||||
? new Date(licenseOrder.issued_at)
|
||||
.toISOString()
|
||||
.substr(0, 10)
|
||||
.substring(0, 10)
|
||||
.replace(/-/g, '/')
|
||||
: null,
|
||||
: undefined,
|
||||
numberOfOrder: licenseOrder.quantity,
|
||||
orderDate: new Date(licenseOrder.ordered_at)
|
||||
.toISOString()
|
||||
.substr(0, 10)
|
||||
.substring(0, 10)
|
||||
.replace(/-/g, '/'),
|
||||
poNumber: licenseOrder.po_number,
|
||||
status: licenseOrder.status,
|
||||
@ -1634,7 +1657,7 @@ export class AccountsService {
|
||||
async updateActiveWorktype(
|
||||
context: Context,
|
||||
externalId: string,
|
||||
id: number,
|
||||
id: number | undefined,
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.updateActiveWorktype.name} | params: { ` +
|
||||
@ -1701,34 +1724,40 @@ export class AccountsService {
|
||||
const { account_id: accountId } =
|
||||
await this.usersRepository.findUserByExternalId(externalId);
|
||||
|
||||
const partners = await this.accountRepository.getPartners(
|
||||
const partnersRecords = await this.accountRepository.getPartners(
|
||||
accountId,
|
||||
limit,
|
||||
offset,
|
||||
);
|
||||
|
||||
// DBから取得したユーザーの外部IDをもとにADB2Cからユーザーを取得する
|
||||
let externalIds = partners.partnersInfo.map(
|
||||
let externalIds = partnersRecords.partnersInfo.map(
|
||||
(x) => x.primaryAccountExternalId,
|
||||
);
|
||||
externalIds = externalIds.filter((item) => item !== undefined);
|
||||
const adb2cUsers = await this.adB2cService.getUsers(context, externalIds);
|
||||
|
||||
// DBから取得した情報とADB2Cから取得した情報をマージ
|
||||
const response = partners.partnersInfo.map((db) => {
|
||||
const partners = partnersRecords.partnersInfo.map((db): Partner => {
|
||||
const adb2cUser = adb2cUsers.find(
|
||||
(adb2c) => db.primaryAccountExternalId === adb2c.id,
|
||||
);
|
||||
|
||||
let primaryAdmin = undefined;
|
||||
let mail = undefined;
|
||||
if (adb2cUser) {
|
||||
primaryAdmin = adb2cUser.displayName;
|
||||
mail = adb2cUser.identities.find(
|
||||
(identity) =>
|
||||
identity.signInType === ADB2C_SIGN_IN_TYPE.EAMILADDRESS,
|
||||
).issuerAssignedId;
|
||||
if (!adb2cUser) {
|
||||
throw new Error(
|
||||
`adb2c user not found. externalId: ${db.primaryAccountExternalId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const primaryAdmin = adb2cUser.displayName;
|
||||
const mail = adb2cUser.identities?.find(
|
||||
(identity) => identity.signInType === ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
)?.issuerAssignedId;
|
||||
if (!mail) {
|
||||
throw new Error(
|
||||
`adb2c user mail not found. externalId: ${db.primaryAccountExternalId}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
name: db.name,
|
||||
tier: db.tier,
|
||||
@ -1741,17 +1770,15 @@ export class AccountsService {
|
||||
});
|
||||
|
||||
return {
|
||||
total: partners.total,
|
||||
partners: response,
|
||||
total: partnersRecords.total,
|
||||
partners: partners,
|
||||
};
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
if (e instanceof Error) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
} finally {
|
||||
this.logger.log(`[OUT] [${context.trackingId}] ${this.getPartners.name}`);
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ export type LicensesRepositoryMockValue = {
|
||||
orderHistories: LicenseOrder[];
|
||||
}
|
||||
| Error;
|
||||
issueLicense: undefined | Error;
|
||||
issueLicense: void | Error;
|
||||
};
|
||||
export type UsersRepositoryMockValue = {
|
||||
findUserById: User | Error;
|
||||
@ -61,10 +61,12 @@ export type ConfigMockValue = {
|
||||
get: string | Error;
|
||||
};
|
||||
export type AccountsRepositoryMockValue = {
|
||||
getLicenseSummaryInfo: {
|
||||
licenseSummary: LicenseSummaryInfo;
|
||||
isStorageAvailable: boolean;
|
||||
};
|
||||
getLicenseSummaryInfo:
|
||||
| {
|
||||
licenseSummary: LicenseSummaryInfo;
|
||||
isStorageAvailable: boolean;
|
||||
}
|
||||
| Error;
|
||||
createAccount: { newAccount: Account; adminUser: User } | Error;
|
||||
};
|
||||
|
||||
@ -181,18 +183,7 @@ export const makeLicensesRepositoryMock = (
|
||||
issueLicense:
|
||||
issueLicense instanceof Error
|
||||
? jest.fn<Promise<void>, []>().mockRejectedValue(issueLicense)
|
||||
: jest
|
||||
.fn<
|
||||
Promise<{
|
||||
context: Context;
|
||||
orderedAccountId: number;
|
||||
myAccountId: number;
|
||||
tier: number;
|
||||
poNumber: string;
|
||||
}>,
|
||||
[]
|
||||
>()
|
||||
.mockResolvedValue(issueLicense),
|
||||
: jest.fn<Promise<void>, []>().mockResolvedValue(issueLicense),
|
||||
};
|
||||
};
|
||||
export const makeUsersRepositoryMock = (value: UsersRepositoryMockValue) => {
|
||||
@ -355,7 +346,7 @@ export const makeDefaultAccountsRepositoryMockValue =
|
||||
user.created_by = 'test';
|
||||
user.created_at = new Date();
|
||||
user.updated_by = null;
|
||||
user.updated_at = null;
|
||||
user.updated_at = new Date();
|
||||
return {
|
||||
getLicenseSummaryInfo: {
|
||||
licenseSummary: licenseSummaryInfo,
|
||||
@ -385,7 +376,7 @@ export const makeDefaultUsersRepositoryMockValue =
|
||||
user.created_by = 'test';
|
||||
user.created_at = new Date();
|
||||
user.updated_by = null;
|
||||
user.updated_at = null;
|
||||
user.updated_at = new Date();
|
||||
|
||||
const typists: User[] = [];
|
||||
typists.push(
|
||||
@ -434,7 +425,7 @@ export const makeDefaultUserGroupsRepositoryMockValue =
|
||||
user.created_by = 'test';
|
||||
user.created_at = new Date();
|
||||
user.updated_by = null;
|
||||
user.updated_at = null;
|
||||
user.updated_at = new Date();
|
||||
|
||||
return {
|
||||
getUserGroups: [
|
||||
|
||||
@ -23,14 +23,14 @@ export const getSortCriteria = async (dataSource: DataSource) => {
|
||||
export const createLicense = async (
|
||||
datasource: DataSource,
|
||||
licenseId: number,
|
||||
expiry_date: Date,
|
||||
expiry_date: Date | null,
|
||||
accountId: number,
|
||||
type: string,
|
||||
status: string,
|
||||
allocated_user_id: number,
|
||||
order_id: number,
|
||||
deleted_at: Date,
|
||||
delete_order_id: number,
|
||||
allocated_user_id: number | null,
|
||||
order_id: number | null,
|
||||
deleted_at: Date | null,
|
||||
delete_order_id: number | null,
|
||||
): Promise<void> => {
|
||||
const { identifiers } = await datasource.getRepository(License).insert({
|
||||
id: licenseId,
|
||||
@ -54,7 +54,7 @@ export const createLicense = async (
|
||||
export const createLicenseSetExpiryDateAndStatus = async (
|
||||
datasource: DataSource,
|
||||
accountId: number,
|
||||
expiryDate: Date,
|
||||
expiryDate: Date | null,
|
||||
status: string,
|
||||
): Promise<void> => {
|
||||
const { identifiers } = await datasource.getRepository(License).insert({
|
||||
@ -171,19 +171,21 @@ export const createOptionItems = async (
|
||||
datasource: DataSource,
|
||||
worktypeId: number,
|
||||
): Promise<OptionItem[]> => {
|
||||
const optionItems = [];
|
||||
const optionItems: OptionItem[] = [];
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
optionItems.push({
|
||||
worktype_id: worktypeId,
|
||||
item_label: '',
|
||||
default_value_type: OPTION_ITEM_VALUE_TYPE.DEFAULT,
|
||||
initial_value: '',
|
||||
created_by: 'test_runner',
|
||||
created_at: new Date(),
|
||||
updated_by: 'updater',
|
||||
updated_at: new Date(),
|
||||
});
|
||||
const optionItem = new OptionItem();
|
||||
{
|
||||
optionItem.worktype_id = worktypeId;
|
||||
optionItem.item_label = '';
|
||||
optionItem.default_value_type = OPTION_ITEM_VALUE_TYPE.DEFAULT;
|
||||
optionItem.initial_value = '';
|
||||
optionItem.created_by = 'test_runner';
|
||||
optionItem.created_at = new Date();
|
||||
optionItem.updated_by = 'updater';
|
||||
optionItem.updated_at = new Date();
|
||||
}
|
||||
optionItems.push(optionItem);
|
||||
}
|
||||
|
||||
await datasource.getRepository(OptionItem).insert(optionItems);
|
||||
|
||||
@ -327,8 +327,8 @@ export class GetOrderHistoriesRequest {
|
||||
export class LicenseOrder {
|
||||
@ApiProperty({ description: '注文日付' })
|
||||
orderDate: string;
|
||||
@ApiProperty({ description: '発行日付' })
|
||||
issueDate: string;
|
||||
@ApiProperty({ description: '発行日付', required: false })
|
||||
issueDate?: string;
|
||||
@ApiProperty({ description: '注文数' })
|
||||
numberOfOrder: number;
|
||||
@ApiProperty({ description: 'POナンバー' })
|
||||
|
||||
@ -5,12 +5,19 @@ import {
|
||||
makeAdB2cServiceMock,
|
||||
makeDefaultAdB2cMockValue,
|
||||
} from './test/auth.service.mock';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
|
||||
describe('AuthController', () => {
|
||||
let controller: AuthController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
envFilePath: ['.env.local', '.env'],
|
||||
isGlobal: true,
|
||||
}),
|
||||
],
|
||||
controllers: [AuthController],
|
||||
providers: [AuthService],
|
||||
})
|
||||
|
||||
@ -3,6 +3,7 @@ import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
import {
|
||||
makeAuthServiceMock,
|
||||
makeDefaultAdB2cMockValue,
|
||||
makeDefaultConfigValue,
|
||||
makeDefaultGetPublicKeyFromJwk,
|
||||
} from './test/auth.service.mock';
|
||||
import { DataSource } from 'typeorm';
|
||||
@ -16,7 +17,8 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
describe('AuthService', () => {
|
||||
it('IDトークンの検証とペイロードの取得に成功する', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam);
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam, configMockValue);
|
||||
//JWKの生成→PEM変換を自力で表現することが厳しいためMockで代替
|
||||
service.getPublicKeyFromJwk = makeDefaultGetPublicKeyFromJwk;
|
||||
const token =
|
||||
@ -27,7 +29,8 @@ describe('AuthService', () => {
|
||||
|
||||
it('IDトークンの形式が不正な場合、形式不正エラーとなる。', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam);
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam, configMockValue);
|
||||
const token = 'invalid.id.token';
|
||||
|
||||
await expect(service.getVerifiedIdToken(token)).rejects.toEqual(
|
||||
@ -37,7 +40,8 @@ describe('AuthService', () => {
|
||||
|
||||
it('IDトークンの有効期限が切れている場合、有効期限切れエラーとなる。', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam);
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam, configMockValue);
|
||||
//JWKの生成→PEM変換を自力で表現することが厳しいためMockで代替
|
||||
service.getPublicKeyFromJwk = makeDefaultGetPublicKeyFromJwk;
|
||||
const token =
|
||||
@ -50,7 +54,8 @@ describe('AuthService', () => {
|
||||
|
||||
it('IDトークンが開始日より前の場合、開始前エラーとなる。', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam);
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam, configMockValue);
|
||||
//JWKの生成→PEM変換を自力で表現することが厳しいためMockで代替
|
||||
service.getPublicKeyFromJwk = makeDefaultGetPublicKeyFromJwk;
|
||||
const token =
|
||||
@ -63,7 +68,8 @@ describe('AuthService', () => {
|
||||
|
||||
it('IDトークンの署名が不正な場合、署名不正エラーとなる。', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam);
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam, configMockValue);
|
||||
const token =
|
||||
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdXNlciIsInN1YiI6InN1YiIsImF1ZCI6ImF1ZCIsIm5vbmNlIjoiZGVmYXVsdE5vbmNlIiwiaWF0IjoxMDAwMDAwMDAwLCJhdXRoX3RpbWUiOjEwMDAwMDAwMDAsImVtYWlscyI6WyJ4eHhAeHguY29tIl0sInRmcCI6InNpZ25pbl91c2VyZmxvdyJ9.sign';
|
||||
|
||||
@ -74,7 +80,8 @@ describe('AuthService', () => {
|
||||
|
||||
it('IDトークンの発行元が想定と異なる場合、発行元不正エラーとなる。', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam);
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
const service = await makeAuthServiceMock(adb2cParam, configMockValue);
|
||||
//JWKの生成→PEM変換を自力で表現することが厳しいためMockで代替
|
||||
service.getPublicKeyFromJwk = makeDefaultGetPublicKeyFromJwk;
|
||||
const token =
|
||||
@ -87,8 +94,9 @@ describe('AuthService', () => {
|
||||
|
||||
it('Azure ADB2Cでネットワークエラーとなる場合、エラーとなる。(メタデータ)', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
adb2cParam.getMetaData = new Error('failed get metadata');
|
||||
const service = await makeAuthServiceMock(adb2cParam);
|
||||
const service = await makeAuthServiceMock(adb2cParam, configMockValue);
|
||||
const token =
|
||||
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdWVyIiwic3ViIjoic3ViIiwiYXVkIjoiYXVkIiwibm9uY2UiOiJkZWZhdWx0Tm9uY2UiLCJpYXQiOjEwMDAwMDAwMDAsImF1dGhfdGltZSI6MTAwMDAwMDAwMCwiZW1haWxzIjpbInh4eEB4eC5jb20iXSwidGZwIjoic2lnbmluX3VzZXJmbG93In0.RyieW-VHsHPQOjXbbhRc307AYJOc1sq2hrcu4SW1-K0pvLlkplepxvx02a3vCwQrnBYrIP5w6HExG-S_JgW5nYyWr6DeY11mA484n9KA8GeAcAXV37StH1gfWUJvfGb4C8BaMbMM9Ix4Z9NGwKA9vjNwevfmBZnz9lQUePgv6BJNmyvCt8ElJ01O-1WODbZuojJ4xXymA1OqluzfbphPOsqWTSNmTn0emkLjjnlMQf1iwM4C_kvvr8dUCFg0_UGDfQVJnzPEKB38UqnhLnC5WacrddDwQ0kBuGKZgZ_63Q_7fOvqAZivqLK7BPmbPxi6mx3R1S9Eq2ugzpY1LfJOjA';
|
||||
|
||||
@ -101,8 +109,9 @@ describe('AuthService', () => {
|
||||
});
|
||||
it('Azure ADB2Cでネットワークエラーとなる場合、エラーとなる。(キーセット)', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
adb2cParam.getSignKeySets = new Error('failed get keyset');
|
||||
const service = await makeAuthServiceMock(adb2cParam);
|
||||
const service = await makeAuthServiceMock(adb2cParam, configMockValue);
|
||||
const token =
|
||||
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdWVyIiwic3ViIjoic3ViIiwiYXVkIjoiYXVkIiwibm9uY2UiOiJkZWZhdWx0Tm9uY2UiLCJpYXQiOjEwMDAwMDAwMDAsImF1dGhfdGltZSI6MTAwMDAwMDAwMCwiZW1haWxzIjpbInh4eEB4eC5jb20iXSwidGZwIjoic2lnbmluX3VzZXJmbG93In0.RyieW-VHsHPQOjXbbhRc307AYJOc1sq2hrcu4SW1-K0pvLlkplepxvx02a3vCwQrnBYrIP5w6HExG-S_JgW5nYyWr6DeY11mA484n9KA8GeAcAXV37StH1gfWUJvfGb4C8BaMbMM9Ix4Z9NGwKA9vjNwevfmBZnz9lQUePgv6BJNmyvCt8ElJ01O-1WODbZuojJ4xXymA1OqluzfbphPOsqWTSNmTn0emkLjjnlMQf1iwM4C_kvvr8dUCFg0_UGDfQVJnzPEKB38UqnhLnC5WacrddDwQ0kBuGKZgZ_63Q_7fOvqAZivqLK7BPmbPxi6mx3R1S9Eq2ugzpY1LfJOjA';
|
||||
|
||||
@ -116,10 +125,11 @@ describe('AuthService', () => {
|
||||
|
||||
it('Azure ADB2Cから取得した鍵が一致しない場合、エラーとなる。', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
const configMockValue = makeDefaultConfigValue();
|
||||
adb2cParam.getSignKeySets = [
|
||||
{ kid: 'invalid', kty: 'RSA', nbf: 0, use: 'sig', e: '', n: '' },
|
||||
];
|
||||
const service = await makeAuthServiceMock(adb2cParam);
|
||||
const service = await makeAuthServiceMock(adb2cParam, configMockValue);
|
||||
const token =
|
||||
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdWVyIiwic3ViIjoic3ViIiwiYXVkIjoiYXVkIiwibm9uY2UiOiJkZWZhdWx0Tm9uY2UiLCJpYXQiOjEwMDAwMDAwMDAsImF1dGhfdGltZSI6MTAwMDAwMDAwMCwiZW1haWxzIjpbInh4eEB4eC5jb20iXSwidGZwIjoic2lnbmluX3VzZXJmbG93In0.RyieW-VHsHPQOjXbbhRc307AYJOc1sq2hrcu4SW1-K0pvLlkplepxvx02a3vCwQrnBYrIP5w6HExG-S_JgW5nYyWr6DeY11mA484n9KA8GeAcAXV37StH1gfWUJvfGb4C8BaMbMM9Ix4Z9NGwKA9vjNwevfmBZnz9lQUePgv6BJNmyvCt8ElJ01O-1WODbZuojJ4xXymA1OqluzfbphPOsqWTSNmTn0emkLjjnlMQf1iwM4C_kvvr8dUCFg0_UGDfQVJnzPEKB38UqnhLnC5WacrddDwQ0kBuGKZgZ_63Q_7fOvqAZivqLK7BPmbPxi6mx3R1S9Eq2ugzpY1LfJOjA';
|
||||
|
||||
@ -133,7 +143,7 @@ describe('AuthService', () => {
|
||||
});
|
||||
|
||||
describe('checkIsAcceptedLatestVersion', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -146,11 +156,14 @@ describe('checkIsAcceptedLatestVersion', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
it('同意済み利用規約バージョンが最新のときにチェックが通ること(第五)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<AuthService>(AuthService);
|
||||
const { admin } = await makeTestAccount(source, {
|
||||
tier: 5,
|
||||
@ -171,7 +184,9 @@ describe('checkIsAcceptedLatestVersion', () => {
|
||||
});
|
||||
|
||||
it('同意済み利用規約バージョンが最新のときにチェックが通ること(第一~第四)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<AuthService>(AuthService);
|
||||
const { admin } = await makeTestAccount(source, {
|
||||
tier: 4,
|
||||
@ -192,7 +207,9 @@ describe('checkIsAcceptedLatestVersion', () => {
|
||||
});
|
||||
|
||||
it('同意済み利用規約バージョンが最新でないときにチェックが通らないこと(第五)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<AuthService>(AuthService);
|
||||
const { admin } = await makeTestAccount(source, {
|
||||
tier: 5,
|
||||
@ -213,7 +230,9 @@ describe('checkIsAcceptedLatestVersion', () => {
|
||||
});
|
||||
|
||||
it('同意済み利用規約(EULA)バージョンが最新でないときにチェックが通らないこと(第一~第四)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<AuthService>(AuthService);
|
||||
const { admin } = await makeTestAccount(source, {
|
||||
tier: 4,
|
||||
@ -234,7 +253,9 @@ describe('checkIsAcceptedLatestVersion', () => {
|
||||
});
|
||||
|
||||
it('同意済み利用規約バージョン(DPA)が最新でないときにチェックが通らないこと(第一~第四)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<AuthService>(AuthService);
|
||||
const { admin } = await makeTestAccount(source, {
|
||||
tier: 4,
|
||||
|
||||
@ -25,6 +25,13 @@ import { Context } from '../../common/log';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
private readonly refreshTokenLifetimeWeb =
|
||||
this.configService.getOrThrow<number>('REFRESH_TOKEN_LIFETIME_WEB');
|
||||
private readonly refreshTokenLifetimeDefault =
|
||||
this.configService.getOrThrow<number>('REFRESH_TOKEN_LIFETIME_DEFAULT');
|
||||
private readonly accessTokenlifetime = this.configService.getOrThrow<number>(
|
||||
'ACCESS_TOKEN_LIFETIME_WEB',
|
||||
);
|
||||
constructor(
|
||||
private readonly adB2cService: AdB2cService,
|
||||
private readonly configService: ConfigService,
|
||||
@ -68,10 +75,7 @@ export class AuthService {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.generateRefreshToken.name}`,
|
||||
);
|
||||
const lifetimeWeb = this.configService.get('REFRESH_TOKEN_LIFETIME_WEB');
|
||||
const lifetimeDefault = this.configService.get(
|
||||
'REFRESH_TOKEN_LIFETIME_DEFAULT',
|
||||
);
|
||||
|
||||
let user: User;
|
||||
// ユーザー情報とユーザーが属しているアカウント情報を取得
|
||||
try {
|
||||
@ -106,7 +110,10 @@ export class AuthService {
|
||||
);
|
||||
}
|
||||
// 要求された環境用トークンの寿命を決定
|
||||
const refreshTokenLifetime = type === 'web' ? lifetimeWeb : lifetimeDefault;
|
||||
const refreshTokenLifetime =
|
||||
type === 'web'
|
||||
? this.refreshTokenLifetimeWeb
|
||||
: this.refreshTokenLifetimeDefault;
|
||||
const privateKey = getPrivateKey(this.configService);
|
||||
|
||||
// ユーザーのロールを設定
|
||||
@ -165,7 +172,6 @@ export class AuthService {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.generateAccessToken.name}`,
|
||||
);
|
||||
const lifetime = this.configService.get('ACCESS_TOKEN_LIFETIME_WEB');
|
||||
|
||||
const privateKey = getPrivateKey(this.configService);
|
||||
const pubkey = getPublicKey(this.configService);
|
||||
@ -188,7 +194,7 @@ export class AuthService {
|
||||
tier: token.tier,
|
||||
userId: token.userId,
|
||||
},
|
||||
lifetime,
|
||||
this.accessTokenlifetime,
|
||||
privateKey,
|
||||
);
|
||||
|
||||
@ -205,11 +211,14 @@ export class AuthService {
|
||||
async getVerifiedIdToken(token: string): Promise<IDToken> {
|
||||
this.logger.log(`[IN] ${this.getVerifiedIdToken.name}`);
|
||||
|
||||
let kid = '';
|
||||
let kid: string | undefined = '';
|
||||
try {
|
||||
// JWTトークンのヘッダを見るため一度デコードする
|
||||
const decodedToken = jwt.decode(token, { complete: true });
|
||||
kid = decodedToken.header.kid;
|
||||
kid = decodedToken?.header.kid;
|
||||
if (!kid) {
|
||||
throw new Error('kid not found');
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
throw new HttpException(
|
||||
|
||||
@ -9,9 +9,13 @@ export type AdB2cMockValue = {
|
||||
getMetaData: B2cMetadata | Error;
|
||||
getSignKeySets: JwkSignKey[] | Error;
|
||||
};
|
||||
export type ConfigMockValue = {
|
||||
getOrThrow: number;
|
||||
};
|
||||
|
||||
export const makeAuthServiceMock = async (
|
||||
adB2cMockValue: AdB2cMockValue,
|
||||
configMockValue: ConfigMockValue,
|
||||
): Promise<AuthService> => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [AuthService],
|
||||
@ -21,7 +25,7 @@ export const makeAuthServiceMock = async (
|
||||
case AdB2cService:
|
||||
return makeAdB2cServiceMock(adB2cMockValue);
|
||||
case ConfigService:
|
||||
return {};
|
||||
return makeConfigMock(configMockValue);
|
||||
case UsersRepositoryService:
|
||||
return {};
|
||||
}
|
||||
@ -80,3 +84,16 @@ export const makeDefaultGetPublicKeyFromJwk = (jwkKey: JwkSignKey): string => {
|
||||
'-----END PUBLIC KEY-----',
|
||||
].join('\n');
|
||||
};
|
||||
export const makeConfigMock = (value: ConfigMockValue) => {
|
||||
const { getOrThrow } = value;
|
||||
|
||||
return {
|
||||
getOrThrow: jest.fn<Promise<number>, []>().mockResolvedValue(getOrThrow),
|
||||
};
|
||||
};
|
||||
|
||||
export const makeDefaultConfigValue = (): ConfigMockValue => {
|
||||
return {
|
||||
getOrThrow: 80000,
|
||||
};
|
||||
};
|
||||
|
||||
@ -158,6 +158,9 @@ export const makeDefaultUsersRepositoryMockValue =
|
||||
created_at: new Date(),
|
||||
updated_by: '',
|
||||
updated_at: new Date(),
|
||||
active_worktype_id: null,
|
||||
secondary_admin_user_id: null,
|
||||
user: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -75,7 +75,6 @@ export class LicensesController {
|
||||
@Req() req: Request,
|
||||
@Body() body: CreateOrdersRequest,
|
||||
): Promise<CreateOrdersResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -127,7 +126,6 @@ export class LicensesController {
|
||||
@Req() req: Request,
|
||||
@Body() body: IssueCardLicensesRequest,
|
||||
): Promise<IssueCardLicensesResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -184,7 +182,6 @@ export class LicensesController {
|
||||
@Req() req: Request,
|
||||
@Body() body: ActivateCardLicensesRequest,
|
||||
): Promise<ActivateCardLicensesResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -238,7 +235,6 @@ export class LicensesController {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@Req() req: Request,
|
||||
): Promise<GetAllocatableLicensesResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -300,7 +296,6 @@ export class LicensesController {
|
||||
@Req() req: Request,
|
||||
@Body() body: CancelOrderRequest,
|
||||
): Promise<CancelOrderResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
|
||||
@ -77,14 +77,14 @@ export const makeDefaultUsersRepositoryMockValue =
|
||||
user.external_id = 'external_id';
|
||||
user.account_id = 123;
|
||||
user.role = 'none';
|
||||
user.author_id = undefined;
|
||||
user.author_id = null;
|
||||
user.accepted_eula_version = '1.0';
|
||||
user.accepted_dpa_version = '1.0';
|
||||
user.email_verified = true;
|
||||
user.auto_renew = false;
|
||||
user.license_alert = false;
|
||||
user.notification = false;
|
||||
user.deleted_at = undefined;
|
||||
user.deleted_at = null;
|
||||
user.created_by = 'test';
|
||||
user.created_at = new Date();
|
||||
user.updated_by = 'test';
|
||||
|
||||
@ -84,7 +84,6 @@ export class TasksController {
|
||||
@Req() req,
|
||||
@Query() body: TasksRequest,
|
||||
): Promise<TasksResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -204,7 +203,7 @@ export class TasksController {
|
||||
@Param() param: ChangeStatusRequest,
|
||||
): Promise<ChangeStatusResponse> {
|
||||
// AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -274,7 +273,7 @@ export class TasksController {
|
||||
): Promise<ChangeStatusResponse> {
|
||||
const { audioFileId } = params;
|
||||
// AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -341,7 +340,7 @@ export class TasksController {
|
||||
): Promise<ChangeStatusResponse> {
|
||||
const { audioFileId } = params;
|
||||
// AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -410,7 +409,7 @@ export class TasksController {
|
||||
): Promise<ChangeStatusResponse> {
|
||||
const { audioFileId } = params;
|
||||
// AuthGuardでチェック済みなのでここでのアクセストークンチェックはしない
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -560,7 +559,7 @@ export class TasksController {
|
||||
@Body() body: PostCheckoutPermissionRequest,
|
||||
): Promise<PostCheckoutPermissionResponse> {
|
||||
const { assignees } = body;
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
|
||||
@ -66,7 +66,7 @@ describe('getTemplates', () => {
|
||||
expect(templates[1].id).toBe(template2.id);
|
||||
expect(templates[1].name).toBe(template2.file_name);
|
||||
}
|
||||
}, 6000000);
|
||||
});
|
||||
|
||||
it('テンプレートファイル一覧を取得できる(0件)', async () => {
|
||||
if (!source) fail();
|
||||
|
||||
@ -23,6 +23,9 @@ export const createTemplateFile = async (
|
||||
id: template.id,
|
||||
},
|
||||
});
|
||||
if (!templateFile) {
|
||||
fail();
|
||||
}
|
||||
|
||||
return templateFile;
|
||||
};
|
||||
|
||||
@ -8,7 +8,7 @@ import { HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
|
||||
describe('利用規約取得', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -21,12 +21,15 @@ describe('利用規約取得', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('最新の利用規約情報が取得できる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<TermsService>(TermsService);
|
||||
|
||||
await createTermInfo(source, 'EULA', 'v1.0');
|
||||
@ -44,7 +47,9 @@ describe('利用規約取得', () => {
|
||||
});
|
||||
|
||||
it('利用規約情報(EULA、DPA両方)が存在しない場合エラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<TermsService>(TermsService);
|
||||
const context = makeContext(uuidv4());
|
||||
await expect(service.getTermsInfo(context)).rejects.toEqual(
|
||||
@ -56,7 +61,9 @@ describe('利用規約取得', () => {
|
||||
});
|
||||
|
||||
it('利用規約情報(EULAのみ)が存在しない場合エラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<TermsService>(TermsService);
|
||||
await createTermInfo(source, 'DPA', 'v1.0');
|
||||
const context = makeContext(uuidv4());
|
||||
@ -69,7 +76,9 @@ describe('利用規約取得', () => {
|
||||
});
|
||||
|
||||
it('利用規約情報(DPAのみ)が存在しない場合エラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<TermsService>(TermsService);
|
||||
await createTermInfo(source, 'EULA', 'v1.0');
|
||||
const context = makeContext(uuidv4());
|
||||
|
||||
@ -406,7 +406,7 @@ const AdB2cMockUsers: AdB2cUser[] = [
|
||||
displayName: 'test1',
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EAMILADDRESS,
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: 'issuer',
|
||||
issuerAssignedId: 'test1@mail.com',
|
||||
},
|
||||
@ -417,7 +417,7 @@ const AdB2cMockUsers: AdB2cUser[] = [
|
||||
displayName: 'test2',
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EAMILADDRESS,
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: 'issuer',
|
||||
issuerAssignedId: 'test2@mail.com',
|
||||
},
|
||||
@ -428,7 +428,7 @@ const AdB2cMockUsers: AdB2cUser[] = [
|
||||
displayName: 'test3',
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EAMILADDRESS,
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: 'issuer',
|
||||
issuerAssignedId: 'test3@mail.com',
|
||||
},
|
||||
|
||||
@ -130,7 +130,6 @@ export class UsersController {
|
||||
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
|
||||
@Get()
|
||||
async getUsers(@Req() req: Request): Promise<GetUsersResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -193,7 +192,6 @@ export class UsersController {
|
||||
prompt,
|
||||
} = body;
|
||||
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -253,7 +251,6 @@ export class UsersController {
|
||||
@UseGuards(AuthGuard)
|
||||
@Get('relations')
|
||||
async getRelations(@Req() req: Request): Promise<GetRelationsResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -307,7 +304,7 @@ export class UsersController {
|
||||
@Req() req: Request,
|
||||
): Promise<PostSortCriteriaResponse> {
|
||||
const { direction, paramName } = body;
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -365,7 +362,7 @@ export class UsersController {
|
||||
@Req() req: Request,
|
||||
): Promise<GetSortCriteriaResponse> {
|
||||
const {} = query;
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -432,7 +429,6 @@ export class UsersController {
|
||||
prompt,
|
||||
} = body;
|
||||
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -501,7 +497,6 @@ export class UsersController {
|
||||
@Body() body: AllocateLicenseRequest,
|
||||
@Req() req: Request,
|
||||
): Promise<AllocateLicenseResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -561,7 +556,6 @@ export class UsersController {
|
||||
@Body() body: DeallocateLicenseRequest,
|
||||
@Req() req: Request,
|
||||
): Promise<DeallocateLicenseResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
|
||||
@ -116,7 +116,7 @@ describe('UsersService.confirmUser', () => {
|
||||
user: resultLicenses[0].user ?? null,
|
||||
};
|
||||
|
||||
expect(resultUser.email_verified).toBe(true);
|
||||
expect(resultUser?.email_verified).toBe(true);
|
||||
expect(resultLicenses.length).toBe(100);
|
||||
expect(resultLicensesCheckParam).toEqual({
|
||||
id: 0,
|
||||
@ -1764,7 +1764,7 @@ describe('UsersService.getUsers', () => {
|
||||
await expect(service.getUsers('externalId_failed')).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E009999'), HttpStatus.NOT_FOUND),
|
||||
);
|
||||
}, 60000000);
|
||||
});
|
||||
|
||||
it('ADB2Cからのユーザーの取得に失敗した場合、エラーとなる', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
@ -2030,15 +2030,15 @@ describe('UsersService.updateUser', () => {
|
||||
|
||||
const createdUser = await getUser(source, user1);
|
||||
|
||||
expect(createdUser.id).toBe(user1);
|
||||
expect(createdUser.role).toBe(USER_ROLES.NONE);
|
||||
expect(createdUser.author_id).toBeNull();
|
||||
expect(createdUser.auto_renew).toBe(false);
|
||||
expect(createdUser.license_alert).toBe(false);
|
||||
expect(createdUser.notification).toBe(false);
|
||||
expect(createdUser.encryption).toBe(false);
|
||||
expect(createdUser.encryption_password).toBeNull();
|
||||
expect(createdUser.prompt).toBe(false);
|
||||
expect(createdUser?.id).toBe(user1);
|
||||
expect(createdUser?.role).toBe(USER_ROLES.NONE);
|
||||
expect(createdUser?.author_id).toBeNull();
|
||||
expect(createdUser?.auto_renew).toBe(false);
|
||||
expect(createdUser?.license_alert).toBe(false);
|
||||
expect(createdUser?.notification).toBe(false);
|
||||
expect(createdUser?.encryption).toBe(false);
|
||||
expect(createdUser?.encryption_password).toBeNull();
|
||||
expect(createdUser?.prompt).toBe(false);
|
||||
});
|
||||
|
||||
it('ユーザー情報を更新できる(Typist)', async () => {
|
||||
@ -2088,15 +2088,15 @@ describe('UsersService.updateUser', () => {
|
||||
|
||||
const createdUser = await getUser(source, user1);
|
||||
|
||||
expect(createdUser.id).toBe(user1);
|
||||
expect(createdUser.role).toBe(USER_ROLES.TYPIST);
|
||||
expect(createdUser.author_id).toBeNull();
|
||||
expect(createdUser.auto_renew).toBe(false);
|
||||
expect(createdUser.license_alert).toBe(false);
|
||||
expect(createdUser.notification).toBe(false);
|
||||
expect(createdUser.encryption).toBe(false);
|
||||
expect(createdUser.encryption_password).toBeNull();
|
||||
expect(createdUser.prompt).toBe(false);
|
||||
expect(createdUser?.id).toBe(user1);
|
||||
expect(createdUser?.role).toBe(USER_ROLES.TYPIST);
|
||||
expect(createdUser?.author_id).toBeNull();
|
||||
expect(createdUser?.auto_renew).toBe(false);
|
||||
expect(createdUser?.license_alert).toBe(false);
|
||||
expect(createdUser?.notification).toBe(false);
|
||||
expect(createdUser?.encryption).toBe(false);
|
||||
expect(createdUser?.encryption_password).toBeNull();
|
||||
expect(createdUser?.prompt).toBe(false);
|
||||
});
|
||||
|
||||
it('ユーザー情報を更新できる(Author)', async () => {
|
||||
@ -2146,15 +2146,15 @@ describe('UsersService.updateUser', () => {
|
||||
|
||||
const createdUser = await getUser(source, user1);
|
||||
|
||||
expect(createdUser.id).toBe(user1);
|
||||
expect(createdUser.role).toBe(USER_ROLES.AUTHOR);
|
||||
expect(createdUser.author_id).toBe('AUTHOR_ID');
|
||||
expect(createdUser.auto_renew).toBe(false);
|
||||
expect(createdUser.license_alert).toBe(false);
|
||||
expect(createdUser.notification).toBe(false);
|
||||
expect(createdUser.encryption).toBe(true);
|
||||
expect(createdUser.encryption_password).toBe('new_password');
|
||||
expect(createdUser.prompt).toBe(true);
|
||||
expect(createdUser?.id).toBe(user1);
|
||||
expect(createdUser?.role).toBe(USER_ROLES.AUTHOR);
|
||||
expect(createdUser?.author_id).toBe('AUTHOR_ID');
|
||||
expect(createdUser?.auto_renew).toBe(false);
|
||||
expect(createdUser?.license_alert).toBe(false);
|
||||
expect(createdUser?.notification).toBe(false);
|
||||
expect(createdUser?.encryption).toBe(true);
|
||||
expect(createdUser?.encryption_password).toBe('new_password');
|
||||
expect(createdUser?.prompt).toBe(true);
|
||||
});
|
||||
|
||||
it('ユーザーのRoleを更新できる(None⇒Typist)', async () => {
|
||||
@ -2204,15 +2204,15 @@ describe('UsersService.updateUser', () => {
|
||||
|
||||
const createdUser = await getUser(source, user1);
|
||||
|
||||
expect(createdUser.id).toBe(user1);
|
||||
expect(createdUser.role).toBe(USER_ROLES.TYPIST);
|
||||
expect(createdUser.author_id).toBeNull();
|
||||
expect(createdUser.auto_renew).toBe(false);
|
||||
expect(createdUser.license_alert).toBe(false);
|
||||
expect(createdUser.notification).toBe(false);
|
||||
expect(createdUser.encryption).toBe(false);
|
||||
expect(createdUser.encryption_password).toBeNull();
|
||||
expect(createdUser.prompt).toBe(false);
|
||||
expect(createdUser?.id).toBe(user1);
|
||||
expect(createdUser?.role).toBe(USER_ROLES.TYPIST);
|
||||
expect(createdUser?.author_id).toBeNull();
|
||||
expect(createdUser?.auto_renew).toBe(false);
|
||||
expect(createdUser?.license_alert).toBe(false);
|
||||
expect(createdUser?.notification).toBe(false);
|
||||
expect(createdUser?.encryption).toBe(false);
|
||||
expect(createdUser?.encryption_password).toBeNull();
|
||||
expect(createdUser?.prompt).toBe(false);
|
||||
});
|
||||
|
||||
it('ユーザーのRoleを更新できる(None⇒Author)', async () => {
|
||||
@ -2262,15 +2262,15 @@ describe('UsersService.updateUser', () => {
|
||||
|
||||
const createdUser = await getUser(source, user1);
|
||||
|
||||
expect(createdUser.id).toBe(user1);
|
||||
expect(createdUser.role).toBe(USER_ROLES.AUTHOR);
|
||||
expect(createdUser.author_id).toBe('AUTHOR_ID');
|
||||
expect(createdUser.auto_renew).toBe(false);
|
||||
expect(createdUser.license_alert).toBe(false);
|
||||
expect(createdUser.notification).toBe(false);
|
||||
expect(createdUser.encryption).toBe(false);
|
||||
expect(createdUser.encryption_password).toBeNull();
|
||||
expect(createdUser.prompt).toBe(false);
|
||||
expect(createdUser?.id).toBe(user1);
|
||||
expect(createdUser?.role).toBe(USER_ROLES.AUTHOR);
|
||||
expect(createdUser?.author_id).toBe('AUTHOR_ID');
|
||||
expect(createdUser?.auto_renew).toBe(false);
|
||||
expect(createdUser?.license_alert).toBe(false);
|
||||
expect(createdUser?.notification).toBe(false);
|
||||
expect(createdUser?.encryption).toBe(false);
|
||||
expect(createdUser?.encryption_password).toBeNull();
|
||||
expect(createdUser?.prompt).toBe(false);
|
||||
});
|
||||
|
||||
it('None以外からRoleを変更した場合、エラーとなる(Typist⇒None)', async () => {
|
||||
@ -2368,15 +2368,15 @@ describe('UsersService.updateUser', () => {
|
||||
|
||||
const createdUser = await getUser(source, user1);
|
||||
|
||||
expect(createdUser.id).toBe(user1);
|
||||
expect(createdUser.role).toBe(USER_ROLES.AUTHOR);
|
||||
expect(createdUser.author_id).toBe('AUTHOR_ID');
|
||||
expect(createdUser.auto_renew).toBe(false);
|
||||
expect(createdUser.license_alert).toBe(false);
|
||||
expect(createdUser.notification).toBe(false);
|
||||
expect(createdUser.encryption).toBe(true);
|
||||
expect(createdUser.encryption_password).toBe('password');
|
||||
expect(createdUser.prompt).toBe(true);
|
||||
expect(createdUser?.id).toBe(user1);
|
||||
expect(createdUser?.role).toBe(USER_ROLES.AUTHOR);
|
||||
expect(createdUser?.author_id).toBe('AUTHOR_ID');
|
||||
expect(createdUser?.auto_renew).toBe(false);
|
||||
expect(createdUser?.license_alert).toBe(false);
|
||||
expect(createdUser?.notification).toBe(false);
|
||||
expect(createdUser?.encryption).toBe(true);
|
||||
expect(createdUser?.encryption_password).toBe('password');
|
||||
expect(createdUser?.prompt).toBe(true);
|
||||
});
|
||||
|
||||
it('Authorが暗号化なしで更新した場合、パスワードをNULLにする(Encryptionがfalse)', async () => {
|
||||
@ -2426,15 +2426,15 @@ describe('UsersService.updateUser', () => {
|
||||
|
||||
const createdUser = await getUser(source, user1);
|
||||
|
||||
expect(createdUser.id).toBe(user1);
|
||||
expect(createdUser.role).toBe(USER_ROLES.AUTHOR);
|
||||
expect(createdUser.author_id).toBe('AUTHOR_ID');
|
||||
expect(createdUser.auto_renew).toBe(false);
|
||||
expect(createdUser.license_alert).toBe(false);
|
||||
expect(createdUser.notification).toBe(false);
|
||||
expect(createdUser.encryption).toBe(false);
|
||||
expect(createdUser.encryption_password).toBeNull();
|
||||
expect(createdUser.prompt).toBe(true);
|
||||
expect(createdUser?.id).toBe(user1);
|
||||
expect(createdUser?.role).toBe(USER_ROLES.AUTHOR);
|
||||
expect(createdUser?.author_id).toBe('AUTHOR_ID');
|
||||
expect(createdUser?.auto_renew).toBe(false);
|
||||
expect(createdUser?.license_alert).toBe(false);
|
||||
expect(createdUser?.notification).toBe(false);
|
||||
expect(createdUser?.encryption).toBe(false);
|
||||
expect(createdUser?.encryption_password).toBeNull();
|
||||
expect(createdUser?.prompt).toBe(true);
|
||||
});
|
||||
|
||||
it('AuthorのDBにパスワードが設定されていない場合、パスワードundefinedでわたすとエラーとなる(Encryptionがtrue)', async () => {
|
||||
@ -2577,7 +2577,7 @@ describe('UsersService.updateAcceptedVersion', () => {
|
||||
await service.updateAcceptedVersion(context, admin.external_id, 'v2.0');
|
||||
const user = await getUser(source, admin.id);
|
||||
|
||||
expect(user.accepted_eula_version).toBe('v2.0');
|
||||
expect(user?.accepted_eula_version).toBe('v2.0');
|
||||
});
|
||||
|
||||
it('同意済み利用規約バージョンを更新できる(第一~第四)', async () => {
|
||||
@ -2598,8 +2598,8 @@ describe('UsersService.updateAcceptedVersion', () => {
|
||||
);
|
||||
const user = await getUser(source, admin.id);
|
||||
|
||||
expect(user.accepted_eula_version).toBe('v2.0');
|
||||
expect(user.accepted_dpa_version).toBe('v3.0');
|
||||
expect(user?.accepted_eula_version).toBe('v2.0');
|
||||
expect(user?.accepted_dpa_version).toBe('v3.0');
|
||||
});
|
||||
|
||||
it('パラメータが不在のときエラーとなる(第一~第四)', async () => {
|
||||
|
||||
@ -486,7 +486,7 @@ export class UsersService {
|
||||
|
||||
// メールアドレスを取得する
|
||||
const mail = adb2cUser?.identities?.find(
|
||||
(identity) => identity.signInType === ADB2C_SIGN_IN_TYPE.EAMILADDRESS,
|
||||
(identity) => identity.signInType === ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
)?.issuerAssignedId;
|
||||
|
||||
//メールアドレスが取得できない場合はエラー
|
||||
|
||||
@ -49,7 +49,7 @@ export const getWorkflow = async (
|
||||
datasource: DataSource,
|
||||
accountId: number,
|
||||
id: number,
|
||||
): Promise<Workflow> => {
|
||||
): Promise<Workflow | null> => {
|
||||
return await datasource.getRepository(Workflow).findOne({
|
||||
where: {
|
||||
account_id: accountId,
|
||||
|
||||
@ -66,7 +66,6 @@ export class WorkflowsController {
|
||||
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
|
||||
@Get()
|
||||
async getWorkflows(@Req() req: Request): Promise<GetWorkflowsResponse> {
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -123,7 +122,7 @@ export class WorkflowsController {
|
||||
@Body() body: CreateWorkflowsRequest,
|
||||
): Promise<CreateWorkflowsResponse> {
|
||||
const { authorId, worktypeId, templateId, typists } = body;
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -188,7 +187,7 @@ export class WorkflowsController {
|
||||
): Promise<UpdateWorkflowResponse> {
|
||||
const { authorId, worktypeId, templateId, typists } = body;
|
||||
const { workflowId } = param;
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
@ -252,7 +251,7 @@ export class WorkflowsController {
|
||||
@Param() param: DeleteWorkflowRequestParam,
|
||||
): Promise<DeleteWorkflowResponse> {
|
||||
const { workflowId } = param;
|
||||
// TODO strictNullChecks対応
|
||||
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
|
||||
@ -40,8 +40,8 @@ export class AdB2cService {
|
||||
// ADB2Cへの認証情報
|
||||
const credential = new ClientSecretCredential(
|
||||
this.configService.getOrThrow<string>('ADB2C_TENANT_ID'),
|
||||
this.configService.getOrThrow('ADB2C_CLIENT_ID'),
|
||||
this.configService.getOrThrow('ADB2C_CLIENT_SECRET'),
|
||||
this.configService.getOrThrow<string>('ADB2C_CLIENT_ID'),
|
||||
this.configService.getOrThrow<string>('ADB2C_CLIENT_SECRET'),
|
||||
);
|
||||
const authProvider = new TokenCredentialAuthenticationProvider(credential, {
|
||||
scopes: ['https://graph.microsoft.com/.default'],
|
||||
@ -76,7 +76,7 @@ export class AdB2cService {
|
||||
},
|
||||
identities: [
|
||||
{
|
||||
signinType: ADB2C_SIGN_IN_TYPE.EAMILADDRESS,
|
||||
signinType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: `${this.tenantName}.onmicrosoft.com`,
|
||||
issuerAssignedId: email,
|
||||
},
|
||||
|
||||
@ -9,7 +9,7 @@ import { Context } from '../../common/log';
|
||||
export class SendGridService {
|
||||
private readonly logger = new Logger(SendGridService.name);
|
||||
private readonly emailConfirmLifetime: number;
|
||||
readonly appDomain: string;
|
||||
private readonly appDomain: string;
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
this.appDomain = this.configService.getOrThrow<string>('APP_DOMAIN');
|
||||
this.emailConfirmLifetime = this.configService.getOrThrow<number>(
|
||||
|
||||
@ -126,13 +126,13 @@ export class AccountsRepositoryService {
|
||||
tier: number,
|
||||
adminExternalUserId: string,
|
||||
adminUserRole: string,
|
||||
adminUserAcceptedEulaVersion: string,
|
||||
adminUserAcceptedDpaVersion: string,
|
||||
adminUserAcceptedEulaVersion?: string,
|
||||
adminUserAcceptedDpaVersion?: string,
|
||||
): Promise<{ newAccount: Account; adminUser: User }> {
|
||||
return await this.dataSource.transaction(async (entityManager) => {
|
||||
const account = new Account();
|
||||
{
|
||||
account.parent_account_id = dealerAccountId;
|
||||
account.parent_account_id = dealerAccountId ?? null;
|
||||
account.company_name = companyName;
|
||||
account.country = country;
|
||||
account.tier = tier;
|
||||
@ -147,8 +147,8 @@ export class AccountsRepositoryService {
|
||||
user.account_id = persistedAccount.id;
|
||||
user.external_id = adminExternalUserId;
|
||||
user.role = adminUserRole;
|
||||
user.accepted_eula_version = adminUserAcceptedEulaVersion;
|
||||
user.accepted_dpa_version = adminUserAcceptedDpaVersion;
|
||||
user.accepted_eula_version = adminUserAcceptedEulaVersion ?? null;
|
||||
user.accepted_dpa_version = adminUserAcceptedDpaVersion ?? null;
|
||||
}
|
||||
const usersRepo = entityManager.getRepository(User);
|
||||
const newUser = usersRepo.create(user);
|
||||
@ -499,6 +499,9 @@ export class AccountsRepositoryService {
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
if (!ownAccount) {
|
||||
throw new AccountNotFoundError();
|
||||
}
|
||||
|
||||
// 自アカウントのライセンス注文状況を取得する
|
||||
const ownLicenseOrderStatus = await this.getAccountLicenseOrderStatus(
|
||||
@ -541,8 +544,8 @@ export class AccountsRepositoryService {
|
||||
);
|
||||
|
||||
// 第五の不足数を算出するためのライセンス数情報を取得する
|
||||
let expiringSoonLicense: number;
|
||||
let allocatableLicenseWithMargin: number;
|
||||
let expiringSoonLicense: number = 0;
|
||||
let allocatableLicenseWithMargin: number = 0;
|
||||
if (childAccount.tier === TIERS.TIER5) {
|
||||
expiringSoonLicense = await this.getExpiringSoonLicense(
|
||||
entityManager,
|
||||
@ -615,7 +618,7 @@ export class AccountsRepositoryService {
|
||||
return await this.dataSource.transaction(async (entityManager) => {
|
||||
const accountRepository = entityManager.getRepository(Account);
|
||||
const maxTierDifference = TIERS.TIER5 - TIERS.TIER1;
|
||||
const parentAccountIds = [];
|
||||
const parentAccountIds: number[] = [];
|
||||
|
||||
let currentAccountId = targetAccountId;
|
||||
// システム的な最大の階層差異分、親を参照する
|
||||
@ -628,6 +631,9 @@ export class AccountsRepositoryService {
|
||||
if (!account) {
|
||||
break;
|
||||
}
|
||||
if (!account.parent_account_id) {
|
||||
throw new Error("Parent account doesn't exist.");
|
||||
}
|
||||
|
||||
parentAccountIds.push(account.parent_account_id);
|
||||
currentAccountId = account.parent_account_id;
|
||||
@ -749,11 +755,13 @@ export class AccountsRepositoryService {
|
||||
});
|
||||
|
||||
// ADB2Cから情報を取得するための外部ユーザIDを取得する(念のためプライマリ管理者IDが存在しない場合を考慮)
|
||||
const primaryUserIds = partnerAccounts.map((x) => {
|
||||
const primaryUserIds = partnerAccounts.flatMap((x) => {
|
||||
if (x.primary_admin_user_id) {
|
||||
return x.primary_admin_user_id;
|
||||
return [x.primary_admin_user_id];
|
||||
} else if (x.secondary_admin_user_id) {
|
||||
return x.secondary_admin_user_id;
|
||||
return [x.secondary_admin_user_id];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
const userRepo = entityManager.getRepository(User);
|
||||
@ -770,15 +778,18 @@ export class AccountsRepositoryService {
|
||||
user.id === account.primary_admin_user_id ||
|
||||
user.id === account.secondary_admin_user_id,
|
||||
);
|
||||
const primaryAccountExternalId = primaryUser
|
||||
? primaryUser.external_id
|
||||
: undefined;
|
||||
if (!primaryUser) {
|
||||
throw new AdminUserNotFoundError(
|
||||
`Primary admin user is not found. id: ${account.primary_admin_user_id}, account_id: ${account.id}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
name: account.company_name,
|
||||
tier: account.tier,
|
||||
accountId: account.id,
|
||||
country: account.country,
|
||||
primaryAccountExternalId: primaryAccountExternalId,
|
||||
primaryAccountExternalId: primaryUser.external_id,
|
||||
dealerManagement: account.delegation_permission,
|
||||
};
|
||||
});
|
||||
@ -799,7 +810,7 @@ export class AccountsRepositoryService {
|
||||
async getOneUpperTierAccount(
|
||||
accountId: number,
|
||||
tier: number,
|
||||
): Promise<Account | undefined> {
|
||||
): Promise<Account | null> {
|
||||
return await this.dataSource.transaction(async (entityManager) => {
|
||||
const accountRepo = entityManager.getRepository(Account);
|
||||
return await accountRepo.findOne({
|
||||
@ -878,10 +889,10 @@ export class AccountsRepositoryService {
|
||||
await accountRepo.update(
|
||||
{ id: myAccountId },
|
||||
{
|
||||
parent_account_id: parentAccountId || null,
|
||||
parent_account_id: parentAccountId ?? null,
|
||||
delegation_permission: delegationPermission,
|
||||
primary_admin_user_id: primaryAdminUserId,
|
||||
secondary_admin_user_id: secondryAdminUserId || null,
|
||||
secondary_admin_user_id: secondryAdminUserId ?? null,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@ -13,7 +13,7 @@ export class Account {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
parent_account_id: number | null;
|
||||
|
||||
@Column()
|
||||
@ -34,30 +34,36 @@ export class Account {
|
||||
@Column({ default: false })
|
||||
verified: boolean;
|
||||
|
||||
@Column({ nullable: true })
|
||||
primary_admin_user_id?: number;
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
primary_admin_user_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
secondary_admin_user_id?: number;
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
secondary_admin_user_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
active_worktype_id?: number;
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
active_worktype_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by?: string;
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by?: string;
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date;
|
||||
|
||||
@OneToMany(() => User, (user) => user.id)
|
||||
user?: User[];
|
||||
user: User[] | null;
|
||||
}
|
||||
|
||||
@ -32,9 +32,9 @@ export class AudioFile {
|
||||
priority: string;
|
||||
@Column()
|
||||
audio_format: string;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
comment: string | null;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
@Column()
|
||||
is_encrypted: boolean;
|
||||
|
||||
@ -18,10 +18,10 @@ export class CheckoutPermission {
|
||||
@Column({})
|
||||
task_id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
user_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
user_group_id: number | null;
|
||||
|
||||
@OneToOne(() => User, (user) => user.id)
|
||||
|
||||
@ -25,10 +25,13 @@ export class LicenseOrder {
|
||||
@Column()
|
||||
to_account_id: number;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
ordered_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
issued_at: Date | null;
|
||||
|
||||
@Column()
|
||||
@ -37,19 +40,25 @@ export class LicenseOrder {
|
||||
@Column()
|
||||
status: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
canceled_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
@ -58,7 +67,7 @@ export class License {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
expiry_date: Date | null;
|
||||
|
||||
@Column()
|
||||
@ -70,28 +79,34 @@ export class License {
|
||||
@Column()
|
||||
status: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
allocated_user_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
order_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
delete_order_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
updated_at: Date;
|
||||
|
||||
@OneToOne(() => User, (user) => user.license, {
|
||||
@ -109,16 +124,22 @@ export class CardLicenseIssue {
|
||||
@Column()
|
||||
issued_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
@ -133,19 +154,25 @@ export class CardLicense {
|
||||
@Column()
|
||||
card_license_key: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
activated_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
@ -172,19 +199,25 @@ export class LicenseAllocationHistory {
|
||||
@Column()
|
||||
switch_from_type: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
updated_at: Date;
|
||||
|
||||
@ManyToOne(() => License, (licenses) => licenses.id, {
|
||||
@ -199,7 +232,7 @@ export class LicenseArchive {
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
expiry_date: Date | null;
|
||||
|
||||
@Column()
|
||||
@ -211,31 +244,34 @@ export class LicenseArchive {
|
||||
@Column()
|
||||
status: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
allocated_user_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
order_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
delete_order_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@Column()
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@Column()
|
||||
updated_at: Date;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
archived_at: Date;
|
||||
}
|
||||
|
||||
@ -262,21 +298,24 @@ export class LicenseAllocationHistoryArchive {
|
||||
@Column()
|
||||
switch_from_type: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@Column()
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@Column()
|
||||
updated_at: Date;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
})
|
||||
archived_at: Date;
|
||||
}
|
||||
|
||||
@ -20,21 +20,21 @@ export class Task {
|
||||
job_number: string;
|
||||
@Column()
|
||||
account_id: number;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'tinyint' })
|
||||
is_job_number_enabled: boolean | null;
|
||||
@Column()
|
||||
audio_file_id: number;
|
||||
@Column()
|
||||
status: string;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
typist_user_id: number | null;
|
||||
@Column()
|
||||
priority: string;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
template_file_id: number | null;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
started_at: Date | null;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
finished_at: Date | null;
|
||||
@Column({})
|
||||
created_at: Date;
|
||||
|
||||
@ -18,11 +18,11 @@ export class TemplateFile {
|
||||
url: string;
|
||||
@Column()
|
||||
file_name: string;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
@CreateDateColumn()
|
||||
created_at: Date;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
@UpdateDateColumn()
|
||||
updated_at: Date;
|
||||
|
||||
@ -17,15 +17,21 @@ export class Term {
|
||||
@Column()
|
||||
version: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by?: string;
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
@ -19,19 +19,25 @@ export class UserGroup {
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date | null;
|
||||
|
||||
@OneToMany(
|
||||
|
||||
@ -21,19 +21,25 @@ export class UserGroupMember {
|
||||
@Column()
|
||||
user_id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date | null;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.id)
|
||||
|
||||
@ -28,13 +28,13 @@ export class User {
|
||||
@Column()
|
||||
role: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
author_id: string | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
accepted_eula_version: string | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
accepted_dpa_version: string | null;
|
||||
|
||||
@Column({ default: false })
|
||||
@ -52,25 +52,31 @@ export class User {
|
||||
@Column({ default: false })
|
||||
encryption: boolean;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
encryption_password: string | null;
|
||||
|
||||
@Column({ default: false })
|
||||
prompt: boolean;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date;
|
||||
|
||||
@ManyToOne(() => Account, (account) => account.user, {
|
||||
@ -100,13 +106,13 @@ export class UserArchive {
|
||||
@Column()
|
||||
role: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
author_id: string | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
accepted_eula_version: string | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
accepted_dpa_version: string | null;
|
||||
|
||||
@Column()
|
||||
@ -127,22 +133,25 @@ export class UserArchive {
|
||||
@Column()
|
||||
prompt: boolean;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@Column()
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@Column()
|
||||
updated_at: Date;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
archived_at: Date;
|
||||
}
|
||||
|
||||
|
||||
@ -471,10 +471,8 @@ export class UsersRepositoryService {
|
||||
},
|
||||
});
|
||||
|
||||
if (!latestEulaInfo.version || !latestDpaInfo.version) {
|
||||
throw new TermInfoNotFoundError(
|
||||
`Terms info is not found. latestEulaInfo: ${latestEulaInfo.version}, latestDpaInfo: ${latestDpaInfo.version}`,
|
||||
);
|
||||
if (!latestEulaInfo || !latestDpaInfo) {
|
||||
throw new TermInfoNotFoundError(`Terms info is not found.`);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@ -24,22 +24,28 @@ export class Workflow {
|
||||
@Column()
|
||||
author_id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
worktype_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
template_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.id)
|
||||
|
||||
@ -19,22 +19,28 @@ export class WorkflowTypist {
|
||||
@Column()
|
||||
workflow_id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
typist_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'unsigned big int' })
|
||||
typist_group_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date;
|
||||
|
||||
@ManyToOne(() => Workflow, (workflow) => workflow.id)
|
||||
|
||||
@ -18,12 +18,18 @@ export class OptionItem {
|
||||
default_value_type: string;
|
||||
@Column()
|
||||
initial_value: string;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at: Date | null;
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date | null;
|
||||
}
|
||||
|
||||
@ -18,21 +18,27 @@ export class Worktype {
|
||||
@Column()
|
||||
custom_worktype_id: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'varchar' })
|
||||
description: string | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@CreateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@Column({ nullable: true, type: 'datetime' })
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
@UpdateDateColumn({
|
||||
default: () => "datetime('now', 'localtime')",
|
||||
type: 'datetime',
|
||||
}) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
"baseUrl": "./",
|
||||
"incremental": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": false,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": false,
|
||||
"strictBindCallApply": false,
|
||||
"forceConsistentCasingInFileNames": false,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user