import { HashContainer } from 'hash' ; import { sql } from 'db' ; import { SetupSetParams } from 'utilitites' ; export const USER_MAX_LEVEL = 99 ; export type SetUserBody = { password ? : string ; password_hash ? : string ; gm : boolean ; points : number ; cash : number ; mpoints : number ; level : number ; curExp : number ; maxExp : number ; vipLevel : number ; vipXp : number ; rank : number ; rankFrame : number ; playedMatches : number ; wins : number ; secondsPlayed : number ; kills : number ; deaths : number ; assists : number ; headshots : number ; accuracy : number ; avatar : number ; unlockedAvatars : number [ ] ; netCafeName : string ; clanName : string ; clanMark : number ; worldRank : number ; titleId : number ; unlockedTitles : number [ ] ; signature : string ; bestGamemode : number ; bestMap : number ; unlockedAchievements : number [ ] ; skillHumanCurXp : number ; skillHumanMaxXp : number ; skillHumanPoints : number ; skillZombieCurXp : number ; skillZombieMaxXp : number ; skillZombiePoints : number ; } ; /**
 * represents an user and its data
 */ export class User { param colOffset param colLength returns public static async getAll ( colOffset , colLength ) { return await sql < User [ ] > `SELECT * FROM users LIMIT ${ colLength } OFFSET ${ colOffset };` ; } param userId param sanitize returns public static async getById ( userId , sanitize = true ) { const resRows = await sql < User > `SELECT * FROM users WHERE id = ${ userId };` ; if ( resRows . count === 0 ) { return null ; } else if ( resRows . count === 1 ) { return sanitize === true ? this . SanitizeForPublic ( resRows [ 0 ] ) : resRows [ 0 ] ; } else { throw new Error ( 'getUserById: got more than one row for an user' ) ; } } param userName param sanitize returns public static async getByName ( userName , sanitize = true ) { const resRows = await sql < User > `SELECT * FROM users WHERE username = ${ userName };` ; if ( resRows . count === 0 ) { return null ; } else if ( resRows . count === 1 ) { return sanitize === true ? this . SanitizeForPublic ( resRows [ 0 ] ) : resRows [ 0 ] ; } else { throw new Error ( 'getUserByName: got more than one row for an user' ) ; } } param userName param playerName returns public static async isTaken ( userName , playerName ) { const resRows = await sql < User > `
            SELECT * FROM users
            WHERE username = ${ userName } OR playername = ${ playerName };
        ` ; return resRows . count !== 0 ; } param userId param updatedUser returns public static async set ( userId , updatedUser ) { if ( ( await User . getById ( userId , false ) ) == null ) { return false ; } if ( updatedUser . password != null ) { const newPwHash = await HashContainer . create ( updatedUser . password ) ; updatedUser . password_hash = newPwHash . build ( ) ; delete updatedUser . password ; } await sql `
            UPDATE users
            SET ${ sql ( updatedUser , ... SetupSetParams ( updatedUser ) ) }
            WHERE id = ${ userId };
        ` ; return true ; } param userName param playerName param password param securityQuestion param securityAnswer returns public static async create ( userName , playerName , password , securityQuestion , securityAnswer ) { const [ passwordHash , secAnswerHash ] = await Promise . all ( [ HashContainer . create ( password ) , HashContainer . create ( securityAnswer ) ] ) ; password = null ; securityAnswer = null ; const res = await sql < User > `
            INSERT INTO users (username, playername, password_hash, security_question_index, security_answer_hash)
            VALUES (${ userName }, ${ playerName }, ${ passwordHash . build ( ) }, ${ securityQuestion }, ${ secAnswerHash . build ( ) })
            RETURNING *;
        ` ; if ( res . count !== 1 ) { throw new Error ( 'INSERT query did not return a single row' ) ; } return this . SanitizeForPublic ( res [ 0 ] ) ; } param userId returns public static async removeById ( userId ) { if ( ( await User . getById ( userId , false ) ) == null ) { return false ; } await sql `
            DELETE FROM users
            WHERE id = ${ userId };
        ` ; return true ; } param userName param password return public static async validateCredentials ( userName , password ) { const user = await User . getByName ( userName , false ) ; if ( user == null ) { return null ; } const targetHash = HashContainer . from ( user . password_hash ) ; const inputHash = await targetHash . cloneSettings ( password ) ; if ( targetHash . compare ( inputHash ) === false ) { return null ; } return user . id ; } param userName param password return public static async validateSecurityAnswer ( userName , securityAnswer ) { const user = await User . getByName ( userName , false ) ; if ( user == null ) { return null ; } const targetHash = HashContainer . from ( user . security_answer_hash ) ; const inputHash = await targetHash . cloneSettings ( securityAnswer ) ; if ( targetHash . compare ( inputHash ) === false ) { return null ; } return user . id ; } private static SanitizeForPublic ( user ) { delete user . password_hash ; delete user . security_answer_hash ; return user ; } public id : number ; public username : string ; public playername : string ; public password_hash : string ; public security_question_index : number ; public security_answer_hash : string ; public gm : boolean ; public points : number ; public cash : number ; public mpoints : number ; public level : number ; public cur_xp : BigInt ; public max_xp : BigInt ; public vip_level : number ; public vip_xp : number ; public rank : number ; public rank_frame : number ; public played_matches : number ; public wins : number ; public seconds_played : number ; public kills : number ; public deaths : number ; public assists : number ; public headshots : number ; public accuracy : number ; public avatar : number ; public unlocked_avatars : number [ ] ; public title : number ; public unlocked_titles : number [ ] ; public signature : string ; public unlocked_achievements : number [ ] ; public campaign_flags : number ; public netcafe_name : string ; public clan_name : string ; public clan_mark : number ; public world_rank : number ; public best_gamemode : number ; public best_map : number ; public skill_human_curxp : BigInt ; public skill_human_maxxp : BigInt ; public skill_human_points : BigInt ; public skill_zombie_curxp : BigInt ; public skill_zombie_maxxp : BigInt ; public skill_zombie_points : BigInt ; }