团队冲刺第四天:
1.继续完成登录注册后端代码:
1 import * as TypeORM from "typeorm"; 2 import Model from "./common"; 3 4 declare var syzoj: any; 5 6 import JudgeState from "./judge_state"; 7 import UserPrivilege from "./user_privilege"; 8 import Article from "./article"; 9 10 @TypeORM.Entity() 11 export default class User extends Model { 12 static cache = true; 13 14 15 @TypeORM.Column({ nullable: true, type: "boolean" })@TypeORM.PrimaryGeneratedColumn() 16 id: number; 17 18 @TypeORM.Index({ unique: true }) 19 @TypeORM.Column({ nullable: true, type: "varchar", length: 80 }) 20 username: string; 21 22 @TypeORM.Column({ nullable: true, type: "varchar", length: 120 }) 23 email: string; 24 25 @TypeORM.Column({ nullable: true, type: "varchar", length: 120 }) 26 password: string; 27 28 @TypeORM.Column({ nullable: true, type: "varchar", length: 80 }) 29 nickname: string; 30 31 @TypeORM.Column({ nullable: true, type: "text" }) 32 nameplate: string; 33 34 @TypeORM.Column({ nullable: true, type: "text" }) 35 information: string; 36 37 @TypeORM.Index() 38 @TypeORM.Column({ nullable: true, type: "integer" }) 39 ac_num: number; 40 41 @TypeORM.Index() 42 @TypeORM.Column({ nullable: true, type: "integer" }) 43 submit_num: number; 44 45 @TypeORM.Column({ nullable: true, type: "boolean" }) 46 is_admin: boolean; 47 48 @TypeORM.Index() 49 is_show: boolean; 50 51 @TypeORM.Column({ nullable: true, type: "boolean", default: true }) 52 public_email: boolean; 53 54 @TypeORM.Column({ nullable: true, type: "boolean", default: true }) 55 prefer_formatted_code: boolean; 56 57 @TypeORM.Column({ nullable: true, type: "integer" }) 58 sex: number; 59 60 @TypeORM.Column({ nullable: true, type: "integer" }) 61 rating: number; 62 63 @TypeORM.Column({ nullable: true, type: "integer" }) 64 register_time: number; 65 66 static async fromEmail(email): Promise<User> { 67 return User.findOne({ 68 where: { 69 email: email 70 } 71 }); 72 } 73 74 static async fromName(name): Promise<User> { 75 return User.findOne({ 76 where: { 77 username: name 78 } 79 }); 80 } 81 82 async isAllowedEditBy(user) { 83 if (!user) return false; 84 if (await user.hasPrivilege('manage_user')) return true; 85 return user && (user.is_admin || this.id === user.id); 86 } 87 88 getQueryBuilderForACProblems() { 89 return JudgeState.createQueryBuilder() 90 .select(`DISTINCT(problem_id)`) 91 .where('user_id = :user_id', { user_id: this.id }) 92 .andWhere('status = :status', { status: 'Accepted' }) 93 .andWhere('type != 1') 94 .orderBy({ problem_id: 'ASC' }) 95 } 96 97 async refreshSubmitInfo() { 98 await syzoj.utils.lock(['User::refreshSubmitInfo', this.id], async () => { 99 this.ac_num = await JudgeState.countQuery(this.getQueryBuilderForACProblems()); 100 this.submit_num = await JudgeState.count({ 101 user_id: this.id, 102 type: TypeORM.Not(1) // Not a contest submission 103 }); 104 105 await this.save(); 106 }); 107 } 108 109 async getACProblems() { 110 let queryResult = await this.getQueryBuilderForACProblems().getRawMany(); 111 112 return queryResult.map(record => record['problem_id']) 113 } 114 115 async getArticles() { 116 return await Article.find({ 117 where: { 118 user_id: this.id 119 } 120 }); 121 } 122 123 async getStatistics() { 124 let statuses = { 125 "Accepted": ["Accepted"], 126 "Wrong Answer": ["Wrong Answer", "File Error", "Output Limit Exceeded"], 127 "Runtime Error": ["Runtime Error"], 128 "Time Limit Exceeded": ["Time Limit Exceeded"], 129 "Memory Limit Exceeded": ["Memory Limit Exceeded"], 130 "Compile Error": ["Compile Error"] 131 }; 132 133 let res = {}; 134 for (let status in statuses) { 135 res[status] = 0; 136 for (let s of statuses[status]) { 137 res[status] += await JudgeState.count({ 138 user_id: this.id, 139 type: 0, 140 status: s 141 }); 142 } 143 } 144 145 return res; 146 } 147 148 async renderInformation() { 149 this.information = await syzoj.utils.markdown(this.information); 150 } 151 152 async getPrivileges() { 153 let privileges = await UserPrivilege.find({ 154 where: { 155 user_id: this.id 156 } 157 }); 158 159 return privileges.map(x => x.privilege); 160 } 161 162 async setPrivileges(newPrivileges) { 163 let oldPrivileges = await this.getPrivileges(); 164 165 let delPrivileges = oldPrivileges.filter(x => !newPrivileges.includes(x)); 166 let addPrivileges = newPrivileges.filter(x => !oldPrivileges.includes(x)); 167 168 for (let privilege of delPrivileges) { 169 let obj = await UserPrivilege.findOne({ where: { 170 user_id: this.id, 171 privilege: privilege 172 } }); 173 174 await obj.destroy(); 175 } 176 177 for (let privilege of addPrivileges) { 178 let obj = await UserPrivilege.create({ 179 user_id: this.id, 180 privilege: privilege 181 }); 182 183 await obj.save(); 184 } 185 } 186 187 async hasPrivilege(privilege) { 188 if (this.is_admin) return true; 189 190 let x = await UserPrivilege.findOne({ where: { user_id: this.id, privilege: privilege } }); 191 return !!x; 192 } 193 194 async getLastSubmitLanguage() { 195 let a = await JudgeState.findOne({ 196 where: { 197 user_id: this.id 198 }, 199 order: { 200 submit_time: 'DESC' 201 } 202 }); 203 if (a) return a.language; 204 205 return null; 206 } 207 }登录注册后端代码
2.管理员用户
1 import * as TypeORM from "typeorm"; 2 import Model from "./common"; 3 4 @TypeORM.Entity() 5 export default class UserPrivilege extends Model { 6 @TypeORM.Index() 7 @TypeORM.PrimaryColumn({ type: "integer" }) 8 user_id: number; 9 10 @TypeORM.Index() 11 @TypeORM.PrimaryColumn({ type: "varchar", length: 80 }) 12 privilege: string; 13 }管理员用户
3.测试截图