diff --git a/dictation_client/src/common/token.ts b/dictation_client/src/common/token.ts index de1e048..b5422ad 100644 --- a/dictation_client/src/common/token.ts +++ b/dictation_client/src/common/token.ts @@ -2,7 +2,7 @@ // TODO トークンの型は仮 export interface Token { userId: string; - scope: string; + role: string; exp: number; iat: number; } @@ -13,7 +13,7 @@ export const isToken = (arg: any): arg is Token => { if (arg.userId === undefined) { return false; } - if (arg.scope === undefined) { + if (arg.role === undefined) { return false; } if (arg.exp === undefined) { diff --git a/dictation_server/src/common/token/types.ts b/dictation_server/src/common/token/types.ts index f4eea6a..d3d91d4 100644 --- a/dictation_server/src/common/token/types.ts +++ b/dictation_server/src/common/token/types.ts @@ -1,11 +1,11 @@ export type RefreshToken = { userId: string; - scope: string; + role: string; }; export type AccessToken = { userId: string; - scope: string; + role: string; }; export type IDToken = { diff --git a/dictation_server/src/features/auth/auth.service.ts b/dictation_server/src/features/auth/auth.service.ts index 8cd5651..4525b80 100644 --- a/dictation_server/src/features/auth/auth.service.ts +++ b/dictation_server/src/features/auth/auth.service.ts @@ -12,6 +12,7 @@ import { } from '../../common/token'; import { AdB2cService } from '../../gateways/adb2c/adb2c.service'; import { CryptoService } from '../../gateways/crypto/crypto.service'; +import { User } from '../../repositories/users/entity/user.entity'; @Injectable() export class AuthService { @@ -56,6 +57,20 @@ export class AuthService { const lifetimeDefault = this.configService.get( 'REFRESH_TOKEN_LIFETIME_DEFAULT', ); + let user: User; + // ユーザー情報とユーザーが属しているアカウント情報を取得 + try { + user = await this.usersRepository.findUserByExternalId(idToken.sub); + if (!user.account) { + throw new Error('Account information not found'); + } + } catch (e) { + this.logger.error(`error=${e}`); + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } // 要求された環境用トークンの寿命を決定 const refreshTokenLifetime = type === 'web' ? lifetimeWeb : lifetimeDefault; @@ -63,7 +78,12 @@ export class AuthService { const privateKey = await this.cryptoService.getPrivateKey(); const token = sign( { - scope: 'test', + role: `${user.role} ${ + user.account.primary_admin_user_id === user.id || + user.account.secondary_admin_user_id === user.id + ? 'admin' + : 'standard' + }`, userId: idToken.sub, }, refreshTokenLifetime, @@ -90,7 +110,7 @@ export class AuthService { const accessToken = sign( { - scope: token.scope, + role: token.role, userId: token.userId, }, lifetime, diff --git a/dictation_server/src/features/users/users.controller.ts b/dictation_server/src/features/users/users.controller.ts index 7e618a2..5d0ff75 100644 --- a/dictation_server/src/features/users/users.controller.ts +++ b/dictation_server/src/features/users/users.controller.ts @@ -129,7 +129,7 @@ export class UsersController { } // アクセストークンの権限不足エラー - if (!confirmPermission(payload.scope)) { + if (!confirmPermission(payload.role)) { throw new HttpException( makeErrorResponse('E000108'), HttpStatus.UNAUTHORIZED, @@ -199,7 +199,7 @@ export class UsersController { ); } //アクセストークンの権限不足エラー - if (!confirmPermission(payload.scope)) { + if (!confirmPermission(payload.role)) { throw new HttpException( makeErrorResponse('E000108'), HttpStatus.UNAUTHORIZED, diff --git a/dictation_server/src/features/users/users.service.spec.ts b/dictation_server/src/features/users/users.service.spec.ts index 6c30d24..69543b8 100644 --- a/dictation_server/src/features/users/users.service.spec.ts +++ b/dictation_server/src/features/users/users.service.spec.ts @@ -259,7 +259,7 @@ describe('UsersService', () => { const autoRenew = true; const licenseAlert = true; const notification = true; - const token: AccessToken = { userId: '0001', scope: '' }; + const token: AccessToken = { userId: '0001', role: '' }; expect( await service.createUser( token, @@ -295,7 +295,7 @@ describe('UsersService', () => { const licenseAlert = true; const notification = true; const authorId = 'testID'; - const token: AccessToken = { userId: '0001', scope: '' }; + const token: AccessToken = { userId: '0001', role: '' }; expect( await service.createUser( token, @@ -332,7 +332,7 @@ describe('UsersService', () => { const licenseAlert = true; const notification = true; const typistGroupId = 111; - const token: AccessToken = { userId: '0001', scope: '' }; + const token: AccessToken = { userId: '0001', role: '' }; expect( await service.createUser( token, @@ -369,7 +369,7 @@ it('DBネットワークエラーとなる場合、エラーとなる。', async const autoRenew = true; const licenseAlert = true; const notification = true; - const token: AccessToken = { userId: '0001', scope: '' }; + const token: AccessToken = { userId: '0001', role: '' }; await expect( service.createUser( token, @@ -407,7 +407,7 @@ it('Azure ADB2Cでネットワークエラーとなる場合、エラーとな const autoRenew = true; const licenseAlert = true; const notification = true; - const token: AccessToken = { userId: '0001', scope: '' }; + const token: AccessToken = { userId: '0001', role: '' }; await expect( service.createUser( token, @@ -445,7 +445,7 @@ it('メールアドレスが重複している場合、エラーとなる。', a const autoRenew = true; const licenseAlert = true; const notification = true; - const token: AccessToken = { userId: '0001', scope: '' }; + const token: AccessToken = { userId: '0001', role: '' }; await expect( service.createUser( token, @@ -483,7 +483,7 @@ it('AuthorIDが重複している場合、エラーとなる。', async () => { const licenseAlert = true; const notification = true; const authorId = 'testID'; - const token: AccessToken = { userId: '0001', scope: '' }; + const token: AccessToken = { userId: '0001', role: '' }; await expect( service.createUser( token, diff --git a/dictation_server/src/repositories/accounts/entity/account.entity.ts b/dictation_server/src/repositories/accounts/entity/account.entity.ts index bf7d45f..88d3626 100644 --- a/dictation_server/src/repositories/accounts/entity/account.entity.ts +++ b/dictation_server/src/repositories/accounts/entity/account.entity.ts @@ -1,9 +1,11 @@ +import { User } from '../../../repositories/users/entity/user.entity'; import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, + OneToMany, } from 'typeorm'; @Entity({ name: 'accounts' }) @@ -52,4 +54,7 @@ export class Account { @UpdateDateColumn() updated_at: Date; + + @OneToMany(() => User, (user) => user.id) + user?: User[]; } diff --git a/dictation_server/src/repositories/users/entity/user.entity.ts b/dictation_server/src/repositories/users/entity/user.entity.ts index 21961c0..2f95973 100644 --- a/dictation_server/src/repositories/users/entity/user.entity.ts +++ b/dictation_server/src/repositories/users/entity/user.entity.ts @@ -1,9 +1,12 @@ +import { Account } from '../../../repositories/accounts/entity/account.entity'; import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, + ManyToOne, + JoinColumn, } from 'typeorm'; @Entity({ name: 'users' }) @@ -52,4 +55,8 @@ export class User { @UpdateDateColumn() updated_at: Date; + + @ManyToOne(() => Account, (account) => account.user) + @JoinColumn({ name: 'account_id' }) + account?: Account; } diff --git a/dictation_server/src/repositories/users/users.repository.service.ts b/dictation_server/src/repositories/users/users.repository.service.ts index 8e1c40b..8617df0 100644 --- a/dictation_server/src/repositories/users/users.repository.service.ts +++ b/dictation_server/src/repositories/users/users.repository.service.ts @@ -93,6 +93,22 @@ export class UsersRepositoryService { return user; } + async findUserByExternalId(sub: string): Promise { + const user = await this.dataSource.getRepository(User).findOne({ + where: { + external_id: sub, + }, + relations: { + account: true, + }, + }); + + if (!user) { + return undefined; + } + return user; + } + async findUserById(id: number): Promise { const user = await this.dataSource.getRepository(User).findOne({ where: {