Add a register api

- Add a register api
- Change requirements, which flask version should be over 2.0
This commit is contained in:
Lost-MSth
2022-04-10 21:02:46 +08:00
parent 35c34f25d5
commit e8c15f5069
8 changed files with 294 additions and 32 deletions

View File

@@ -1,19 +1,34 @@
from flask import jsonify
def code_get_msg(code):
# api接口code获取msg返回字符串
msg = {
'0': '',
'-1': 'See status code',
'-2': 'No data',
'-3': 'No data or user',
'-4': 'No user_id',
'-100': 'Wrong post data',
'-101': 'Wrong data type',
'-102': 'Wrong query parameter',
'-103': 'Wrong sort parameter',
'-104': 'Wrong sort order parameter',
'-201': 'Wrong username or password',
'-202': 'User is banned',
'-999': 'Unknown error'
0: '',
-1: 'See status code',
-2: 'No data',
-3: 'No data or user',
-4: 'No user_id',
-100: 'Wrong post data',
-101: 'Wrong data type',
-102: 'Wrong query parameter',
-103: 'Wrong sort parameter',
-104: 'Wrong sort order parameter',
-201: 'Wrong username or password',
-202: 'User is banned',
-203: 'Username exists',
-204: 'Email address exists',
-999: 'Unknown error'
}
return msg[str(code)]
return msg[code]
def return_encode(code: int = 0, data: dict = {}, status: int = 200, msg: str = ''):
# 构造返回返回jsonify处理过后的response_class
if msg == '':
msg = code_get_msg(code)
if code < 0:
return jsonify({'status': status, 'code': code, 'data': {}, 'msg': msg})
else:
return jsonify({'status': status, 'code': code, 'data': data, 'msg': msg})

View File

@@ -3,12 +3,13 @@ from flask import (
)
import functools
import api.api_auth
import api.users
from . import users
import api.songs
from api.api_code import code_get_msg
from .api_code import code_get_msg, return_encode
bp = Blueprint('api', __name__, url_prefix='/api/v1')
bp.register_blueprint(users.bp)
class Query():
@@ -62,16 +63,6 @@ def get_query_parameter(request, query_able=[], sort_able=[]):
return decorator
def return_encode(code: int = 0, data: dict = {}, status: int = 200, msg: str = ''):
# 构造返回返回jsonify处理过后的response_class
if msg == '':
msg = code_get_msg(code)
if code < 0:
return jsonify({'status': status, 'code': code, 'data': {}, 'msg': msg})
else:
return jsonify({'status': status, 'code': code, 'data': data, 'msg': msg})
@bp.route('/')
def ping():
return return_encode()
@@ -111,7 +102,7 @@ def token_delete(user):
def users_get(query, user):
# 查询全用户信息
data = api.users.get_users(query)
data = users.get_users(query)
if not data:
return return_encode(-2)
@@ -133,7 +124,7 @@ def users_user_get(user, user_id):
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return return_encode(-1, {}, 403, 'No permission')
data = api.users.get_user_info(user_id)
data = users.get_user_info(user_id)
if not data:
return return_encode(-3)
@@ -152,7 +143,7 @@ def users_user_b30_get(user, user_id):
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return return_encode(-1, {}, 403, 'No permission')
data = api.users.get_user_b30(user_id)
data = users.get_user_b30(user_id)
if data['data'] == []:
return return_encode(-3)
@@ -173,7 +164,7 @@ def users_user_best_get(query, user, user_id):
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return return_encode(-1, {}, 403, 'No permission')
data = api.users.get_user_best(user_id, query)
data = users.get_user_best(user_id, query)
if data['data'] == []:
return return_encode(-3)
@@ -192,7 +183,7 @@ def users_user_r30_get(user, user_id):
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return return_encode(-1, {}, 403, 'No permission')
data = api.users.get_user_r30(user_id)
data = users.get_user_r30(user_id)
if data['data'] == []:
return return_encode(-3)

View File

@@ -1,9 +1,48 @@
from flask import (
Blueprint, request, jsonify
)
from .api_code import code_get_msg, return_encode
from .api_auth import role_required
from core.user import RegisterUser
from core.error import ArcError, PostError
from server.sql import Connect
from server.sql import Sql
import time
import web.webscore
import server.info
bp = Blueprint('users', __name__, url_prefix='/users')
@bp.route('', methods=['POST'])
@role_required(request, ['change'])
def users_post(user):
# 注册用户
with Connect() as c:
new_user = RegisterUser(c)
try:
if 'name' in request.json:
new_user.set_name(request.json['name'])
else:
raise PostError('No name provided.')
if 'password' in request.json:
new_user.set_password(request.json['password'])
else:
raise PostError('No password provided.')
if 'email' in request.json:
new_user.set_email(request.json['email'])
else:
raise PostError('No email provided.')
new_user.register()
except ArcError as e:
return return_encode(e.api_error_code)
return return_encode(0, {'user_id': new_user.user_id, 'user_code': new_user.user_code})
def get_users(query=None):
# 获取全用户信息,返回字典列表

View File

View File

@@ -0,0 +1,28 @@
class ArcError(Exception):
api_error_code = -999
error_code = 108
message = None
def __init__(self, message=None, error_code=None, api_error_code=None) -> None:
self.message = message
if error_code:
self.error_code = error_code
if api_error_code:
self.api_error_code = api_error_code
def __str__(self) -> str:
return repr(self.message)
class InputError(ArcError):
def __init__(self, message=None, error_code=None, api_error_code=-100) -> None:
super().__init__(message, error_code, api_error_code)
class DataExist(ArcError):
pass
class PostError(ArcError):
def __init__(self, message=None, error_code=None, api_error_code=-100) -> None:
super().__init__(message, error_code, api_error_code)

View File

@@ -0,0 +1,83 @@
import sqlite3
from flask import current_app
import traceback
class Connect():
# 数据库连接类,上下文管理
def __init__(self, file_path='./database/arcaea_database.db'):
"""
数据库连接默认连接arcaea_database.db
接受:文件路径
返回sqlite3连接操作对象
"""
self.file_path = file_path
def __enter__(self):
self.conn = sqlite3.connect(self.file_path)
self.c = self.conn.cursor()
return self.c
def __exit__(self, exc_type, exc_val, exc_tb):
if self.conn:
self.conn.commit()
self.conn.close()
if exc_type is not None:
current_app.logger.error(
traceback.format_exception(exc_type, exc_val, exc_tb))
return True
class Sql():
@staticmethod
def select(c, table_name, target_column=[], query=None):
# 执行查询单句sql语句返回fetchall数据
# 使用准确查询,且在单表内
sql = 'select '
sql_dict = {}
if len(target_column) >= 2:
sql += target_column[0]
for i in range(1, len(target_column)):
sql += ',' + target_column[i]
sql += ' from ' + table_name
elif len(target_column) == 1:
sql += target_column[0] + ' from ' + table_name
else:
sql += '* from ' + table_name
where_field = []
where_value = []
if query:
for i in query.query:
where_field.append(i)
where_value.append(query.query[i])
if where_field and where_value:
sql += ' where '
sql += where_field[0] + '=:' + where_field[0]
sql_dict[where_field[0]] = where_value[0]
if len(where_field) >= 2:
for i in range(1, len(where_field)):
sql_dict[where_field[i]] = where_value[i]
sql += ' and ' + where_field[i] + '=:' + where_field[i]
if query and query.sort:
sql += ' order by ' + \
query.sort[0]['column'] + ' ' + query.sort[0]['order']
for i in range(1, len(query.sort)):
sql += ', ' + query.sort[i]['column'] + \
' ' + query.sort[i]['order']
if query and query.limit >= 0:
sql += ' limit :limit offset :offset'
sql_dict['limit'] = query.limit
sql_dict['offset'] = query.offset
c.execute(sql, sql_dict)
return c.fetchall()

106
latest version/core/user.py Normal file
View File

@@ -0,0 +1,106 @@
from .error import ArcError, InputError, DataExist
from setting import Config
import hashlib
import time
class User:
name = None
email = None
password = None
user_id = None
user_code = None
def __init__(self) -> None:
pass
class RegisterUser(User):
def __init__(self, c) -> None:
super().__init__()
self.c = c
def set_name(self, name: str):
if 3 <= len(name) <= 16:
self.c.execute(
'''select exists(select * from user where name = :name)''', {'name': name})
if self.c.fetchone() == (0,):
self.name = name
else:
raise DataExist('Username exists.', 101, -203)
else:
raise InputError('Username is invalid.')
def set_password(self, password: str):
if 8 <= len(password) <= 32:
self.password = password
self.hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
else:
raise InputError('Password is invalid.')
def set_email(self, email: str):
# 邮箱格式懒得多判断
if 4 <= len(email) <= 32 and '@' in email and '.' in email:
self.c.execute(
'''select exists(select * from user where email = :email)''', {'email': email})
if self.c.fetchone() == (0,):
self.email = email
else:
raise DataExist('Email address exists.', 102, -204)
else:
raise InputError('Email address is invalid.')
def _build_user_code(self):
from random import randint
random_times = 0
while random_times <= 1000:
random_times += 1
user_code = ''.join([str(randint(0, 9)) for _ in range(9)])
self.c.execute('''select exists(select * from user where user_code = :user_code)''',
{'user_code': user_code})
if self.c.fetchone() == (0,):
break
if random_times <= 1000:
self.user_code = user_code
else:
raise ArcError('No available user code.')
def _build_user_id(self):
# 生成user_id往后加1
self.c.execute('''select max(user_id) from user''')
x = self.c.fetchone()
if x[0] is not None:
self.user_id = x[0] + 1
else:
self.user_id = 2000001
def _insert_user_char(self):
# 为用户添加初始角色
self.c.execute('''insert into user_char values(?,?,?,?,?,?)''',
(self.user_id, 0, 1, 0, 0, 0))
self.c.execute('''insert into user_char values(?,?,?,?,?,?)''',
(self.user_id, 1, 1, 0, 0, 0))
self.c.execute(
'''select character_id, max_level, is_uncapped from character''')
x = self.c.fetchall()
if x:
for i in x:
exp = 25000 if i[1] == 30 else 10000
self.c.execute('''insert into user_char_full values(?,?,?,?,?,?)''',
(self.user_id, i[0], i[1], exp, i[2], 0))
def register(self):
now = int(time.time() * 1000)
self._build_user_code()
self._build_user_id()
self._insert_user_char()
self.c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt,
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket, prog_boost, email)
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '', :memories, 0, :email)
''', {'user_code': self.user_code, 'user_id': self.user_id, 'join_date': now, 'name': self.name, 'password': self.hash_pwd, 'memories': Config.DEFAULT_MEMORIES, 'email': self.email})
self.c.execute('''insert into recent30(user_id) values(:user_id)''', {
'user_id': self.user_id})

View File

@@ -1,2 +1,2 @@
flask
flask==2.0.2
cryptography