From 7c946686b7b0f1d6e254f2afcd8e84625f0ea2ec Mon Sep 17 00:00:00 2001 From: "saito.k" Date: Tue, 5 Sep 2023 05:52:49 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=20289:=20=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=82=AB=E3=83=AB=E3=81=A7Redis=E3=82=B3=E3=83=B3=E3=83=86?= =?UTF-8?q?=E3=83=8A=E3=81=AB=E6=8E=A5=E7=B6=9A=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 概要 [Task2312: ローカルでRedisコンテナに接続する](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2312) - 元PBI or タスクへのリンク(内容・目的などはそちらにあるはず) - 何をどう変更したか、追加したライブラリなど - このPull Requestでの対象/対象外 - 影響範囲(他の機能にも影響があるか) ## レビューポイント - 特にレビューしてほしい箇所 - 軽微なものや自明なものは記載不要 - 修正範囲が大きい場合などに記載 - 全体的にや仕様を満たしているか等は本当に必要な時のみ記載 ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## 動作確認状況 - ローカルで確認、develop環境で確認など ## 補足 - 相談、参考資料などがあれば --- .env | 1 + dictation_server/.env.local.example | 3 + dictation_server/package-lock.json | 111 ++++++++++++++++++ dictation_server/package.json | 3 + dictation_server/src/app.module.ts | 2 + .../src/common/redis/redis.module.ts | 36 ++++++ .../src/common/redis/redis.service.ts | 30 +++++ .../src/features/auth/auth.controller.ts | 9 +- .../src/features/auth/auth.module.ts | 4 +- docker-compose.yml | 5 +- 10 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 dictation_server/src/common/redis/redis.module.ts create mode 100644 dictation_server/src/common/redis/redis.service.ts diff --git a/.env b/.env index b2baf36..43a16b8 100644 --- a/.env +++ b/.env @@ -5,4 +5,5 @@ DB_NAME=omds DB_ROOT_PASS=omdsdbpass DB_USERNAME=omdsdbuser DB_PASSWORD=omdsdbpass +REDIS_PASSWORD=omdsredispass NO_COLOR=TRUE \ No newline at end of file diff --git a/dictation_server/.env.local.example b/dictation_server/.env.local.example index 5cfa845..1acdf09 100644 --- a/dictation_server/.env.local.example +++ b/dictation_server/.env.local.example @@ -25,3 +25,6 @@ STORAGE_ACCOUNT_KEY_EU=XXXXXXXXXXXXXXXXXXXXXXX STORAGE_ACCOUNT_ENDPOINT_US=https://AAAAAAAAAAAAA STORAGE_ACCOUNT_ENDPOINT_AU=https://AAAAAAAAAAAAA STORAGE_ACCOUNT_ENDPOINT_EU=https://AAAAAAAAAAAAA +REDIS_HOST=redis-cache +REDIS_PORT=6379 +REDIS_PASSWORD=omdsredispass \ No newline at end of file diff --git a/dictation_server/package-lock.json b/dictation_server/package-lock.json index 8c3825c..d9fffb4 100644 --- a/dictation_server/package-lock.json +++ b/dictation_server/package-lock.json @@ -26,6 +26,8 @@ "@types/jsonwebtoken": "^9.0.1", "@types/uuid": "^8.3.4", "axios": "^1.3.4", + "cache-manager": "^5.2.0", + "cache-manager-redis-store": "^2.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "connect-redis": "^6.1.3", @@ -47,6 +49,7 @@ "@nestjs/schematics": "^8.0.0", "@nestjs/swagger": "^6.3.0", "@nestjs/testing": "^9.3.12", + "@types/cache-manager-redis-store": "^2.0.1", "@types/cookie-parser": "^1.4.3", "@types/express": "^4.17.13", "@types/express-session": "^1.17.5", @@ -2859,6 +2862,22 @@ "@types/node": "*" } }, + "node_modules/@types/cache-manager": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/cache-manager/-/cache-manager-4.0.2.tgz", + "integrity": "sha512-fT5FMdzsiSX0AbgnS5gDvHl2Nco0h5zYyjwDQy4yPC7Ww6DeGMVKPRqIZtg9HOXDV2kkc18SL1B0N8f0BecrCA==", + "dev": true + }, + "node_modules/@types/cache-manager-redis-store": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/cache-manager-redis-store/-/cache-manager-redis-store-2.0.1.tgz", + "integrity": "sha512-8QuccvcPieh1xM/5kReE76SfdcIdEB0ePc+54ah/NBuK2eG+6O50SX4WKoJX81UxGdW3sh/WlDaDNqjnqxWNsA==", + "dev": true, + "dependencies": { + "@types/cache-manager": "*", + "@types/redis": "^2.8.0" + } + }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -3062,6 +3081,15 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "node_modules/@types/redis": { + "version": "2.8.32", + "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.32.tgz", + "integrity": "sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", @@ -4235,6 +4263,60 @@ "dev": true, "optional": true }, + "node_modules/cache-manager": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.2.3.tgz", + "integrity": "sha512-9OErI8fksFkxAMJ8Mco0aiZSdphyd90HcKiOMJQncSlU1yq/9lHHxrT8PDayxrmr9IIIZPOAEfXuGSD7g29uog==", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "^9.1.2" + } + }, + "node_modules/cache-manager-redis-store": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cache-manager-redis-store/-/cache-manager-redis-store-2.0.0.tgz", + "integrity": "sha512-bWLWlUg6nCYHiJLCCYxY2MgvwvKnvlWwrbuynrzpjEIhfArD2GC9LtutIHFEPeyGVQN6C+WEw+P3r+BFBwhswg==", + "dependencies": { + "redis": "^3.0.2" + }, + "engines": { + "node": ">= 8.3" + } + }, + "node_modules/cache-manager-redis-store/node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cache-manager-redis-store/node_modules/redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/cache-manager/node_modules/lru-cache": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", + "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -8130,6 +8212,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -9802,6 +9889,30 @@ "@redis/time-series": "1.0.4" } }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", diff --git a/dictation_server/package.json b/dictation_server/package.json index 6da89b6..bea2e4e 100644 --- a/dictation_server/package.json +++ b/dictation_server/package.json @@ -45,6 +45,8 @@ "@types/jsonwebtoken": "^9.0.1", "@types/uuid": "^8.3.4", "axios": "^1.3.4", + "cache-manager": "^5.2.0", + "cache-manager-redis-store": "^2.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "connect-redis": "^6.1.3", @@ -66,6 +68,7 @@ "@nestjs/schematics": "^8.0.0", "@nestjs/swagger": "^6.3.0", "@nestjs/testing": "^9.3.12", + "@types/cache-manager-redis-store": "^2.0.1", "@types/cookie-parser": "^1.4.3", "@types/express": "^4.17.13", "@types/express-session": "^1.17.5", diff --git a/dictation_server/src/app.module.ts b/dictation_server/src/app.module.ts index e8b4375..9c4beb2 100644 --- a/dictation_server/src/app.module.ts +++ b/dictation_server/src/app.module.ts @@ -42,6 +42,7 @@ import { SortCriteriaRepositoryModule } from './repositories/sort_criteria/sort_ import { TemplateFilesRepositoryModule } from './repositories/template_files/template_files.repository.module'; import { WorktypesRepositoryModule } from './repositories/worktypes/worktypes.repository.module'; import { OptionItemsRepositoryModule } from './repositories/option_items/option_items.repository.module'; +import { RedisModule } from './common/redis/redis.module'; @Module({ imports: [ @@ -91,6 +92,7 @@ import { OptionItemsRepositoryModule } from './repositories/option_items/option_ }), inject: [ConfigService], }), + RedisModule, NotificationModule, NotificationhubModule, BlobstorageModule, diff --git a/dictation_server/src/common/redis/redis.module.ts b/dictation_server/src/common/redis/redis.module.ts new file mode 100644 index 0000000..1741179 --- /dev/null +++ b/dictation_server/src/common/redis/redis.module.ts @@ -0,0 +1,36 @@ +import { CacheModule, Module } from '@nestjs/common'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import * as redisStore from 'cache-manager-redis-store'; +import { RedisService } from './redis.service'; + +@Module({ + imports: [ + CacheModule.registerAsync({ + imports: [ConfigModule], + useFactory: async (configService: ConfigService) => { + if (process.env.STAGE === 'local') { + return { + store: redisStore, + host: configService.get('REDIS_HOST'), + port: configService.get('REDIS_PORT'), + password: configService.get('REDIS_PASSWORD'), + ttl: configService.get('REDIS_TTL'), + }; + } + return { + store: redisStore, + url: `rediss://${configService.get('REDIS_HOST')}:${configService.get( + 'REDIS_PORT', + )}}`, + password: configService.get('REDIS_PASSWORD'), + ttl: configService.get('REDIS_TTL'), + tls: {}, + }; + }, + inject: [ConfigService], + }), + ], + providers: [RedisService], + exports: [RedisService], +}) +export class RedisModule {} diff --git a/dictation_server/src/common/redis/redis.service.ts b/dictation_server/src/common/redis/redis.service.ts new file mode 100644 index 0000000..330a9bc --- /dev/null +++ b/dictation_server/src/common/redis/redis.service.ts @@ -0,0 +1,30 @@ +import { + CACHE_MANAGER, + Inject, + Injectable, + InternalServerErrorException, +} from '@nestjs/common'; +import { Cache } from 'cache-manager'; + +// TODO「タスク 1828: IDトークンを一度しか使えないようにする」で本実装する予定 +@Injectable() +export class RedisService { + constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {} + + async set(key: string, value: string): Promise { + try { + await this.cacheManager.set(key, value); + } catch (error) { + throw new InternalServerErrorException(); + } + } + + async get(key: string): Promise { + try { + const value = await this.cacheManager.get(key); + return value; + } catch (error) { + throw new InternalServerErrorException(); + } + } +} diff --git a/dictation_server/src/features/auth/auth.controller.ts b/dictation_server/src/features/auth/auth.controller.ts index b0b2f3e..377f98f 100644 --- a/dictation_server/src/features/auth/auth.controller.ts +++ b/dictation_server/src/features/auth/auth.controller.ts @@ -23,11 +23,16 @@ import { import { retrieveAuthorizationToken } from '../../common/http/helper'; import { makeContext } from '../../common/log'; import { v4 as uuidv4 } from 'uuid'; +import { RedisService } from '../../common/redis/redis.service'; @ApiTags('auth') @Controller('auth') export class AuthController { - constructor(private readonly authService: AuthService) {} + constructor( + // TODO「タスク 1828: IDトークンを一度しか使えないようにする」で使用する予定 + private readonly redisService: RedisService, + private readonly authService: AuthService, + ) {} @Post('token') @ApiResponse({ @@ -60,6 +65,8 @@ export class AuthController { HttpStatus.BAD_REQUEST, ); } + //TODO redisにidTokenを保存 + this.redisService.set(body.idToken, 'used'); const context = makeContext(uuidv4()); diff --git a/dictation_server/src/features/auth/auth.module.ts b/dictation_server/src/features/auth/auth.module.ts index e502c2f..2ccc725 100644 --- a/dictation_server/src/features/auth/auth.module.ts +++ b/dictation_server/src/features/auth/auth.module.ts @@ -4,9 +4,9 @@ import { AdB2cModule } from '../../gateways/adb2c/adb2c.module'; import { UsersRepositoryModule } from '../../repositories/users/users.repository.module'; import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; - +import { RedisModule } from '../../common/redis/redis.module'; @Module({ - imports: [ConfigModule, AdB2cModule, UsersRepositoryModule], + imports: [ConfigModule, AdB2cModule, UsersRepositoryModule, RedisModule], controllers: [AuthController], providers: [AuthService], }) diff --git a/docker-compose.yml b/docker-compose.yml index d5d246a..f17431d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,10 +26,11 @@ services: cache: image: redis:latest container_name: redis-cache + command: [ "redis-server", "--requirepass ${REDIS_PASSWORD}" ] ports: - - 8000:8000 + - 6379:6379 expose: - - 8000 + - 6379 networks: - network volumes: