saito.k 3a7bf60f3e Merged PR 202: 画面実装(PlayBackボタン)
## 概要
[Task1997: 画面実装(PlayBackボタン)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/1997)

- Playbackボタン押下時の挙動を実装
  - typist
    - 自身が割り当て候補となっているタスクをPlayBackする
    - 成功時、カスタムURLスキームでデスクトップアプリを起動する
  - author
    - 自身のAuthorIDと一致するタスクをPlayBackする
    - 成功時、カスタムURLスキームでデスクトップアプリを起動する
- ログイン時の、カスタムURLスキームを実際のデスクトップアプリのスキーム名に修正

## レビューポイント
- playbackAsyncのなかでソート条件更新APIを一緒に呼び出しているが問題ないか
  - ソート条件を更新するタイミングはここで問題ないか
  - ユーザーがTypistの時のみ更新するようにしたが問題ないか

## UIの変更
- https://ndstokyo.sharepoint.com/:f:/r/sites/Piranha/Shared%20Documents/General/OMDS/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88/Task1997?csf=1&web=1&e=9kLaxo

## 動作確認状況
- ローカルで確認

## 補足
- Authorの挙動はAPI側の実装が完了していないので、未確認
2023-07-04 06:06:37 +00:00

320 lines
8.3 KiB
TypeScript

import {
Body,
Controller,
Get,
HttpException,
HttpStatus,
Post,
Query,
Req,
UseGuards,
} from '@nestjs/common';
import {
ApiBearerAuth,
ApiOperation,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { Request } from 'express';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { ErrorResponse } from '../../common/error/types/types';
import { retrieveAuthorizationToken } from '../../common/http/helper';
import { AccessToken } from '../../common/token';
import {
ConfirmRequest,
ConfirmResponse,
GetRelationsResponse,
GetUsersResponse,
SignupRequest,
SignupResponse,
PostSortCriteriaRequest,
PostSortCriteriaResponse,
GetSortCriteriaRequest,
GetSortCriteriaResponse,
} from './types/types';
import { UsersService } from './users.service';
import jwt from 'jsonwebtoken';
import { AuthGuard } from '../../common/guards/auth/authguards';
import {
isSortDirection,
isTaskListSortableAttribute,
} from '../../common/types/sort';
import { ADMIN_ROLES } from '../../constants';
import { RoleGuard } from '../../common/guards/role/roleguards';
@ApiTags('users')
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@ApiResponse({
status: HttpStatus.OK,
type: ConfirmResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '不正なトークン',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'confirmUser' })
@Post('confirm')
async confirmUser(@Body() body: ConfirmRequest): Promise<ConfirmResponse> {
await this.usersService.confirmUser(body.token);
return {};
}
@ApiResponse({
status: HttpStatus.OK,
type: ConfirmResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '不正なトークン',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'confirmUserAndInitPassword' })
@Post('confirm/initpassword')
async confirmUserAndInitPassword(
@Body() body: ConfirmRequest,
): Promise<ConfirmResponse> {
console.log(body);
await this.usersService.confirmUserAndInitPassword(body.token);
return {};
}
@ApiResponse({
status: HttpStatus.OK,
type: GetUsersResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getUsers' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Get()
async getUsers(@Req() req: Request): Promise<GetUsersResponse> {
console.log(req.header('Authorization'));
const accessToken = retrieveAuthorizationToken(req);
const decodedToken = jwt.decode(accessToken, { json: true }) as AccessToken;
const users = await this.usersService.getUsers(decodedToken);
return { users };
}
@ApiResponse({
status: HttpStatus.OK,
type: SignupResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '登録済みメールによる再登録、AuthorIDの重複など',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'signup' })
@ApiBearerAuth()
@Post('/signup')
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async signup(
@Req() req: Request,
@Body() body: SignupRequest,
): Promise<SignupResponse> {
const {
name,
role,
email,
autoRenew,
licenseAlert,
notification,
authorId,
typistGroupId,
} = body;
const accessToken = retrieveAuthorizationToken(req);
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
//ユーザ作成処理
await this.usersService.createUser(
payload,
name,
role,
email,
autoRenew,
licenseAlert,
notification,
authorId,
typistGroupId,
);
return {};
}
@ApiResponse({
status: HttpStatus.OK,
type: GetRelationsResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getRelations',
description: 'ログインしているユーザーに関連する各種情報を取得します',
})
@ApiBearerAuth()
@Get('relations')
async getRelations(@Req() req: Request): Promise<GetRelationsResponse> {
console.log(req.header('Authorization'));
return {
authorId: 'AUTHOR',
authorIdList: ['AUTHOR', 'AUTHOR1'],
workTypeList: [
{
workTypeId: '1',
optionItemList: [
{
label: '1',
initialValueType: 0,
defaultValue: 'default',
},
],
},
],
isEncrypted: true,
encryptionPassword: '',
activeWorktype: '',
audioFormat: 'DS2',
prompt: true,
};
}
@ApiResponse({
status: HttpStatus.OK,
type: PostSortCriteriaResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '不正なパラメータ',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'updateSortCriteria',
description: 'ログインしているユーザーのタスクソート条件を更新します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@Post('sort-criteria')
async updateSortCriteria(
@Body() body: PostSortCriteriaRequest,
@Req() req: Request,
): Promise<PostSortCriteriaResponse> {
const { direction, paramName } = body;
const accessToken = retrieveAuthorizationToken(req);
const decodedToken = jwt.decode(accessToken, { json: true }) as AccessToken;
//型チェック
if (
!isTaskListSortableAttribute(paramName) ||
!isSortDirection(direction)
) {
throw new HttpException(
makeErrorResponse('E010001'),
HttpStatus.BAD_REQUEST,
);
}
await this.usersService.updateSortCriteria(
paramName,
direction,
decodedToken,
);
return {};
}
@ApiResponse({
status: HttpStatus.OK,
type: GetSortCriteriaResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getSortCriteria',
description: 'ログインしているユーザーのタスクソート条件を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@Get('sort-criteria')
async getSortCriteria(
@Query() query: GetSortCriteriaRequest,
@Req() req: Request,
): Promise<GetSortCriteriaResponse> {
const {} = query;
const accessToken = retrieveAuthorizationToken(req);
const decodedToken = jwt.decode(accessToken, { json: true }) as AccessToken;
const { direction, paramName } = await this.usersService.getSortCriteria(
decodedToken,
);
return { direction, paramName };
}
}