feat(api): validate configuration

This commit is contained in:
Julian Tölle 2020-05-03 03:47:24 +02:00
parent ad98ce4e88
commit e78c6e312d
8 changed files with 109 additions and 12 deletions

View file

@ -16,9 +16,11 @@ services:
target: build-api
command: ["npm", "run", "start:dev"]
environment:
DB_HOST: db
DB_USERNAME: listory
DB_PASSWORD: listory
DB_HOST: db
DB_DATABASE: listory
APP_URL: "http://localhost:3000"
env_file: .env
volumes:
- ./src:/app/src

49
package-lock.json generated
View file

@ -484,6 +484,49 @@
}
}
},
"@hapi/address": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.0.1.tgz",
"integrity": "sha512-0oEP5UiyV4f3d6cBL8F3Z5S7iWSX39Knnl0lY8i+6gfmmIBj44JCBNtcMgwyS+5v7j3VYavNay0NFHDS+UGQcw==",
"requires": {
"@hapi/hoek": "^9.0.0"
}
},
"@hapi/formula": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz",
"integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A=="
},
"@hapi/hoek": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.0.4.tgz",
"integrity": "sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw=="
},
"@hapi/joi": {
"version": "17.1.1",
"resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.1.tgz",
"integrity": "sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg==",
"requires": {
"@hapi/address": "^4.0.1",
"@hapi/formula": "^2.0.0",
"@hapi/hoek": "^9.0.0",
"@hapi/pinpoint": "^2.0.0",
"@hapi/topo": "^5.0.0"
}
},
"@hapi/pinpoint": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz",
"integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw=="
},
"@hapi/topo": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz",
"integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==",
"requires": {
"@hapi/hoek": "^9.0.0"
}
},
"@istanbuljs/load-nyc-config": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz",
@ -1523,6 +1566,12 @@
"@types/node": "*"
}
},
"@types/hapi__joi": {
"version": "16.0.12",
"resolved": "https://registry.npmjs.org/@types/hapi__joi/-/hapi__joi-16.0.12.tgz",
"integrity": "sha512-xJYifuz59jXdWY5JMS15uvA3ycS3nQYOGqoIIE0+fwQ0qI3/4CxBc6RHsOTp6wk9M0NWEdpcTl02lOQOKMifbQ==",
"dev": true
},
"@types/istanbul-lib-coverage": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz",

View file

@ -20,6 +20,7 @@
"test:e2e": "jest --config ./apps/listory/test/jest-e2e.json"
},
"dependencies": {
"@hapi/joi": "^17.1.1",
"@nestjs/common": "^7.0.9",
"@nestjs/config": "^0.4.0",
"@nestjs/core": "^7.0.9",
@ -48,6 +49,7 @@
"@nestjs/schematics": "^7.0.0",
"@nestjs/testing": "^7.0.9",
"@types/express": "^4.17.6",
"@types/hapi__joi": "^16.0.12",
"@types/jest": "^25.2.1",
"@types/node": "^13.13.4",
"@types/passport-jwt": "^3.0.3",

View file

@ -1,5 +1,4 @@
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { ScheduleModule } from "@nestjs/schedule";
import { ServeStaticModule } from "@nestjs/serve-static";
import { join } from "path";
@ -10,12 +9,14 @@ import { LoggerModule } from "./logger/logger.module";
import { MusicLibraryModule } from "./music-library/music-library.module";
import { SourcesModule } from "./sources/sources.module";
import { UsersModule } from "./users/users.module";
import { ConfigModule } from "./config/config.module";
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
ScheduleModule.forRoot(),
LoggerModule,
ConfigModule,
DatabaseModule,
ScheduleModule.forRoot(),
ServeStaticModule.forRoot({
rootPath: join(__dirname, "..", "static"),
exclude: ["/api*"],
@ -25,7 +26,6 @@ import { UsersModule } from "./users/users.module";
SourcesModule,
MusicLibraryModule,
ListensModule,
LoggerModule,
],
})
export class AppModule {}

View file

@ -13,9 +13,9 @@ export class SpotifyStrategy extends PassportStrategy(Strategy) {
super({
clientID: config.get<string>("SPOTIFY_CLIENT_ID"),
clientSecret: config.get<string>("SPOTIFY_CLIENT_SECRET"),
callbackURL: `${
config.get<string>("BASE_DOMAIN") || "http://localhost:3000"
}/api/v1/auth/spotify/callback`,
callbackURL: `${config.get<string>(
"APP_URL"
)}/api/v1/auth/spotify/callback`,
scope: [
"user-read-private",
"user-read-email",

View file

@ -0,0 +1,40 @@
import * as Joi from "@hapi/joi";
import { Module } from "@nestjs/common";
import {
ConfigModule as NestConfigModule,
ConfigService,
} from "@nestjs/config";
@Module({
imports: [
NestConfigModule.forRoot({
isGlobal: true,
validationSchema: Joi.object({
// Application
NODE_ENV: Joi.string().valid("dev", "production").default("dev"),
PORT: Joi.number().default(3000),
APP_URL: Joi.string().default("http://localhost:3000"),
// JWT
JWT_SECRET: Joi.string().required(),
JWT_EXPIRATION_TIME: Joi.string().default("1d"),
// Spotify
SPOTIFY_CLIENT_ID: Joi.string().required(),
SPOTIFY_CLIENT_SECRET: Joi.string().required(),
SPOTIFY_FETCH_INTERVAL_MS: Joi.number().default(5 * 60 * 1000),
SPOTIFY_WEB_API_URL: Joi.string().default("https://api.spotify.com/"),
SPOTIFY_AUTH_API_URL: Joi.string().default(
"https://accounts.spotify.com/"
),
// DB
DB_HOST: Joi.string().required(),
DB_USERNAME: Joi.string().required(),
DB_PASSWORD: Joi.string().required(),
DB_DATABASE: Joi.string().required(),
}),
}),
],
})
export class ConfigModule {}

View file

@ -1,13 +1,15 @@
import { HttpModule, Module } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { SpotifyApiService } from "./spotify-api.service";
@Module({
imports: [
HttpModule.registerAsync({
useFactory: () => ({
useFactory: (config: ConfigService) => ({
timeout: 5000,
baseURL: "https://api.spotify.com/",
baseURL: config.get<string>("SPOTIFY_WEB_API_URL"),
}),
inject: [ConfigService],
}),
],
providers: [SpotifyApiService],

View file

@ -1,13 +1,15 @@
import { HttpModule, Module } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { SpotifyAuthService } from "./spotify-auth.service";
@Module({
imports: [
HttpModule.registerAsync({
useFactory: () => ({
useFactory: (config: ConfigService) => ({
timeout: 5000,
baseURL: "https://accounts.spotify.com/",
baseURL: config.get<string>("SPOTIFY_AUTH_API_URL"),
}),
inject: [ConfigService],
}),
],
providers: [SpotifyAuthService],