def update_password(self): """ 修改密码 :return: """ old_password = self.get_post_data('old_password', require=True, error_message='请输入旧密码') password = self.get_post_data('password', require=True, error_message='请输入密码') with session_scope() as session: user = session.query(User).filter( User.uuid == self.user_uuid).first() if user is None: raise exception.api.Unauthorized('请先登录') hashed_old_password = authorization.toolkit.hash_plaintext( old_password) if hashed_old_password != user.password: raise exception.api.InvalidRequest('旧密码错误') user.password = authorization.toolkit.hash_plaintext(password) return ApiResult('修改密码成功', 201).to_response()
def get(self): with session_scope() as db_session: if not permission.toolkit.check_manage_role_permission( db_session, self.user_id): raise exception.api.Forbidden('当前用户无法管理角色') # 查询用户当前角色 user_role = None target_user_id = self.get_data('user_id') if self.valid_data(target_user_id): user_role = db_session.query(Role) \ .filter(User.id == UserRole.user_id) \ .filter(UserRole.role_id == Role.id) \ .filter(User.id == target_user_id).first() # 查询所有角色列表 roles = db_session.query(Role).order_by(Role.id).all() role_list = [] for role in roles: role_list.append(to_dict(role)) payload = {'roles': role_list} if user_role is not None: payload['user_role'] = to_dict(user_role) result = ApiResult('获取角色信息成功', 200, payload) return make_response(result.to_response())
def validate_email(self, jwt): try: jwt_dict = authorization.toolkit.decode_jwt_token(jwt) # type:dict except PyJWTError: raise exception.api.InvalidRequest('激活链接已过期或者激活请求非法') if 'sub' not in jwt_dict.keys( ) or jwt_dict['sub'] != JwtSub.Activation.value: raise exception.api.InvalidRequest('激活请求非法') uuid = jwt_dict['uuid'] with session_scope() as session: user = session.query(User).filter(User.uuid == uuid).first() if user.status == 1: raise exception.api.Conflict('邮箱已完成验证,无需重复验证') user.status = 1 scholar_payment_account = session.query(ScholarPaymentAccount) \ .filter(ScholarPaymentAccount.user_uuid == uuid, ScholarPaymentAccount.status == ScholarPaymentAccount.STATUS.VALID.value) \ .first() # type: ScholarPaymentAccount if scholar_payment_account is not None: scholar_payment_account.balance = configs.NEW_USER_SCHOLAR_BALANCE jwt_token = authorization.toolkit.derive_jwt_token(user_id=user.id, user_uuid=uuid) result = ApiResult('邮箱验证成功', 201, payload={'jwt': jwt_token}) return result.to_response()
def send_activation_email(self): with session_scope() as session: user = session.query(User).filter( User.uuid == self.user_uuid).first() expired_in = 48 extra_payload = {'sub': JwtSub.Activation.value} jwt = authorization.toolkit.derive_jwt_token( user_id=self.user_id, user_uuid=self.user_uuid, expired_in=expired_in, extra_payload=extra_payload) if configs.DEBUG: domain = 'http://localhost:8080' else: domain = 'http://www.celerysoft.science' activate_url = '{}/activation?jwt={}'.format(domain, jwt) background_task.send_activation_email.delay( user_email=user.email, username=user.username, activate_url=activate_url) return ApiResult('激活邮件已发送至注册邮箱{},请查收'.format(user.email), 201).to_response()
def get_user_services(self, user_uuid): with session_scope() as db_session: query = db_session.query(Service, ServiceTemplate.title) \ .outerjoin(ServiceTemplate, Service.template_uuid == ServiceTemplate.uuid) \ .filter(Service.user_uuid == user_uuid) \ .filter(Service.status != Service.STATUS.DELETED) \ .order_by(Service.created_at) page, page_size, offset, max_page = self._derive_page_parameter(query.count()) services = query.offset(offset).limit(page_size).all() service_list = [] for record in services: service = record.Service service_dict = service.to_dict() service_dict['title'] = record.title service_list.append(service_dict) result = ApiResult('获取用户学术服务信息成功', payload={ 'page': page, 'page_size': page_size, 'max_page': max_page, 'services': service_list }) return result.to_response()
def modify_email(self, jwt): try: jwt_dict = authorization.toolkit.decode_jwt_token(jwt) # type:dict except PyJWTError: raise exception.api.InvalidRequest('修改电子邮件地址的链接已过期或者激活请求非法') if 'sub' not in jwt_dict.keys( ) or jwt_dict['sub'] != JwtSub.ModifyEmail.value: raise exception.api.InvalidRequest('修改电子邮件地址的请求非法') if 'uuid' not in jwt_dict.keys() or 'email' not in jwt_dict.keys(): raise exception.api.InvalidRequest('修改电子邮件地址的请求非法') uuid = jwt_dict['uuid'] with session_scope() as session: user = session.query(User).filter(User.uuid == uuid).first() email = jwt_dict['email'] if user.email == email: raise exception.api.Conflict('电子邮箱地址已经成功完成了变更,无法重复变更') user.email = email jwt_token = authorization.toolkit.derive_jwt_token(user_id=user.id, user_uuid=uuid) result = ApiResult('电子邮箱地址修改成功', 201, payload={'jwt': jwt_token}) return result.to_response()
def post(self): name = self.get_post_data('name', require=True, error_message='缺少name字段') label = self.get_post_data('label', require=True, error_message='缺少label字段') description = self.get_post_data('description') permissions = self.get_post_data('permissions') with session_scope() as session: if not permission.toolkit.check_manage_role_permission( session, self.user_id): raise exception.api.Forbidden('当前用户无法管理角色') role = Role(name, label, description) session.add(role) session.flush() role_id = role.id for permission_id in permissions: role_permission = RolePermission(role_id, permission_id) session.add(role_permission) result = ApiResult('创建角色成功', 201, {'role_id': role_id}) return make_response(result.to_response())
def get(self): with session_scope() as session: invitation_list = [] query = self.derive_query_for_get_method(session, InvitationCode) \ .filter(InvitationCode.status != InvitationCode.Status.DELETED.value) page, page_size, offset, max_page = self.derive_page_parameter(query.count()) invitations = query.limit(page_size).offset(offset).all() for invitation in invitations: # type: InvitationCode invitation_dict = invitation.to_dict() inviter_username = session.query(User.username) \ .filter(User.uuid == invitation.inviter_uuid, User.status != User.STATUS.DELETED).first() inviter_username = inviter_username.username if inviter_username is not None else '' invitee_username = session.query(User.username) \ .filter(User.uuid == invitation.invitee_uuid, User.status != User.STATUS.DELETED).first() invitee_username = invitee_username.username if invitee_username is not None else '' invitation_dict['inviter_username'] = inviter_username invitation_dict['invitee_username'] = invitee_username invitation_list.append(invitation_dict) result = ApiResult('获取邀请码信息成功', payload={ 'invitations': invitation_list, 'page': page, 'page_size': page_size, 'max_page': max_page, }) return result.to_response()
def get_template_by_type(self, template_type: Union[str, int]): try: template_type = int(template_type) except ValueError: return exception.api.InvalidRequest('请输入正确的服务类型') if template_type == ServiceTemplate.TYPE.RECOMMENDATION: return self.get_recommendation_template() with session_scope() as session: query = session.query(ServiceTemplate).filter( ServiceTemplate.type == template_type, ServiceTemplate.status == ServiceTemplate.STATUS.VALID) page, page_size, offset, max_page = self.derive_page_parameter( query.count()) templates = query.offset(offset).limit(page_size).all() result = ApiResult( '获取服务模板信息成功', 200, { 'templates': self.models_to_list(templates), 'page': page, 'page_size': page_size, 'max_page': max_page, }) return result.to_response()
def get(self): with session_scope() as session: event_list = [] query = self.derive_query_for_get_method(session, Event) \ .filter(Event.status != Event.Status.DELETED.value) page, page_size, offset, max_page = self.derive_page_parameter( query.count()) events = query.limit(page_size).offset(offset).all() for event in events: # type: Event event_dict = event.to_dict('content') author_username = session.query(User.username) \ .filter(User.uuid == event.author_uuid, User.status != User.STATUS.DELETED).first() author_username = author_username.username if author_username is not None else '' event_dict['author_username'] = author_username event_list.append(event_dict) result = ApiResult('获取公告成功', payload={ 'events': event_list, 'page': page, 'page_size': page_size, 'max_page': max_page, }) return result.to_response()
def get(self): log_file = configs.SS_LISTENER_LOG_FILE with open(log_file, 'r') as f: lines = f.readlines() lines = lines[-10:] if len(lines) >= 10 else lines warning_message = None last_record = lines[-1] if len(lines) > 0 else None if last_record is not None: datetime_str = last_record.split(' - ')[0] last_record_datetime = datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S,%f') if datetime.now().timestamp() - last_record_datetime.timestamp( ) > 12 * 60 * 60: warning_message = '最后一条记录产生于12小时之前,请检查是否需要重启监听服务' elif datetime.now().timestamp() - last_record_datetime.timestamp( ) < 0: warning_message = '最后一条记录产生在未来,我的天!请检查是否需要重启监听服务' else: warning_message = '监听服务运行正常' response_data = { 'usages': lines, 'warning_message': warning_message, } result = ApiResult('获取学术统计信息成功', 200, response_data) return make_response(result.to_response())
def put(self): service_uuid = self.get_post_data('uuid', require=True, error_message='缺少uuid字段') password = self.get_post_data('password', require=True, error_message='请输入长度至少为1位的新密码') with session_scope() as session: service = session.query(Service).filter( Service.uuid == service_uuid).first() if service is None: raise exception.api.NotFound('套餐不存在') if service.user_uuid != self.user_uuid: raise exception.api.Forbidden('无权修改其他用户的学术服务密码') service.password = password if service.status == Service.STATUS.ACTIVATED: background_task.modify_port_password.delay(port=service.port, password=password) result = ApiResult('修改连接密码成功', 201) return result.to_response()
def delete(self): """ 取消订单 :return: """ uuid = self.get_data('uuid', require=True, error_message='缺少uuid字段') with session_scope() as session: order = session.query(TradeOrder) \ .filter(TradeOrder.uuid == uuid, TradeOrder.status != TradeOrder.STATUS.DELETED.value).first() # type: TradeOrder if order is None: raise exception.api.NotFound('订单不存在') if order.user_uuid != self.user_uuid: raise exception.api.Forbidden('无权修改他人的订单') if order.status == TradeOrder.STATUS.CANCEL.value: raise exception.api.Conflict('订单已取消,无法重复取消') if order.status not in [ TradeOrder.STATUS.INITIALIZATION.value, TradeOrder.STATUS.PAYING.value ]: raise exception.api.InvalidRequest( '订单已进入支付流程,无法取消,请完成支付后进行退款操作') order.status = TradeOrder.STATUS.CANCEL.value result = ApiResult('订单取消成功') return result.to_response()
def reset_password(self, jwt: str): """ 重设密码 :return: """ password = self.get_post_data('password', require=True, error_message='请输入新密码') try: jwt_dict = authorization.toolkit.decode_jwt_token(jwt) # type:dict except PyJWTError: raise exception.api.InvalidRequest('重设密码的链接已过期或者重设密码请求非法') if 'sub' not in jwt_dict.keys( ) or jwt_dict['sub'] != JwtSub.ResetPassword.value: raise exception.api.InvalidRequest('重设密码的请求非法') if 'uuid' not in jwt_dict.keys(): raise exception.api.InvalidRequest('重设密码的请求非法') uuid = jwt_dict['uuid'] with session_scope() as session: user = session.query(User).filter(User.uuid == uuid).first() user.password = authorization.toolkit.hash_plaintext(password) result = ApiResult('密码重设成功,以后请使用新密码登录', 201) return result.to_response()
def generate_creation_order(self, service_template_uuid: str): """ 生成创建新的学术服务的订单 :param service_template_uuid: :return: """ with session_scope() as session: conflict, snapshot = trade_order.toolkit.check_is_order_conflict( session, self.user_uuid, service_template_uuid=service_template_uuid) if conflict: raise exception.api.Conflict('有尚未支付的『{}』的订单,请勿重复下单'.format( snapshot.title)) password = self.get_post_data('password', require=True, error_message='缺少password字段') auto_renew = self.get_post_data('auto_renew') service_template = session.query(ServiceTemplate) \ .filter(ServiceTemplate.uuid == service_template_uuid, ServiceTemplate.status != ServiceTemplate.STATUS.DELETED).first() # type: ServiceTemplate if service_template is None: raise exception.api.NotFound('套餐不存在,无法办理') if service_template.status == ServiceTemplate.STATUS.SUSPEND: raise exception.api.ServiceUnavailable('该套餐已下架,故无法办理') total_payment = service_template.initialization_fee + service_template.price order = TradeOrder(user_uuid=self.user_uuid, order_type=TradeOrder.TYPE.CONSUME.value, amount=total_payment, description='开通学术服务,服务模板UUID:{}'.format( service_template.uuid)) session.add(order) session.flush() auto_renew = auto_renew if self.valid_data(auto_renew) else 0 snapshot = SubscribeServiceSnapshot( trade_order_uuid=order.uuid, user_uuid=self.user_uuid, service_password=password, auto_renew=auto_renew, service_template_uuid=service_template_uuid, service_type=service_template.type, title=service_template.title, subtitle=service_template.subtitle, description=service_template.description, package=service_template.package, price=service_template.price, initialization_fee=service_template.initialization_fee) session.add(snapshot) result = ApiResult('订单创建成功', 201, { 'uuid': order.uuid, }) return result.to_response()
def delete(self): with session_scope() as session: self.delete_model(session, Event, delete_status=Event.Status.DELETED.value, not_found_error_message='需要删除的公告不存在') result = ApiResult('删除公告成功') return result.to_response()
def get_order_by_uuid(self, uuid: str): with session_scope() as session: order = session.query(TradeOrder) \ .filter(TradeOrder.uuid == uuid, TradeOrder.status != TradeOrder.STATUS.DELETED.value).first() # type: TradeOrder if order is None: raise exception.api.NotFound('订单不存在') result = ApiResult('获取订单信息成功', payload={'order': order.to_dict()}) return result.to_response()
def post(self): with session_scope() as session: invitation = InvitationCode(self.user_uuid) session.add(invitation) session.flush() result = ApiResult('创建邀请码成功', 201, payload={ 'invitation': invitation.to_dict(), }) return result.to_response()
def put(self): with session_scope() as session: event = self.update_model(session, Event) result = ApiResult('修改公告成功', 200, payload={ 'event': event.to_dict(), }) return result.to_response()
def put(self): with session_scope() as session: template = self.update_model(session, ServiceTemplate) result = ApiResult('修改学术服务模板成功', 200, payload={ 'template': template.to_dict(), }) return result.to_response()
def get_template_by_uuid(self, uuid: str): with session_scope() as session: service_template = session.query(ServiceTemplate) \ .filter(ServiceTemplate.uuid == uuid).first() # type: ServiceTemplate if service_template is None: raise exception.api.NotFound('服务模版不存在') result = ApiResult( '获取服务模板信息成功', payload={'template': service_template.to_dict()}) return result.to_response()
def get(self): with session_scope() as db_session: permissions = permission.toolkit.derive_user_permissions( db_session, self.user_uuid) permission_list = [] for p in permissions: # type: Permission permission_list.append(p.to_dict()) result = ApiResult('获取用户权限成功', payload={'permissions': permission_list}) return make_response(result.to_response())
def post(self): with session_scope() as session: event = self.create_model_from_http_post(Event) session.add(event) session.flush() result = ApiResult('发布公告成功', 201, payload={ 'event': event.to_dict(), }) return result.to_response()
def get_single_account(self, user_uuid): with session_scope() as session: account = session.query(ScholarPaymentAccount) \ .filter(ScholarPaymentAccount.user_uuid == user_uuid, ScholarPaymentAccount.status != ScholarPaymentAccount.STATUS.DELETED.value) \ .first() # type: ScholarPaymentAccount if account is None: raise exception.api.NotFound('学术积分账户不存在') result = ApiResult('获取学术积分账户信息成功', payload={'account': account.to_dict()}) return result.to_response()
def post(self): # service_type = self.get_post_data('type', require=True, error_message='缺少type字段') # title = self.get_post_data('title', require=True, error_message='缺少title字段') # subtitle = self.get_post_data('subtitle', require=True, error_message='缺少subtitle字段') # description = self.get_post_data('description', require=True, error_message='缺少description字段') # package = self.get_post_data('package', require=True, error_message='缺少package字段') # try: # package = int(package) # except: # raise exception.api.InvalidRequest('请输入合法的package字段') # price = self.get_post_data('price', require=True, error_message='缺少price字段') # try: # price = float(price) # except: # raise exception.api.InvalidRequest('请输入合法的price字段') # initialization_fee = self.get_post_data('initialization_fee', require=True, # error_message='缺少initialization_fee字段') # try: # initialization_fee = float(initialization_fee) # except: # raise exception.api.InvalidRequest('请输入合法的initialization_fee字段') # # with session_scope() as session: # template = ServiceTemplate( # service_type=service_type, # title=title, # subtitle=subtitle, # description=description, # package=package, # price=price, # initialization_fee=initialization_fee, # ) # session.add(template) # session.flush() # # result = ApiResult('创建学术服务模板成功', 201, payload={ # 'template': template.to_dict(), # }) # return result.to_response() with session_scope() as session: template = self.create_model_from_http_post(ServiceTemplate) session.add(template) session.flush() result = ApiResult('创建学术服务模板成功', 201, payload={ 'template': template.to_dict(), }) return result.to_response()
def get_events(self): with session_scope() as session: query = self.derive_query_for_get_method(session, Event) \ .filter(Event.status == Event.Status.VALID.value) page, page_size, offset, max_page = self.derive_page_parameter( query.count()) events = query.offset(offset).limit(page_size).all() event_list = [] for event in events: # type:Event event_list.append(event.to_dict('content')) result = ApiResult('获取公告成功', payload={'events': event_list}) return result.to_response()
def get_orders(self): with session_scope() as session: order_list = [] query = session.query(TradeOrder, SubscribeServiceSnapshot.title) orders = self.derive_query_for_get_method(session, TradeOrder, query) \ .outerjoin(SubscribeServiceSnapshot, SubscribeServiceSnapshot.trade_order_uuid == TradeOrder.uuid) \ .filter(TradeOrder.user_uuid == self.user_uuid).all() for order in orders: order_dict = order.TradeOrder.to_dict() order_dict['title'] = order.title order_list.append(order_dict) result = ApiResult('获取订单信息成功', payload={ 'orders': order_list, }) return result.to_response()
def delete(self): uuid = self.get_data('uuid', require=True, error_message='请输入uuid字段') with session_scope() as session: template = session.query(ServiceTemplate) \ .filter(ServiceTemplate.uuid == uuid, ServiceTemplate.status != ServiceTemplate.STATUS.DELETED) \ .first() # type: ServiceTemplate if template is None: raise exception.api.NotFound('需要删除的学术服务模板不存在') template.status = 2 result = ApiResult('删除学术服务模板成功') return result.to_response()
def get_self_information(self): with session_scope() as session: user = session.query(User).filter( User.uuid == self.user_uuid).first() # type:User result = ApiResult('获取个人信息成功', payload={ 'uuid': user.uuid, 'username': user.username, 'email': user.email, 'register_date': user.created_at.isoformat(), 'created_at': user.created_at.isoformat(), 'status': user.status }) return result.to_response()
def patch(self): with session_scope() as session: uuid = self.get_post_data('uuid', require=True, error_message='缺少uuid字段') service = session.query(Service).filter(Service.uuid == uuid).first() if service is None: raise exception.api.NotFound('学术服务不存在') if service.user_uuid != self.user_uuid: raise exception.api.Forbidden('无权修改其他用户的学术服务') auto_renew = self.get_post_data('auto_renew') if self.valid_data(auto_renew): self.patch_service_auto_renew(service) result = ApiResult('修改套餐成功', 201) return result.to_response()