diff --git a/latest version/api/api_auth.py b/latest version/api/api_auth.py index 2325943..f71d7cf 100644 --- a/latest version/api/api_auth.py +++ b/latest version/api/api_auth.py @@ -70,11 +70,11 @@ def request_json_handle(request, required_keys=[], optional_keys=[]): json_data = loads( b64decode(request.args['query']).decode()) else: - return view(data, *args, **kwargs) + json_data = {} for key in required_keys: if key not in json_data: - return error_return(PostError('Missing parameter: ' + key, api_error_code=-100)) + return error_return(PostError(f'Missing parameter: {key}', api_error_code=-100)) data[key] = json_data[key] for key in optional_keys: diff --git a/latest version/api/api_code.py b/latest version/api/api_code.py index 50e76ea..dcb98ac 100644 --- a/latest version/api/api_code.py +++ b/latest version/api/api_code.py @@ -6,21 +6,23 @@ default_error = ArcError('Unknown Error') CODE_MSG = { 0: '', - -1: 'See status code', + -1: 'See status code', # 基础错误 -2: 'No data', -3: 'No data or user', -4: 'No user_id', - -100: 'Wrong post data', + -5: 'No user_id or user', + -100: 'Wrong post data', # 1xx数据错误 -101: 'Wrong data type', -102: 'Wrong query parameter', -103: 'Wrong sort parameter', -104: 'Wrong sort order parameter', - -200: 'No permission', + -200: 'No permission', # 2xx用户相关错误 -201: 'Wrong username or password', -202: 'User is banned', - -203: 'Username exists', - -204: 'Email address exists', - -205: 'Too many login attempts', + -203: 'Too many login attempts', + -210: 'Username exists', + -211: 'Email address exists', + -212: 'User code exists', -999: 'Unknown error' } diff --git a/latest version/api/users.py b/latest version/api/users.py index 7a0a4e0..0fbc41f 100644 --- a/latest version/api/users.py +++ b/latest version/api/users.py @@ -1,7 +1,7 @@ from core.error import InputError, NoAccess, NoData from core.score import Potential, UserScoreList from core.sql import Connect, Query, Sql -from core.user import UserInfo, UserRegister +from core.user import UserChanger, UserInfo, UserRegister from core.api_user import APIUser from flask import Blueprint, request @@ -76,6 +76,38 @@ def users_user_get(user, user_id): return success_return(u.to_dict()) +@bp.route('/', methods=['PUT']) +@role_required(request, ['change']) +@request_json_handle(request, optional_keys=['name', 'password', 'user_code', 'ticket', 'email']) +@api_try +def users_user_put(data, user, user_id): + '''修改一个用户''' + with Connect() as c: + u = UserChanger(c, user_id) + r = {} + r['user_id'] = user_id + if 'name' in data: + u.set_name(data['name']) + r['name'] = u.name + if 'password' in data: + u.set_password(data['password']) + r['password'] = u.hash_pwd + if 'email' in data: + u.set_email(data['email']) + r['email'] = u.email + if 'user_code' in data: + u.set_user_code(data['user_code']) + r['user_code'] = u.user_code + if 'ticket' in data: + if not isinstance(data['ticket'], int): + raise InputError('Ticket must be int') + u.ticket = data['ticket'] + r['ticket'] = u.ticket + if r: + u.update_columns(d=r) + return success_return(r) + + @bp.route('//b30', methods=['GET']) @role_required(request, ['select', 'select_me']) @api_try diff --git a/latest version/core/sql.py b/latest version/core/sql.py index 6a05535..d050e68 100644 --- a/latest version/core/sql.py +++ b/latest version/core/sql.py @@ -215,6 +215,36 @@ class Sql: 'replace', 'R', 'r', 'REPLACE'] else 'ignore' return ('insert into ' if insert_type is None else 'insert or ' + insert_type + ' into ') + table_name + ('(' + ','.join(key) + ')' if key else '') + ' values(' + ','.join(['?'] * (len(key) if value_len is None else value_len)) + ')' + @staticmethod + def get_update_sql(table_name: str, d: dict = {}, query: 'Query' = None) -> str: + if not d: + return None + sql_list = [] + sql = f"update {table_name} set {','.join([f'{k}=?' for k in d.keys()])}" + sql_list.extend(d.values()) + + if query is None: + return sql, sql_list + + where_key = [] + for k, v in query.query.items(): + if isinstance(v, list): + where_key.append(f"{k} in ({','.join(['?'] * len(v))})") + sql_list.extend(v) + else: + where_key.append(f'{k}=?') + sql_list.append(v) + + for k, v in query.fuzzy_query.items(): + where_key.append(f'{k} like ?') + sql_list.append(f'%{v}%') + + if where_key: + sql += ' where ' + sql += ' and '.join(where_key) + + return sql, sql_list + @staticmethod def get_delete_sql(table_name: str, query: 'Query' = None): '''拼接删除语句,query中只有query和fuzzy_query会被处理''' @@ -267,6 +297,13 @@ class Sql: self.c.executemany(self.get_insert_sql( table_name, key, len(value_list[0]), insert_type), value_list) + def update(self, table_name: str, d: dict, query: 'Query' = None) -> None: + '''单表内行update单句sql语句''' + if not d: + return + sql, sql_list = self.get_update_sql(table_name, d, query) + self.c.execute(sql, sql_list) + def delete(self, table_name: str, query: 'Query' = None) -> None: '''删除,query中只有query和fuzzy_query会被处理''' sql, sql_list = self.get_delete_sql(table_name, query) diff --git a/latest version/core/user.py b/latest version/core/user.py index 5269495..4b6ffd9 100644 --- a/latest version/core/user.py +++ b/latest version/core/user.py @@ -11,7 +11,7 @@ from .error import (ArcError, DataExist, FriendError, InputError, NoAccess, from .item import UserItemList from .limiter import ArcLimiter from .score import Score -from .sql import Connect +from .sql import Query, Sql from .world import Map, UserMap, UserStamina @@ -32,17 +32,17 @@ def code_get_id(c, user_code: str) -> int: class User: def __init__(self) -> None: - self.name = None - self.email = None - self.password = None - self.user_id = None - self.user_code = None + self.name: str = None + self.email: str = None + self.password: str = None + self.user_id: int = None + self.user_code: str = None self.join_date = None self.rating_ptt: int = None # 100 times - self.ticket = None - self.world_rank_score = None + self.ticket: int = None + self.world_rank_score: int = None self.ban_flag = None @property @@ -63,7 +63,7 @@ class UserRegister(User): if self.c.fetchone() == (0,): self.name = name else: - raise DataExist('Username exists.', 101, -203) + raise DataExist('Username exists.', 101, -210) else: raise InputError('Username is invalid.') @@ -82,10 +82,22 @@ class UserRegister(User): if self.c.fetchone() == (0,): self.email = email else: - raise DataExist('Email address exists.', 102, -204) + raise DataExist('Email address exists.', 102, -211) else: raise InputError('Email address is invalid.') + def set_user_code(self, user_code: str) -> None: + '''设置用户的user_code''' + if len(user_code) == 9 and user_code.isdigit(): + self.c.execute( + '''select exists(select * from user where user_code = ?)''', (user_code, )) + if self.c.fetchone() == (0,): + self.user_code = user_code + else: + raise DataExist('User code exists.', 103, -212) + else: + raise InputError('User code is invalid.') + def _build_user_code(self): # 生成9位的user_code,用的自然是随机 from random import randint @@ -225,7 +237,7 @@ class UserLogin(User): self.set_ip(ip) if not self.limiter.hit(name): - raise RateLimit('Too many login attempts.', 123) + raise RateLimit('Too many login attempts.', 123, -203) self.c.execute('''select user_id, password, ban_flag from user where name = :name''', { 'name': self.name}) @@ -283,7 +295,7 @@ class UserAuth(User): class UserInfo(User): def __init__(self, c, user_id=None) -> None: - super().__init__() + User.__init__(self) self.c = c self.user_id = user_id self.character = None @@ -733,3 +745,21 @@ class UserOnline(UserInfo): self.favorite_character = UserCharacter(self.c, character_id, self) self.c.execute('''update user set favorite_character = :a where user_id = :b''', {'a': self.favorite_character.character_id, 'b': self.user_id}) + + +class UserChanger(UserInfo, UserRegister): + + def __init__(self, c, user_id=None) -> None: + super().__init__(c, user_id) + + def update_columns(self, columns: list = None, d: dict = None) -> None: + if columns is not None: + d = {} + for column in columns: + if column == 'password': + d[column] = self.hash_pwd + else: + d[column] = self.__dict__[column] + + Sql(self.c).update('user', d, Query().from_args( + {'user_id': self.user_id}))