From 4823f7f10982ba9464ec8af696ac533a8bfd8c6d Mon Sep 17 00:00:00 2001 From: Chip Wasson Date: Mon, 20 Nov 2023 16:58:56 -0700 Subject: [PATCH] Store users in s3 --- package.json | 1 + src/app.module.ts | 2 ++ src/auth/auth.service.ts | 9 +++++--- src/users/users.module.ts | 5 +++-- src/users/users.service.ts | 45 +++++++++++++++++++++++++++++--------- yarn.lock | 28 +++++++++++++++++++++++- 6 files changed, 74 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index bd386ab..1f64dc2 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@nestjs/core": "^10.0.0", "@nestjs/jwt": "^10.1.1", "@nestjs/platform-express": "^10.0.0", + "@nestjs/schedule": "^4.0.0", "@nestjs/swagger": "^7.1.11", "@willsoto/nestjs-prometheus": "^6.0.0", "axios": "^1.5.0", diff --git a/src/app.module.ts b/src/app.module.ts index d04bf49..ecd283e 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -18,9 +18,11 @@ import { KvModule } from './kv/kv.module'; import { BullModule } from '@nestjs/bull'; import type { RedisClientOptions } from 'redis'; import { redisStore } from 'cache-manager-redis-store'; +import { ScheduleModule } from '@nestjs/schedule'; @Module({ imports: [ + ScheduleModule.forRoot(), ConfigModule.forRoot({ isGlobal: true, load: [configuration], diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 0631dfd..6d5cca7 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -13,7 +13,7 @@ export class AuthService { async signIn(username: string, pass: string): Promise { const user = await this.usersService.findOne(username); - if (!(await bcrypt.compare(pass, user?.password))) { + if (!user?.password || !(await bcrypt.compare(pass, user?.password))) { throw new UnauthorizedException(); } const payload = { sub: user.userId, username: user.username }; @@ -22,7 +22,10 @@ export class AuthService { }; } - async hash(pass: string, rounds: number = bcryptConstants.saltRounds): Promise { - return bcrypt.hash(pass, rounds) + async hash( + pass: string, + rounds: number = bcryptConstants.saltRounds, + ): Promise { + return bcrypt.hash(pass, rounds); } } diff --git a/src/users/users.module.ts b/src/users/users.module.ts index bd42599..46ccec5 100644 --- a/src/users/users.module.ts +++ b/src/users/users.module.ts @@ -1,8 +1,9 @@ import { Module } from '@nestjs/common'; import { UsersService } from './users.service'; +import { MinioService } from 'src/minio/minio.service'; @Module({ - providers: [UsersService], - exports: [UsersService] + providers: [UsersService, MinioService], + exports: [UsersService], }) export class UsersModule {} diff --git a/src/users/users.service.ts b/src/users/users.service.ts index c3783db..20b7446 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -1,18 +1,43 @@ -import { Injectable } from '@nestjs/common'; -require('dotenv').config() +import { Injectable, Logger } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { Cron } from '@nestjs/schedule'; +import { MinioService } from 'src/minio/minio.service'; +require('dotenv').config(); // This should be a real class/interface representing a user entity -export type User = any; +export type User = { + userId: number; + username: string; + password: string; +}; @Injectable() export class UsersService { - private readonly users = [ - { - userId: 1, - username: 'admin', - password: process.env.ADMIN_PASS, - }, - ]; + private users: User[] = []; + private readonly bucket: string; + private readonly logger: Logger = new Logger(UsersService.name); + + constructor( + private readonly minioService: MinioService, + private readonly configService: ConfigService, + ) { + this.bucket = configService.get('S3_BUCKET', 'api.us.dev'); + this.refreshUsers(); + } + + @Cron('* * * * *') + async refreshUsers(): Promise { + this.logger.verbose('Refreshing users'); + const buffer = await this.minioService.getBuffer(this.bucket, 'users.json'); + this.users = JSON.parse(buffer.toString()); + if (this.users === undefined) { + this.logger.error('Users undefined'); + } + if (this.users.length === 0) { + this.logger.error('Users length is 0'); + } + this.logger.verbose(`Refreshed with ${this.users.length} users`); + } async findOne(username: string): Promise { return this.users.find((user) => user.username === username); diff --git a/yarn.lock b/yarn.lock index 3bfb958..94ce436 100644 --- a/yarn.lock +++ b/yarn.lock @@ -840,6 +840,14 @@ multer "1.4.4-lts.1" tslib "2.6.2" +"@nestjs/schedule@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@nestjs/schedule/-/schedule-4.0.0.tgz#522fa0c79a2b44a66aab16a46bdf4c11ae73f3c3" + integrity sha512-zz4h54m/F/1qyQKvMJCRphmuwGqJltDAkFxUXCVqJBXEs5kbPt93Pza3heCQOcMH22MZNhGlc9DmDMLXVHmgVQ== + dependencies: + cron "3.1.3" + uuid "9.0.1" + "@nestjs/schematics@^10.0.0", "@nestjs/schematics@^10.0.1": version "10.0.2" resolved "https://registry.yarnpkg.com/@nestjs/schematics/-/schematics-10.0.2.tgz#d782ac1a6e9372d2f7ede1e2077c3a7484714923" @@ -1158,6 +1166,11 @@ dependencies: "@types/node" "*" +"@types/luxon@~3.3.0": + version "3.3.4" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.3.4.tgz#cda5c0709a0c4c01ba059c40e62d76610479049a" + integrity sha512-H9OXxv4EzJwE75aTPKpiGXJq+y4LFxjpsdgKwSmr503P5DkWc3AG7VAFYrFNVvqemT5DfgZJV9itYhqBHSGujA== + "@types/mime@*": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" @@ -2305,6 +2318,14 @@ cron-parser@^4.2.1: dependencies: luxon "^3.2.1" +cron@3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/cron/-/cron-3.1.3.tgz#4eac8f6691ce7e24c8e89b5317b8097d6f2d0053" + integrity sha512-KVxeKTKYj2eNzN4ElnT6nRSbjbfhyxR92O/Jdp6SH3pc05CDJws59jBrZWEMQlxevCiE6QUTrXy+Im3vC3oD3A== + dependencies: + "@types/luxon" "~3.3.0" + luxon "~3.4.0" + cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -4213,7 +4234,7 @@ lru-cache@^6.0.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a" integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== -luxon@^3.2.1: +luxon@^3.2.1, luxon@~3.4.0: version "3.4.4" resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.4.tgz#cf20dc27dc532ba41a169c43fdcc0063601577af" integrity sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA== @@ -5798,6 +5819,11 @@ uuid@9.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== +uuid@9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + uuid@^8.3.0: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"