From 4eb71d6cad599dfc173efc072b7158aba58365a6 Mon Sep 17 00:00:00 2001 From: Philip Molares Date: Sat, 11 Apr 2020 14:12:39 +0200 Subject: [PATCH] reworked user.ts - fixed imports - removed complicated ternary operators - simplified parseProfile - added enum ProviderEnum - added type Profile - added type PhotoProfile Signed-off-by: Philip Molares Signed-off-by: David Mehren --- lib/models/user.ts | 159 ++++++++++++++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 54 deletions(-) diff --git a/lib/models/user.ts b/lib/models/user.ts index dc691e495..69c2764cd 100644 --- a/lib/models/user.ts +++ b/lib/models/user.ts @@ -1,17 +1,45 @@ -import { Note } from './note'; -import { Table, BeforeCreate, BeforeUpdate, HasMany, Unique, IsUUID, IsEmail, Column, DataType, PrimaryKey, Model, Default } from 'sequelize-typescript'; -import scrypt from 'scrypt-kdf'; -import { generateAvatarURL } from '../letter-avatars'; -import logger from '../logger'; +import { Note } from './note' +import { Table, BeforeCreate, BeforeUpdate, HasMany, Unique, IsEmail, Column, DataType, PrimaryKey, Model, Default } from 'sequelize-typescript' +import scrypt from 'scrypt-kdf' +import { generateAvatarURL } from '../letter-avatars' +import logger from '../logger' +import { UUIDV4 } from 'sequelize' -var Sequelize = require('sequelize') // core +export enum ProviderEnum { + facebook = 'facebook', + twitter = 'twitter', + github = 'github', + gitlab = 'gitlab', + dropbox = 'dropbox', + google = 'google', + ldap = 'ldap', + saml = 'saml', +} + +// ToDo Fix this 'any' mess +export type Profile = { + id: string; + username: string; + displayName: string; + emails: any[]; + avatarUrl: string; + profileUrl: string; + provider: ProviderEnum; + photos: any[]; +} + +export type PhotoProfile = { + name: string; + photo: string; + biggerphoto: string; +} + @Table export class User extends Model { - @PrimaryKey - @Default(Sequelize.UUIDV4) + @Default(UUIDV4) @Column(DataType.UUID) id: string; @@ -23,7 +51,7 @@ export class User extends Model { profile: string; @Column(DataType.TEXT) - histroy: string; + history: string; @Column(DataType.TEXT) accessToken: string; @@ -41,52 +69,67 @@ export class User extends Model { @Column(DataType.TEXT) password: string; - verifyPassword(attempt: string) { - return scrypt.verify(Buffer.from(this.password, 'hex'), attempt); + verifyPassword (attempt: string): Promise { + return scrypt.verify(Buffer.from(this.password, 'hex'), attempt) } @HasMany(() => Note, { foreignKey: 'lastchangeuserId', constraints: false }) @HasMany(() => Note, { foreignKey: 'ownerId', constraints: false }) - - static parsePhotoByProfile(profile: any, bigger: boolean) { - let photo: string; + + static parsePhotoByProfile (profile: Profile, bigger: boolean): string { + let photo: string switch (profile.provider) { - case 'facebook': + case ProviderEnum.facebook: photo = 'https://graph.facebook.com/' + profile.id + '/picture' - if (bigger) photo += '?width=400' - else photo += '?width=96' + if (bigger) { + photo += '?width=400' + } else { + photo += '?width=96' + } break - case 'twitter': + case ProviderEnum.twitter: photo = 'https://twitter.com/' + profile.username + '/profile_image' - if (bigger) photo += '?size=original' - else photo += '?size=bigger' + if (bigger) { + photo += '?size=original' + } else { + photo += '?size=bigger' + } break - case 'github': + case ProviderEnum.github: photo = 'https://avatars.githubusercontent.com/u/' + profile.id - if (bigger) photo += '?s=400' - else photo += '?s=96' + if (bigger) { + photo += '?s=400' + } else { + photo += '?s=96' + } break - case 'gitlab': + case ProviderEnum.gitlab: photo = profile.avatarUrl if (photo) { - if (bigger) photo = photo.replace(/(\?s=)\d*$/i, '$1400') - else photo = photo.replace(/(\?s=)\d*$/i, '$196') + if (bigger) { + photo = photo.replace(/(\?s=)\d*$/i, '$1400') + } else { + photo = photo.replace(/(\?s=)\d*$/i, '$196') + } } else { photo = generateAvatarURL(profile.username) } break - case 'dropbox': + case ProviderEnum.dropbox: photo = generateAvatarURL('', profile.emails[0].value, bigger) break - case 'google': + case ProviderEnum.google: photo = profile.photos[0].value - if (bigger) photo = photo.replace(/(\?sz=)\d*$/i, '$1400') - else photo = photo.replace(/(\?sz=)\d*$/i, '$196') + if (bigger) { + photo = photo.replace(/(\?sz=)\d*$/i, '$1400') + } else { + photo = photo.replace(/(\?sz=)\d*$/i, '$196') + } break - case 'ldap': + case ProviderEnum.ldap: photo = generateAvatarURL(profile.username, profile.emails[0], bigger) break - case 'saml': + case ProviderEnum.saml: photo = generateAvatarURL(profile.username, profile.emails[0], bigger) break default: @@ -95,7 +138,8 @@ export class User extends Model { } return photo } - static parseProfileByEmail(email: string) { + + static parseProfileByEmail (email: string): PhotoProfile { return { name: email.substring(0, email.lastIndexOf('@')), photo: generateAvatarURL('', email, false), @@ -105,41 +149,48 @@ export class User extends Model { @BeforeUpdate @BeforeCreate - static async updatePasswordHashHook(user: User) { + static async updatePasswordHashHook (user: User): Promise { // suggested way to hash passwords to be able to do this asynchronously: // @see https://github.com/sequelize/sequelize/issues/1821#issuecomment-44265819 if (!user.changed('password')) { - return Promise.resolve(); + return Promise.resolve() } - return scrypt.kdf(user.getDataValue('password'), { logN: 15, r: 8, p: 1 }).then(keyBuf => { - user.setDataValue('password', keyBuf.toString('hex')); - }) + return scrypt + .kdf(user.getDataValue('password'), { logN: 15, r: 8, p: 1 }) + .then(keyBuf => { + user.setDataValue('password', keyBuf.toString('hex')) + }) } - static getProfile(user: User) { + static getProfile (user: User): PhotoProfile | null { if (!user) { return null } - return user.profile ? user.parseProfile(user.profile) : (user.email ? User.parseProfileByEmail(user.email) : null) - } - parseProfile(profile: any) { - try { - profile = JSON.parse(profile) - } catch (err) { - logger.error(err) - profile = null - } - if (profile) { - profile = { - name: profile.displayName || profile.username, - photo: User.parsePhotoByProfile(profile, false), - biggerphoto: User.parsePhotoByProfile(profile, true) + if (user.profile) { + return user.parseProfile(user.profile) + } else { + if (user.email) { + return User.parseProfileByEmail(user.email) + } else { + return null } } - return profile } + parseProfile (profile: string): PhotoProfile | null { + try { + const parsedProfile: Profile = JSON.parse(profile) + return { + name: parsedProfile.displayName || parsedProfile.username, + photo: User.parsePhotoByProfile(parsedProfile, false), + biggerphoto: User.parsePhotoByProfile(parsedProfile, true) + } + } catch (err) { + logger.error(err) + return null + } + } }