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): def code_get_msg(code):
# api接口code获取msg返回字符串 # api接口code获取msg返回字符串
msg = { msg = {
'0': '', 0: '',
'-1': 'See status code', -1: 'See status code',
'-2': 'No data', -2: 'No data',
'-3': 'No data or user', -3: 'No data or user',
'-4': 'No user_id', -4: 'No user_id',
'-100': 'Wrong post data', -100: 'Wrong post data',
'-101': 'Wrong data type', -101: 'Wrong data type',
'-102': 'Wrong query parameter', -102: 'Wrong query parameter',
'-103': 'Wrong sort parameter', -103: 'Wrong sort parameter',
'-104': 'Wrong sort order parameter', -104: 'Wrong sort order parameter',
'-201': 'Wrong username or password', -201: 'Wrong username or password',
'-202': 'User is banned', -202: 'User is banned',
'-999': 'Unknown error' -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 functools
import api.api_auth import api.api_auth
import api.users from . import users
import api.songs 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 = Blueprint('api', __name__, url_prefix='/api/v1')
bp.register_blueprint(users.bp)
class Query(): class Query():
@@ -62,16 +63,6 @@ def get_query_parameter(request, query_able=[], sort_able=[]):
return decorator 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('/') @bp.route('/')
def ping(): def ping():
return return_encode() return return_encode()
@@ -111,7 +102,7 @@ def token_delete(user):
def users_get(query, user): def users_get(query, user):
# 查询全用户信息 # 查询全用户信息
data = api.users.get_users(query) data = users.get_users(query)
if not data: if not data:
return return_encode(-2) 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权限 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') 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: if not data:
return return_encode(-3) 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权限 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') 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'] == []: if data['data'] == []:
return return_encode(-3) 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权限 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') 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'] == []: if data['data'] == []:
return return_encode(-3) 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权限 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') 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'] == []: if data['data'] == []:
return return_encode(-3) 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 Connect
from server.sql import Sql from server.sql import Sql
import time import time
import web.webscore import web.webscore
import server.info 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): 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 cryptography