mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
add settings as key value approach
This commit is contained in:
parent
161fae9ba2
commit
e963a34b36
@ -67,6 +67,9 @@ export class UpdateUserInfosArgs {
|
|||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
passwordNew?: string
|
passwordNew?: string
|
||||||
|
|
||||||
|
@Field({ nullable: true })
|
||||||
|
coinanimation?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ArgsType()
|
@ArgsType()
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { LoginViaVerificationCode } from '../models/LoginViaVerificationCode'
|
|||||||
import { SendPasswordResetEmailResponse } from '../models/SendPasswordResetEmailResponse'
|
import { SendPasswordResetEmailResponse } from '../models/SendPasswordResetEmailResponse'
|
||||||
import { UpdateUserInfosResponse } from '../models/UpdateUserInfosResponse'
|
import { UpdateUserInfosResponse } from '../models/UpdateUserInfosResponse'
|
||||||
import { User } from '../models/User'
|
import { User } from '../models/User'
|
||||||
|
import { User as dbUser } from '../../typeorm/entity/User'
|
||||||
import encode from '../../jwt/encode'
|
import encode from '../../jwt/encode'
|
||||||
import {
|
import {
|
||||||
ChangePasswordArgs,
|
ChangePasswordArgs,
|
||||||
@ -22,6 +23,10 @@ import {
|
|||||||
klicktippNewsletterStateMiddleware,
|
klicktippNewsletterStateMiddleware,
|
||||||
} from '../../middleware/klicktippMiddleware'
|
} from '../../middleware/klicktippMiddleware'
|
||||||
import { CheckEmailResponse } from '../models/CheckEmailResponse'
|
import { CheckEmailResponse } from '../models/CheckEmailResponse'
|
||||||
|
import { getCustomRepository } from 'typeorm'
|
||||||
|
import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository'
|
||||||
|
import { Setting } from '../../types'
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class UserResolver {
|
export class UserResolver {
|
||||||
@Query(() => User)
|
@Query(() => User)
|
||||||
@ -135,6 +140,7 @@ export class UserResolver {
|
|||||||
publisherId,
|
publisherId,
|
||||||
password,
|
password,
|
||||||
passwordNew,
|
passwordNew,
|
||||||
|
coinanimation,
|
||||||
}: UpdateUserInfosArgs,
|
}: UpdateUserInfosArgs,
|
||||||
@Ctx() context: any,
|
@Ctx() context: any,
|
||||||
): Promise<UpdateUserInfosResponse> {
|
): Promise<UpdateUserInfosResponse> {
|
||||||
@ -152,9 +158,47 @@ export class UserResolver {
|
|||||||
'User.password_old': password || undefined,
|
'User.password_old': password || undefined,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const result = await apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
|
let response: UpdateUserInfosResponse | undefined
|
||||||
if (!result.success) throw new Error(result.data)
|
if (
|
||||||
return new UpdateUserInfosResponse(result.data)
|
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)
|
@Query(() => CheckUsernameResponse)
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import schema from './graphql/schema'
|
|||||||
// TODO implement
|
// TODO implement
|
||||||
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
|
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
|
||||||
|
|
||||||
const DB_VERSION = '0001-init_db'
|
const DB_VERSION = '0002-add_settings'
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
// open mysql connection
|
// open mysql connection
|
||||||
|
|||||||
@ -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"
|
// import { Group } from "./Group"
|
||||||
@Entity('state_users')
|
@Entity('state_users')
|
||||||
@ -27,6 +28,9 @@ export class User extends BaseEntity {
|
|||||||
@Column()
|
@Column()
|
||||||
disabled: boolean
|
disabled: boolean
|
||||||
|
|
||||||
|
@OneToMany(() => UserSetting, (userSetting) => userSetting.user)
|
||||||
|
settings: UserSetting[]
|
||||||
|
|
||||||
static findByPubkeyHex(pubkeyHex: string): Promise<User> {
|
static findByPubkeyHex(pubkeyHex: string): Promise<User> {
|
||||||
return this.createQueryBuilder('user')
|
return this.createQueryBuilder('user')
|
||||||
.where('hex(user.pubkey) = :pubkeyHex', { pubkeyHex })
|
.where('hex(user.pubkey) = :pubkeyHex', { pubkeyHex })
|
||||||
|
|||||||
20
backend/src/typeorm/entity/UserSetting.ts
Normal file
20
backend/src/typeorm/entity/UserSetting.ts
Normal 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
|
||||||
|
}
|
||||||
26
backend/src/typeorm/repository/UserSettingRepository.ts
Normal file
26
backend/src/typeorm/repository/UserSettingRepository.ts
Normal 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
5
backend/src/types.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
enum Setting {
|
||||||
|
COIN_ANIMATION = 'coinanimation',
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Setting }
|
||||||
9
backend/src/util/validate.ts
Normal file
9
backend/src/util/validate.ts
Normal 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 }
|
||||||
1131
backend/yarn.lock
1131
backend/yarn.lock
File diff suppressed because it is too large
Load Diff
28
database/migrations/0002-add_settings.ts
Normal file
28
database/migrations/0002-add_settings.ts
Normal 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\`;`)
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user