add settings endpoint
This commit is contained in:
parent
57e13b84df
commit
b16d2f49c3
@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- `SIGNUP_DISABLED=true` to prevent users from signing up
|
||||
|
||||
### Changed
|
||||
### Fixed
|
||||
|
||||
|
||||
25
src/dto/setting/pager.setting.model.ts
Normal file
25
src/dto/setting/pager.setting.model.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
import { GraphQLInt } from 'graphql';
|
||||
import {SettingModel} from './setting.model'
|
||||
|
||||
@ObjectType('PagerSetting')
|
||||
export class PagerSettingModel {
|
||||
@Field(() => [SettingModel])
|
||||
entries: SettingModel[]
|
||||
|
||||
@Field(() => GraphQLInt)
|
||||
total: number
|
||||
|
||||
@Field(() => GraphQLInt)
|
||||
limit: number
|
||||
|
||||
@Field(() => GraphQLInt)
|
||||
start: number
|
||||
|
||||
constructor(entries: SettingModel[], total: number, limit: number, start: number) {
|
||||
this.entries = entries
|
||||
this.total = total
|
||||
this.limit = limit
|
||||
this.start = start
|
||||
}
|
||||
}
|
||||
24
src/dto/setting/setting.model.ts
Normal file
24
src/dto/setting/setting.model.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { Field, ID, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
@ObjectType('Setting')
|
||||
export class SettingModel {
|
||||
@Field(() => ID)
|
||||
readonly key: string
|
||||
|
||||
@Field()
|
||||
readonly value: string
|
||||
|
||||
@Field()
|
||||
readonly isTrue: boolean
|
||||
|
||||
@Field()
|
||||
readonly isFalse: boolean
|
||||
|
||||
constructor(key: string, value: string) {
|
||||
this.key = key
|
||||
this.value = value
|
||||
|
||||
this.isTrue = value.toLowerCase() === 'true' || value === '1'
|
||||
this.isFalse = !this.isTrue
|
||||
}
|
||||
}
|
||||
@ -4,12 +4,14 @@ import { PinoLogger } from 'nestjs-pino/dist';
|
||||
import { AuthJwtModel } from '../../dto/auth/auth.jwt.model';
|
||||
import { UserCreateInput } from '../../dto/user/user.create.input';
|
||||
import { AuthService } from '../../service/auth/auth.service';
|
||||
import {SettingService} from '../../service/setting.service'
|
||||
import { UserCreateService } from '../../service/user/user.create.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthRegisterResolver {
|
||||
constructor(
|
||||
private readonly createUser: UserCreateService,
|
||||
private readonly settingService: SettingService,
|
||||
private readonly auth: AuthService,
|
||||
private readonly logger: PinoLogger,
|
||||
) {
|
||||
@ -19,6 +21,10 @@ export class AuthRegisterResolver {
|
||||
async authRegister(
|
||||
@Args({ name: 'user' }) data: UserCreateInput,
|
||||
): Promise<AuthJwtModel> {
|
||||
if (await this.settingService.isTrue('SIGNUP_DISABLED')) {
|
||||
throw new Error('signup disabled')
|
||||
}
|
||||
|
||||
this.logger.info({
|
||||
email: data.email,
|
||||
username: data.username,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { authServices } from './auth';
|
||||
import { formResolvers } from './form';
|
||||
import { profileResolvers } from './profile';
|
||||
import {settingsResolvers} from './setting'
|
||||
import { StatusResolver } from './status.resolver';
|
||||
import { submissionResolvers } from './submission';
|
||||
import { userResolvers } from './user';
|
||||
@ -12,4 +13,5 @@ export const resolvers = [
|
||||
...profileResolvers,
|
||||
...formResolvers,
|
||||
...submissionResolvers,
|
||||
...settingsResolvers,
|
||||
]
|
||||
|
||||
7
src/resolver/setting/index.ts
Normal file
7
src/resolver/setting/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import {SettingMutation} from './setting.mutation'
|
||||
import {SettingResolver} from './setting.resolver'
|
||||
|
||||
export const settingsResolvers = [
|
||||
SettingResolver,
|
||||
SettingMutation,
|
||||
]
|
||||
8
src/resolver/setting/setting.mutation.ts
Normal file
8
src/resolver/setting/setting.mutation.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import {Roles} from '../../decorator/roles.decorator'
|
||||
|
||||
export class SettingMutation {
|
||||
@Roles('superuser')
|
||||
setSetting(key: string, value: string) {
|
||||
// TODO https://github.com/ohmyform/api/issues/3
|
||||
}
|
||||
}
|
||||
44
src/resolver/setting/setting.resolver.ts
Normal file
44
src/resolver/setting/setting.resolver.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import {ConfigService} from '@nestjs/config'
|
||||
import {Args, ID, Query} from '@nestjs/graphql'
|
||||
import {Roles} from '../../decorator/roles.decorator'
|
||||
import {User} from '../../decorator/user.decorator'
|
||||
import {PagerSettingModel} from '../../dto/setting/pager.setting.model'
|
||||
import {SettingModel} from '../../dto/setting/setting.model'
|
||||
import {UserModel} from '../../dto/user/user.model'
|
||||
import {UserDocument} from '../../schema/user.schema'
|
||||
import {SettingService} from '../../service/setting.service'
|
||||
|
||||
export class SettingResolver {
|
||||
private publicKeys: string[] = [
|
||||
'SIGNUP_DISABLED',
|
||||
]
|
||||
|
||||
constructor(
|
||||
private readonly settingService: SettingService,
|
||||
) {
|
||||
}
|
||||
|
||||
@Query(() => PagerSettingModel)
|
||||
@Roles('superuser')
|
||||
async getSettings(): Promise<PagerSettingModel> {
|
||||
// TODO https://github.com/ohmyform/api/issues/3
|
||||
return new PagerSettingModel(
|
||||
[],
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
@Query(() => SettingModel)
|
||||
async getSetting(
|
||||
@Args('key', {type: () => ID}) key: string,
|
||||
@User() user: UserDocument,
|
||||
): Promise<SettingModel> {
|
||||
if (!this.publicKeys.includes(key) && !user.roles.includes('superuser')) {
|
||||
throw new Error(`no access to key ${key}`)
|
||||
}
|
||||
|
||||
return await this.settingService.getByKey(key)
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@ import { formServices } from './form';
|
||||
import { InstallationMetricsService } from './installation.metrics.service';
|
||||
import { MailService } from './mail.service';
|
||||
import { profileServices } from './profile';
|
||||
import {SettingService} from './setting.service'
|
||||
import { submissionServices } from './submission';
|
||||
import { userServices } from './user';
|
||||
|
||||
@ -17,6 +18,7 @@ export const services = [
|
||||
...formServices,
|
||||
...authServices,
|
||||
...submissionServices,
|
||||
SettingService,
|
||||
MailService,
|
||||
InstallationMetricsService,
|
||||
{
|
||||
|
||||
28
src/service/setting.service.ts
Normal file
28
src/service/setting.service.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import {Injectable} from '@nestjs/common'
|
||||
import {ConfigService} from '@nestjs/config'
|
||||
import {SettingModel} from '../dto/setting/setting.model'
|
||||
|
||||
@Injectable()
|
||||
export class SettingService {
|
||||
constructor(
|
||||
private readonly configService: ConfigService,
|
||||
) {
|
||||
}
|
||||
|
||||
async getByKey(key: string): Promise<SettingModel> {
|
||||
switch (key) {
|
||||
case 'SIGNUP_DISABLED':
|
||||
return new SettingModel(key, this.configService.get(key))
|
||||
}
|
||||
|
||||
throw new Error(`no config stored for key ${key}`)
|
||||
}
|
||||
|
||||
async isTrue(key: string): Promise<boolean> {
|
||||
return (await this.getByKey(key)).isTrue
|
||||
}
|
||||
|
||||
async isFalse(key: string): Promise<boolean> {
|
||||
return (await this.getByKey(key)).isFalse
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user