add settings as key value approach

This commit is contained in:
Einhornimmond 2021-10-01 18:42:48 +02:00
parent 161fae9ba2
commit e963a34b36
10 changed files with 691 additions and 589 deletions

View File

@ -67,6 +67,9 @@ export class UpdateUserInfosArgs {
@Field({ nullable: true })
passwordNew?: string
@Field({ nullable: true })
coinanimation?: boolean
}
@ArgsType()

View File

@ -8,6 +8,7 @@ import { LoginViaVerificationCode } from '../models/LoginViaVerificationCode'
import { SendPasswordResetEmailResponse } from '../models/SendPasswordResetEmailResponse'
import { UpdateUserInfosResponse } from '../models/UpdateUserInfosResponse'
import { User } from '../models/User'
import { User as dbUser } from '../../typeorm/entity/User'
import encode from '../../jwt/encode'
import {
ChangePasswordArgs,
@ -22,6 +23,10 @@ import {
klicktippNewsletterStateMiddleware,
} from '../../middleware/klicktippMiddleware'
import { CheckEmailResponse } from '../models/CheckEmailResponse'
import { getCustomRepository } from 'typeorm'
import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository'
import { Setting } from '../../types'
@Resolver()
export class UserResolver {
@Query(() => User)
@ -135,6 +140,7 @@ export class UserResolver {
publisherId,
password,
passwordNew,
coinanimation,
}: UpdateUserInfosArgs,
@Ctx() context: any,
): Promise<UpdateUserInfosResponse> {
@ -152,9 +158,47 @@ export class UserResolver {
'User.password_old': password || undefined,
},
}
const result = await apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
if (!result.success) throw new Error(result.data)
return new UpdateUserInfosResponse(result.data)
let response: UpdateUserInfosResponse | undefined
if (
firstName ||
lastName ||
description ||
username ||
language ||
publisherId ||
passwordNew ||
password
) {
const result = await apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
if (!result.success) throw new Error(result.data)
response = new UpdateUserInfosResponse(result.data)
}
if (coinanimation) {
// get public key for current logged in user
const result = await apiGet(CONFIG.LOGIN_API_URL + 'login?session_id=' + context.sessionId)
if (!result.success) throw new Error(result.data)
// load user and balance
const userEntity = await dbUser.findByPubkeyHex(result.data.user.public_hex)
const userSettingRepository = getCustomRepository(UserSettingRepository)
userSettingRepository.setOrUpdate(
userEntity.id,
Setting.COIN_ANIMATION,
coinanimation.toString(),
)
if (!response) {
response = new UpdateUserInfosResponse({ valid_values: 1 })
} else {
response.validValues++
}
}
if (!response) {
throw new Error('no valid response')
}
return response
}
@Query(() => CheckUsernameResponse)

View File

@ -22,7 +22,7 @@ import schema from './graphql/schema'
// TODO implement
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
const DB_VERSION = '0001-init_db'
const DB_VERSION = '0002-add_settings'
async function main() {
// open mysql connection

View File

@ -1,4 +1,5 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
import { UserSetting } from './UserSetting'
// import { Group } from "./Group"
@Entity('state_users')
@ -27,6 +28,9 @@ export class User extends BaseEntity {
@Column()
disabled: boolean
@OneToMany(() => UserSetting, (userSetting) => userSetting.user)
settings: UserSetting[]
static findByPubkeyHex(pubkeyHex: string): Promise<User> {
return this.createQueryBuilder('user')
.where('hex(user.pubkey) = :pubkeyHex', { pubkeyHex })

View File

@ -0,0 +1,20 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'
import { User } from './User'
@Entity()
export class UserSetting extends BaseEntity {
@PrimaryGeneratedColumn()
id: number
@Column()
userId: number
@ManyToOne(() => User, (user) => user.settings)
user: User
@Column()
key: string
@Column()
value: string
}

View File

@ -0,0 +1,26 @@
import { EntityRepository, Repository } from 'typeorm'
import { UserSetting } from '../entity/UserSetting'
import { Setting } from '../../types'
import { isStringBoolean } from '../../util/validate'
@EntityRepository()
export class UserSettingRepository extends Repository<UserSetting> {
async setOrUpdate(userId: number, key: Setting, value: string): Promise<UserSetting> {
switch (key) {
case Setting.COIN_ANIMATION:
if (!isStringBoolean(value)) {
throw new Error("coinanimation value isn't boolean")
}
break
}
let entity = await this.findOne({ userId: userId, key: key })
if (!entity) {
entity = new UserSetting()
entity.userId = userId
entity.key = key
}
entity.value = value
return this.save(entity)
}
}

5
backend/src/types.ts Normal file
View File

@ -0,0 +1,5 @@
enum Setting {
COIN_ANIMATION = 'coinanimation',
}
export { Setting }

View File

@ -0,0 +1,9 @@
function isStringBoolean(value: string): boolean {
const lowerValue = value.toLowerCase()
if (lowerValue === 'true' || lowerValue === 'false') {
return true
}
return false
}
export { isStringBoolean }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
/* FIRST MIGRATION
*
* This migration is special since it takes into account that
* the database can be setup already but also may not be.
* Therefore you will find all `CREATE TABLE` statements with
* a `IF NOT EXISTS`, all `INSERT` with an `IGNORE` and in the
* downgrade function all `DROP TABLE` with a `IF EXISTS`.
* This ensures compatibility for existing or non-existing
* databases.
*/
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
await queryFn(`
CREATE TABLE IF NOT EXISTS \`userSetting\` (
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
\`userId\` int(11) NOT NULL,
\`key\` varchar(255) NOT NULL,
\`value\` varchar(255) NOT NULL,
PRIMARY KEY (\`id\`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`)
}
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
// write downgrade logic as parameter of queryFn
await queryFn(`DROP TABLE IF EXISTS \`userSettings\`;`)
}