def follow_user(): """ 关注一个用户 :return: """ ids = json_to_pyseq(request.argget.all("ids", [])) s, r = arg_verify(reqargs=[("id", ids)], required=True) if not s: return r cnt = 0 for tid in ids[:]: if tid != current_user.str_id and get_one_user(user_id=str(tid)): r = mdb_user.db.user_follow.update_one( { "user_id": current_user.str_id, "type": "account" }, {"$addToSet": { "follow": tid }}, upsert=True) if r.modified_count or r.upserted_id: cnt += 1 # 更新粉丝统计 update_one_user(user_id=str(tid), updata={"$inc": { "fans_num": 1 }}) delete_user_info_cache(user_id=tid) if cnt: # 更新关注统计 update_one_user(user_id=current_user.str_id, updata={"$inc": { "follow_user_num": cnt }}) delete_user_info_cache(user_id=current_user.str_id) data = { "msg": gettext("Followed"), "msg_type": "s", "http_status": 201 } elif len(ids) == 1 and ids[0] == current_user.str_id: data = { "msg": gettext("You can't follow yourself"), "msg_type": "w", "http_status": 400 } else: data = { "msg": gettext("You are already following this user"), "msg_type": "w", "http_status": 400 } return data
def user_del(): ids = json_to_pyseq(request.argget.all('ids', [])) permanent = request.argget.all('permanent', 0) try: permanent = int(permanent) except BaseException: pass noper = 0 temp_ids = ids[:] ids = [] for tid in temp_ids: # 检查是否有权限 current_user_role = mdbs["user"].db.role.find_one({"_id": ObjectId(current_user.role_id)}) rm_user = get_one_user(user_id=str(tid)) rm_user_role = mdbs["user"].db.role.find_one({"_id": ObjectId(rm_user["role_id"])}) if get_num_digits(current_user_role["permissions"]) <= get_num_digits(rm_user_role["permissions"]): # 没有权限删除 continue ids.append(ObjectId(tid)) if not permanent: update_data = { 'is_delete': 1 } r = mdbs["user"].db.user.update_many( {"_id": {"$in": ids}}, {"$set": update_data}) if r.modified_count: for uid in ids: clean_get_one_user_cache(user_id=uid) data = { 'msg': gettext("Has recovered {} users, {} users can not operate").format( r.modified_count, noper), 'msg_type': "s", "custom_status": 201} else: data = { 'msg': gettext("Recycle user failed.May not have permission"), 'msg_type': "w", "custom_status": 401} else: # 永久删除 r = mdbs["user"].db.user.delete_many( {"_id": {"$in": ids}, "is_delete": {"$in": [1, True]}}) if r.deleted_count: data = { 'msg': gettext( "{} users have been deleted and {} users can not be deleted".format( r.deleted_count, noper)), 'msg_type': "s", "custom_status": 204} else: data = { 'msg': gettext("Failed to delete.May not have permission"), 'msg_type': "w", "custom_status": 401} return data
def verify_password(self, password): """ 密码验证 :param password: :return: """ user = get_one_user(user_id=str(self.id)) return check_password_hash(user["password"], password)
def clean_login(self): """ 清理用户登录 :return: """ auth_token = request.headers.get('OSR-BearerToken') if auth_token: payload = self.decode_auth_token(auth_token) if not isinstance(payload, str): user = get_one_user(user_id=str(payload['data']['id'])) if not user: result = ( None, gettext( "User authentication failed, user does not exist")) else: if payload['data']["cid"] in user["jwt_login_time"] and \ user["jwt_login_time"][payload['data']["cid"]] == \ payload['data']['login_time']: # 清除退出当前客户端的登录时间信息 user = get_one_user(user_id=str(payload['data']['id'])) del user["jwt_login_time"][payload["data"]["cid"]] update_one_user(user_id=payload["data"]["id"], updata={ "$set": { "jwt_login_time": user["jwt_login_time"] } }) result = (True, "") else: result = (True, "") else: result = (None, payload) else: result = ( None, gettext( 'No user authentication token provided "OSR-BearerToken"')) return result
def user(): tid = request.argget.all('id').strip() data = {} data["user"] = get_one_user(user_id=str(tid)) if not data["user"]: data = { 'msg': gettext("The specified user is not found"), 'msg_type': "w", "custom_status": 404} else: data["user"]["_id"] = str(data["user"]["_id"]) data["user"]["role_id"] = str(data["user"]["role_id"]) return data
def user_edit(): """ 用户编辑 :return: """ tid = request.argget.all('id') role_id = request.argget.all('role_id') active = str_to_num(request.argget.all('active', 0)) s, r = arg_verify(reqargs=[("id", tid), ("role_id", role_id)], required=True) if not s: return r data = { 'msg': gettext("Update success"), 'msg_type': "s", "custom_status": 201 } update_data = { 'role_id': role_id, 'active': active, } user = get_one_user(user_id=str(tid)) if user: # 权限检查 current_user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(current_user.role_id)}) edit_user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(user["role_id"])}) if edit_user_role \ and get_num_digits(current_user_role["permissions"]) \ <= get_num_digits(edit_user_role["permissions"]): # 没有权限修改 data = { "msg_type": "w", "msg": gettext("No permission modification"), "custom_status": 401 } return data r = update_one_user(user_id=str(tid), updata={"$set": update_data}) if not r.modified_count: data = { 'msg': gettext("No changes"), 'msg_type': "w", "custom_status": 201 } return data
def __init__(self, id, **kwargs): user_id = id super(User, self).__init__(**kwargs) user = get_one_user(user_id=str(user_id)) if user: if "password" in user and user["password"]: self.no_password = False del user["password"] else: self.no_password = True self.id = ObjectId(user_id) self.str_id = str(user_id) self.username = user["username"] self.alias = user["alias"] self.email = user["email"] self.mphone_num = user["mphone_num"] self.custom_domain = user["custom_domain"] self.gender = user["gender"] self.avatar_url = get_avatar_url(user["avatar_url"]) self.role_id = ObjectId(user["role_id"]) self.active = user["active"] self.is_delete = user["is_delete"] self.create_at = user["create_at"] self.update_at = user["update_at"] self.editor = user["editor"] self.jwt_login_time = user.get("jwt_login_time", None) if not self.mphone_num: user_info_mphone_num = None else: temp_num = str(self.mphone_num) user_info_mphone_num = "{}****{}".format( temp_num[0:3], temp_num[-5:-1]), self.user_info = { "username": self.username, "active": self.active, "is_delete": self.is_delete, "email": self.email, "mphone_num": user_info_mphone_num, "custom_domain": self.custom_domain, "avatar_url": self.avatar_url, "role_id": self.role_id, "id": self.id } else: return
def user_activation(): active = int(request.argget.all('active', 0)) ids = json_to_pyseq(request.argget.all('ids', [])) noper = 0 ac_ids = [] for uid in ids: # 检查是否有权限 current_user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(current_user.role_id)}) re_user = get_one_user(user_id=str(uid)) re_user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(re_user["role_id"])}) if get_num_digits(current_user_role["permissions"]) <= get_num_digits( re_user_role["permissions"]): # 没有权限恢复 noper += 1 continue ac_ids.append(ObjectId(uid)) update_data = {'active': active} r = mdbs["user"].db.user.update_many({"_id": { "$in": ac_ids }}, {"$set": update_data}) if r.modified_count: for uid in ac_ids: clean_get_one_user_cache(user_id=uid) data = { 'msg': gettext( "{} user activation is successful, {} no permission to operate" .format(r.modified_count, noper)), 'msg_type': "s", "custom_status": 201 } else: data = { 'msg': gettext("Activation failed.May not have permission"), 'msg_type': "w", "custom_status": 401 } return data
def user_restore(): ids = json_to_pyseq(request.argget.all('ids', [])) noper = 0 re_ids = [] for uid in ids: # 检查是否有权限 current_user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(current_user.role_id)}) re_user = get_one_user(user_id=str(uid)) re_user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(re_user["role_id"])}) if get_num_digits(current_user_role["permissions"]) <= get_num_digits( re_user_role["permissions"]): # 没有权限恢复 noper += 1 continue re_ids.append(ObjectId(uid)) update_data = {'is_delete': 0} r = mdbs["user"].db.user.update_many({"_id": { "$in": re_ids }}, {"$set": update_data}) if r.modified_count: for uid in re_ids: clean_get_one_user_cache(user_id=uid) data = { 'msg': gettext( "Restore the {} users,The other {} users have no power control" .format(r.modified_count, noper)), 'msg_type': "s", "custom_status": 201 } else: data = { 'msg': gettext("Restore the failure.May not have permission"), 'msg_type': "w", "custom_status": 401 } return data
def send_code(): """ 发送验证码 :return: """ data = {} account_type = request.argget.all('account_type', "email").strip() account = request.argget.all('account') exist_account = str_to_num(request.argget.all('exist_account', 0)) code = request.argget.all('code', '').strip() code_url_obj = json_to_pyseq(request.argget.all('code_url_obj', {})) s, r = arg_verify(reqargs=[("account_type", account_type)], only=["email", "mobile_phone"]) if not s: return r if account_type == "email": s, r = arg_verify(reqargs=[(gettext("Email"), account)], required=True) if not s: return r # 邮箱格式验证 r, s = email_format_ver(account) if not r: data = {'msg': s, 'msg_type': "e", "custom_status": 422} return data if exist_account: if not get_one_user(email=account): data = { 'msg': gettext("This account is not registered on this platform"), 'msg_type': "w", "custom_status": 400 } return data r, s = call_verification(code_url_obj, code) if not r: return s data = create_code_send(account=account, account_type=account_type) elif account_type == "mobile_phone": s, r = arg_verify(reqargs=[(gettext("Telephone number"), account)], required=True) if not s: return r # 移动号码格式格式验证 r, s = mobile_phone_format_ver(account) if not r: data = {'msg': s, 'msg_type': "e", "custom_status": 422} return data if exist_account: user_query = {"mphone_num": account} if not get_one_user(mphone_num=account): data = { 'msg': gettext("This account is not registered on this platform"), 'msg_type': "w", "custom_status": 400 } return data r, s = call_verification(code_url_obj, code) if not r: return s data = create_code_send(account=account, account_type=account_type) return data
def p_retrieve_password(email, code, password, password2): """ 密码重设 :param account: :param code: :param password: :param password2: :return: """ data = {} if not email: data = { 'msg': gettext('Account does not exist'), 'msg_type': 'e', "http_status": 404 } return data s, r = email_format_ver(email=email) if s: user = get_one_user(email=email) else: data = {"msg": r, "msg_type": "e", "http_status": 403} return data if user: r = verify_code(code, email=user["email"]) else: data = { 'msg': gettext('Account does not exist'), 'msg_type': 'e', "http_status": 404 } return data if not r: data = { 'msg': gettext('Email or SMS verification code error'), 'msg_type': 'e', "http_status": 401 } else: if user: r = password_format_ver(password) if not r: data = {"msg": r, "msg_type": "e", "http_status": "403"} return data elif password != password2: data = { 'msg': gettext('Two password is not the same'), 'msg_type': 'w', "http_status": 400 } else: password_hash = generate_password_hash(password) # 将jwt_login_time设为{}退出所有jwt登录的用户 r = update_one_user(user_id=str(user["_id"]), updata={ "$set": { "password": password_hash, "jwt_login_time": {} } }) if r.modified_count: oplog = { 'op_type': 'retrieve_pass', 'time': time.time(), 'status': 's', 'info': '', 'ip': request.remote_addr } insert_op_log(oplog, user_id=user["_id"]) # 发送邮件 subject = gettext("Password reset notification") body = "Your account <a>{}</a> has reset your password. <br>Please keep it safe.".format( user["email"]) data = { "title": subject, "body": body, "other_info": gettext("End"), } html = get_email_html(data) send_email(subject=subject, recipients=[user["email"]], html_msg=html) data = { 'msg': gettext( 'Password reset successfully.Please return to login page to login' ), 'msg_type': 's', "http_status": 201 } logout_user() else: data = { "msg_type": "w", "msg": gettext("Reset password failed(unknown error)"), "http_status": 400 } return data return data
def user_edit(): """ 用户编辑 :return: """ tid = request.argget.all('id') role_id = request.argget.all('role_id') email = request.argget.all('email') password = request.argget.all('password') active = str_to_num(request.argget.all('active', 0)) s, r = arg_verify(reqargs=[("id", tid), ("role_id", role_id)], required=True) if not s: return r data = { 'msg': gettext("Update success"), 'msg_type': "s", "custom_status": 201 } if not email: email = None update_data = {'role_id': role_id, 'active': active, "email": email} user = get_one_user(user_id=str(tid)) if user: # 权限检查 current_user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(current_user.role_id)}) edit_user_role = mdbs["user"].db.role.find_one( {"_id": ObjectId(user["role_id"])}) if edit_user_role \ and get_num_digits(current_user_role["permissions"]) \ <= get_num_digits(edit_user_role["permissions"]): # 没有权限修改 data = { "msg_type": "w", "msg": gettext("No permission modification"), "custom_status": 401 } return data if email: # 邮件注册 # 邮箱格式验证 s, r = email_format_ver(email) if not s: data = {'msg': r, 'msg_type': "e", "custom_status": 422} return data elif mdbs["user"].db.user.find_one({ "email": email, "_id": { "$ne": ObjectId(tid) } }): # 邮箱是否注册过 data = { 'msg': gettext( "This email has been registered in the site oh, please login directly." ), 'msg_type': "w", "custom_status": 403 } return data if password: # 密码格式验证 s, r = password_format_ver(password) if not s: data = {'msg': r, 'msg_type': "e", "custom_status": 422} return data if password: password = generate_password_hash(password) update_data["password"] = password r = update_one_user(user_id=str(tid), updata={"$set": update_data}) if not r.modified_count: data = { 'msg': gettext("No changes"), 'msg_type': "w", "custom_status": 201 } return data
def p_sign_in(username, password, code_url_obj, code, remember_me, use_jwt_auth=0): ''' 用户登录函数 :param adm: :return: ''' data = {} if current_user.is_authenticated and username in [current_user.username, current_user.email, current_user.mphone_num]: data['msg'] = gettext("Is logged in") data["msg_type"] = "s" data["http_status"] = 201 data['to_url'] = request.argget.all('next') or get_config("login_manager", "LOGIN_IN_TO") return data # name & pass s, r = email_format_ver(username) s2, r2 = mobile_phone_format_ver(username) if s: user = get_one_user(email=username) elif s2: user = get_one_user(mphone_num=username) else: user = get_one_user(username=username) if not user: data = {"msg":gettext("Account or password error"), "msg_type":"e", "http_status":401} return data user = User(user["_id"]) # 判断是否多次密码错误,是就要验证图片验证码 user_p = mdb_user.db.user_login_log.find_one({'user_id':user.str_id}) PW_WRONG_NUM_IMG_CODE = get_config("login_manager", "PW_WRONG_NUM_IMG_CODE") if user_p and 'pass_error' in user_p and user_p['pass_error'] >= PW_WRONG_NUM_IMG_CODE: # 图片验证码验证 r = verify_image_code(code_url_obj, code) if not r: data["open_img_verif_code"] = True data['msg'] = gettext("Verification code error") data["msg_type"] = "e" data["http_status"] = 401 return data # 密码验证 if user and user.verify_password(password) and not user.is_delete: if user.is_active: if use_jwt_auth: # 使用的时jwt验证 # 获取token jwt_auth = JwtAuth() data["auth_token"] = jwt_auth.get_login_token(user) client = "app" else: login_user(user, remember_me) client = "browser" # 记录登录日志 login_log(user, client) data['msg'] = gettext("Sign in success") data["msg_type"] = "s" data["http_status"] = 201 data["to_url"] = request.argget.all('next') or get_config("login_manager", "LOGIN_IN_TO") return data # 未激活 data['msg'] = gettext("Account is inactive or frozen") data["msg_type"] = "w" data["http_status"] = 401 else: # 密码错误 mdb_user.db.user_login_log.update_one({'user_id':user.str_id}, {"$inc":{"pass_error":1}}, upsert=True) # 判断是否多次密码错误 if user_p and 'pass_error' in user_p and user_p['pass_error'] >= PW_WRONG_NUM_IMG_CODE: # 图片验证码验证码 data["open_img_verif_code"] = True data['msg'] = gettext("Account or password error") data["msg_type"] = "e" data["http_status"] = 401 return data
def avatar_upload(): """ 头像上传 :return: """ result = None imgfile_base = request.argget.all("imgfile_base") max_size_mb = get_config("account", "USER_AVATAR_MAX_SIZE") max_size_b = max_size_mb * 1024 * 1024 if imgfile_base: if len(imgfile_base) > max_size_b: data = { "msg": gettext("Upload avatar image can not exceed {}M".format( max_size_mb)), "msg_type": "w", "http_status": 413 } return data else: result = fileup_base_64(uploaded_files=[imgfile_base], prefix="user_avatar/") else: file = request.files['upfile'] if len(file.read()) > max_size_b: data = { "msg": gettext("Upload avatar image can not exceed {}M".format( max_size_mb)), "msg_type": "w", "http_status": 413 } return data if file: tailoring = request.argget.all('tailoring') if tailoring: if not isinstance(tailoring, dict): tailoring = json.loads(tailoring) for k in ["width", "height", "x", "y", "rotate"]: tailoring.setdefault(k, 0) result = file_up(uploaded_files=[file], prefix="user_avatar/", tailoring=tailoring) data = {} if result: result = result[0] user = get_one_user(user_id=current_user.str_id) if user: if user['avatar_url'] and "key" in user['avatar_url'] \ and result["key"] != user['avatar_url']["key"]: # 当使用了不同的名字删除老的头像 file_del(user['avatar_url']) update_data = {"avatar_url": result} r = update_one_user(user_id=current_user.str_id, updata={"$set": update_data}) if not r.matched_count: data = { 'msg': gettext("Save failed"), 'msg_type': "w", "http_status": 400 } else: if result["type"] == "local": # 如果保存再本地的话, 保存为一定尺寸大小 path = "{}{}".format(APPS_PATH, get_file_url(result)) imgcp = ImageCompression(path, path) ava_size = get_config("account", "USER_AVATAR_SIZE") imgcp.custom_pixels(ava_size[0], ava_size[1]) data = { 'msg': gettext("Save successfully"), 'msg_type': "s", "http_status": 201 } if not data: data = { 'msg': gettext("Upload failed"), 'msg_type': "w", "http_status": 400 } # 清理user信息数据缓存 delete_user_info_cache(user_id=current_user.str_id) return data