def post(self): '''完成重置密码''' form = ForgetPasswordForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) identifier = self.db.query(AuthIdentifier).filter_by( uuid=form.identifier_id.data).first() if not identifier: return self.fail(_("No such identifier")) if identifier.code != form.identifier_code.data: return self.fail(_("Invalid identifier code")) if not identifier.is_valid(): return self.fail(_("Identifier is expired")) u = self.db.query(User).filter_by(email=identifier.data).first() if not u: # TODO: should not got it! return self.fail(_("User is not existed")) u.set_password(form.password.data) self.db.delete(identifier) for s in u.sessions: self.db.delete(s) self.db.commit() # TODO: 生成新 sid , 以便用户自动登录? self.success()
def save_single_file(db, filedata, user): # TODO: fix me! tp = os.path.join(settings.OSS_PATH, str(user.uid)) if not os.path.isdir(tp): try: os.makedirs(tp) logging.info('create oss storage path: %s', tp) except Exception as e: logging.error('create oss path failed: %s', e) return None, _("Create OSS path failed!") for f in filedata: h = hashlib.sha1() h.update(f['body']) checksum = h.hexdigest() save_to = os.path.join(settings.OSS_PATH, "{0}".format(checksum)) # OOSObject 是否存在 obj = db.query(OSSObject).filter_by(checksum=checksum).first() if obj: logging.debug('OSSObject %s is existed, pass create', checksum) else: # 创建 obj try: open(save_to, 'wb').write(f['body']) logging.debug('save OSSObject %s success', save_to) except Exception as e: logging.error('save OSSObject failed: %s', e) return None, _("save OSSObject failed!") obj = OSSObject(size=len(f['body']), checksum=checksum) obj.uid = OSSObject.gen_uid(db) db.add(obj) db.commit() # OSSUserObject 关联是否存在 user_obj = db.query(OSSUserObject).filter( and_(OSSUserObject.user_id == user.id, OSSUserObject.obj_id == obj.id)).first() if user_obj: logging.warning('OSSUserObject %s is existed', user_obj.uid) else: # 创建用户关联 user_obj = OSSUserObject(user=user, obj=obj, filename=f['filename']) user_obj.uid = OSSUserObject.gen_uid(db) db.add(user_obj) db.commit() # 创建硬连接 user_obj_save_to = os.path.join( tp, "{0}_{1}".format(obj.checksum, user_obj.filename)) os.link(save_to, user_obj_save_to) return user_obj, None return None, _("Can not find any files!")
class ArticleNewForm(ArticleBaseForm): title = StringField(_("Title"), validators=[ validators.DataRequired(), validators.Length(min=2, max=128) ]) body = TextField(_("Body"), validators=[validators.DataRequired()])
def save_single_file(db, filedata, user): # TODO: fix me! tp = os.path.join(settings.OSS_PATH, str(user.uid)) if not os.path.isdir(tp): try: os.makedirs(tp) logging.info('create oss storage path: %s', tp) except Exception as e: logging.error('create oss path failed: %s', e) return None, _("Create OSS path failed!") for f in filedata: h = hashlib.sha1() h.update(f['body']) checksum = h.hexdigest() save_to = os.path.join(settings.OSS_PATH, "{0}".format(checksum)) # OOSObject 是否存在 obj = db.query(OSSObject).filter_by(checksum=checksum).first() if obj: logging.debug('OSSObject %s is existed, pass create', checksum) else: # 创建 obj try: open(save_to, 'wb').write(f['body']) logging.debug('save OSSObject %s success', save_to) except Exception as e: logging.error('save OSSObject failed: %s', e) return None, _("save OSSObject failed!") obj = OSSObject(size=len(f['body']), checksum=checksum) obj.uid = OSSObject.gen_uid(db) db.add(obj) db.commit() # OSSUserObject 关联是否存在 user_obj = db.query(OSSUserObject).filter( and_(OSSUserObject.user_id == user.id, OSSUserObject.obj_id == obj.id)).first() if user_obj: logging.warning('OSSUserObject %s is existed', user_obj.uid) else: # 创建用户关联 user_obj = OSSUserObject(user=user, obj=obj, filename=f['filename']) user_obj.uid = OSSUserObject.gen_uid(db) db.add(user_obj) db.commit() # 创建硬连接 user_obj_save_to = os.path.join(tp, "{0}_{1}".format(obj.checksum, user_obj.filename)) os.link(save_to, user_obj_save_to) return user_obj, None return None, _("Can not find any files!")
class TagBaseForm(Form): name = StringField(_("Name")) summary = TextField(_("Summary")) body = TextField(_("Body")) body_markup = SelectField(_("Body Markup"), coerce=int, choices=MARKUP_CHOICES, validators=[validators.optional()], default=1)
class ProfileEditForm(Form): """更新用户属性表单 """ nickname = StringField(_("Nickname")) first_name = StringField(_("First Name")) last_name = StringField(_("Last Name")) gender = SelectField(_('Gender'), choices=GENDER_CHOICES, default="secret") language = SelectField(_('Language'), choices=settings.LANGUAGES, default="en")
def get_order_obj(model, args): sort_by = args.get('sort_by') if sort_by != 'id' and sort_by not in model.__table__.columns: raise EvaError(_("unknown order_by: %s") % sort_by) sort_direction = args.get('sort_direction') if sort_direction not in ['asc', 'desc']: raise EvaError(_("unknown sort_direction: %s") % sort_direction) order_obj = desc(sort_by) if sort_direction == 'desc' else asc(sort_by) return order_obj
class PasswordResetForm(Form): """用户重置自己的密码 """ old_password = PasswordField( _("Old Password"), [validators.DataRequired(), validators.Length(min=6, max=64)]) new_password = PasswordField( _("New Password"), [validators.DataRequired(), validators.Length(min=6, max=64)])
def get_like_obj(model, args): like_k = args.get('like_k') if not like_k: return if like_k and like_k not in model.__table__.columns: raise EvaError(_("unknown like_k: %s") % like_k) like_v = args.get('like_v') if not like_v: raise EvaError(_("like_v is needed by like_k")) return getattr(model.__table__.columns, like_k).like("%" + like_v + "%")
def post(self): '''新建标签''' form = TagNewForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) tag = self.db.query(BlogTag).filter( and_( BlogTag.user_id == self.current_user.id, BlogTag.name == form.name.data )).first() if tag: return self.fail(_("tag exist")) tag = BlogTag( user=self.current_user, name=form.name.data, summary=form.summary.data, body=form.body.data, body_markup=form.body_markup.data ) tag.uid = BlogTag.gen_uid(self.db) self.db.add(tag) self.db.commit() self.success(id=tag.uid)
def post(self): print(self.request) if self.request.files and 'fileDataFileName' in self.request.files: filedata = self.request.files['fileDataFileName'] attachment, emsg = save_single_file(self.db, filedata, self.current_user) if attachment: d = { "success": True, "file_path": attachment.static_url, } else: d = { "success": False, "msg": emsg, } else: d = { "success": False, "msg": _("No files to upload!"), } # TODO: fix me! self.success(data=d)
def get_my_obj(self, model, uid): try: return self.db.query(model).filter( and_(model.user_id == self.current_user.id, model.uid == uid)).one() except NoResultFound: raise EvaError( _("can not find {0} with uid {1}").format( model.__tablename__, uid)) except MultipleResultsFound: # 不应该出现 raise EvaError( _("found duplicate objects for {0}").format( model.__tablename__))
def put(self, uid): '''更新标签''' form = TagEditForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) tag = self.tag if not form.name.is_missing: old_tag = self.db.query(BlogTag).filter( and_( BlogTag.user_id == self.current_user.id, BlogTag.name == form.name.data, BlogTag.uid != tag.uid # 不是本标签 )).first() if old_tag: return self.fail(_("tag exist")) tag.name = form.name.data if not form.body.is_missing: tag.body = form.body.data if not form.body_markup.is_missing: tag.body_markup = form.body_markup.data if not form.summary.is_missing: tag.summary = form.summary.data self.db.commit() self.success()
def post(self): '''新建类别''' form = CategoryNewForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) parent = None if not form.parent_id.is_missing: parent = self.db.query(BlogCategory).filter_by( uid=form.parent_id.data).first() if not parent: return self.fail( _("Can not find parent category {0}").format( form.parent_id.data)) category = BlogCategory(name=form.name.data, parent=parent, summary=form.summary.data, body=form.body.data, body_markup=form.body_markup.data) category.uid = BlogCategory.gen_uid(self.db) self.db.add(category) self.db.commit() self.success(uid=category.uid)
def post(self): '''新建类别''' form = CategoryNewForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) parent = None if not form.parent_id.is_missing: parent = self.db.query(BlogCategory).filter_by( uid=form.parent_id.data).first() if not parent: return self.fail(_("Can not find parent category {0}").format(form.parent_id.data)) category = BlogCategory( name=form.name.data, parent=parent, summary=form.summary.data, body=form.body.data, body_markup=form.body_markup.data ) category.uid = BlogCategory.gen_uid(self.db) self.db.add(category) self.db.commit() self.success(uid=category.uid)
class TagNewForm(TagBaseForm): name = StringField(_("Name"), validators=[ validators.DataRequired(), validators.Length(min=2, max=128) ])
def get_my_obj(self, model, uid): try: return self.db.query(model).filter( and_( model.user_id == self.current_user.id, model.uid == uid )).one() except NoResultFound: raise EvaError(_("can not find {0} with uid {1}").format( model.__tablename__, uid)) except MultipleResultsFound: # 不应该出现 raise EvaError( _("found duplicate objects for {0}").format(model.__tablename__))
def post(self): '''用户登录''' form = SignInForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) # support username login user = self.db.query(User).filter_by( username=form.username.data).first() # support email login if not user: user = self.db.query(User).filter_by( email=form.username.data).first() # support uid login if not user: try: UID = int(form.username.data) user = self.db.query(User).filter_by(uid=UID).first() except: pass if not user: return self.fail(_("Wrong username or password")) if user.is_locked: return self.fail(_("User is locked")) if not user.is_active: return self.fail(_("User is inactive")) if not user.check_password(form.password.data): return self.fail(_("Wrong username or password")) # 设置其他 user.last_login = datetime.datetime.utcnow() user.last_active = datetime.datetime.utcnow() # 验证成功 session = create_session( self.db, user, from_ip=self.request.remote_ip) self.require_setting("secret_key", "secure key") secret = self.application.settings["secret_key"] sid = create_signed_value( secret, "Sid", session.sid).decode() # TODO: fix me! self.success(sid=sid, expired=rfc3339_string(session.expired))
def post(self): '''用户登录''' form = SignInForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) # support username login user = self.db.query(User).filter_by( username=form.username.data).first() # support email login if not user: user = self.db.query(User).filter_by( email=form.username.data).first() # support uid login if not user: try: UID = int(form.username.data) user = self.db.query(User).filter_by(uid=UID).first() except: pass if not user: return self.fail(_("Wrong username or password")) if user.is_locked: return self.fail(_("User is locked")) if not user.is_active: return self.fail(_("User is inactive")) if not user.check_password(form.password.data): return self.fail(_("Wrong username or password")) # 设置其他 user.last_login = datetime.datetime.utcnow() user.last_active = datetime.datetime.utcnow() # 验证成功 session = create_session(self.db, user, from_ip=self.request.remote_ip) self.require_setting("secret_key", "secure key") secret = self.application.settings["secret_key"] sid = create_signed_value(secret, "Sid", session.sid).decode() # TODO: fix me! self.success(sid=sid, expired=rfc3339_string(session.expired))
def get(self, uid): '''查看文章''' article = self.db.query(BlogArticle).filter( and_(BlogArticle.uid == uid, BlogArticle.is_public == True)).first() if not article: return self.fail_404(_("No such article")) self.success(**article.iuser)
class BlogVote(UIDMixin, ORMBase): '''Blog 投票系统 1. 针对文章、评论的投票 2. 每个用户只能投票一次 3. 自己不能投自己 ''' TARGETS = ( (1, 'article', _('Article')), (2, 'comment', _('Comment')), ) __tablename__ = 'blog_vote' id = Column(Integer, Sequence('blog_vote_id_seq'), primary_key=True) target_id = Column(Integer, nullable=False) target_type = Column(Integer, nullable=False) user_id = Column(Integer, ForeignKey('auth_user.id')) user = relationship("User", backref="blog_article_votes") # 投票值 [-1, 1] vote = Column(Integer, nullable=False) created = Column(DateTime, default=datetime.datetime.utcnow) updated = Column(DateTime, default=datetime.datetime.utcnow) def __init__(self, user, vote, target): self.user_id = user.id self.vote = vote target_id = target.id if isinstance(target, BlogArticle): self.target_type = 1 elif isinstance(target, BlogComment): self.target_type = 2 target.to_vote(vote)
def delete(self, uid): '''删除目录''' # Can not delete non-empty catalog! if self.catalog.articles.count() > 0: return self.fail(_("there are articles in this catalog")) self.db.delete(self.catalog) self.db.commit() self.success()
def delete(self, uid): '''删除标签''' # Can not delete non-empty tag! if self.tag.articles.count("id") > 0: return self.fail(_("there are articles in this tag")) self.db.delete(self.tag) self.db.commit() self.success()
def get_limit_objects(handler, model, q, args): '''获取对象列表 通过过滤参数查询对象列表,如文章列表、用户列表 列表过滤参数有: - sort_by, sort_direction - like_k, like_v - after, before (表示位置, 参考 graphql) - limit (表示范围,对象个数) - TODO: 使用 page ? ''' # LIKE like_obj = get_like_obj(model, args) if like_obj is not None: q = q.filter(like_obj) # ORDER BY order_obj = get_order_obj(model, args) q = q.order_by(order_obj) # TODO: 检查 after , before 规则 # AFTER after = args.get('after') if after: I = handler.db.query(model).filter_by(uid=after).first() if I: q = q.filter(model.id > I.id) # BEFORE before = args.get('before') if before: I = handler.db.query(model).filter_by(uid=before).first() if I: q = q.filter(model.id < I.id) # LIMIT limit = args.get('page_size') # Start / Stop if not after and not before: p = args.get('current_page') if p < 1: raise EvaError(_("No such page!")) start = (p - 1) * limit stop = p * limit q = q.slice(start, stop) return q.limit(limit)
def get(self): '''用户注销''' if not self.current_user: return self.fail(_("You are not logined!")) # TODO: just delete current session! # Delete all old sessions, user need resignin. for s in self.current_user.sessions: self.db.delete(s) self.db.commit() self.success()
def post(self): '''获取注册验证码''' form = NewIdentifierForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) t = form.type.data d = form.data.data c = create_identifier(self.db, t, data=d) if t == "email": if len(d.split("@")) != 2: return self.fail(_("Invalid email address.")) to_addr = d.strip() if self.db.query(User.id).filter_by(email=to_addr).count() > 0: return self.fail(_("Email address is existed.")) identifier_notice_email(to_addr, c.code) return self.success(id=c.uuid) else: return self.fail(_("Unknown identifier type: {}").format(t))
def post(self): '''完成注册''' form = SignUpForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) identifier = self.db.query(AuthIdentifier).filter_by( uuid=form.identifier_id.data).first() if not identifier: return self.fail(_("No such identifier")) if identifier.code != form.identifier_code.data: return self.fail(_("Invalid identifier code")) if not identifier.is_valid(): return self.fail(_("Identifier is expired")) user = self.db.query(User).filter_by(email=identifier.data).first() if user: # TODO: should not got it! return self.fail(_("User is existed")) # create user user = create_user(self.db, password=form.password.data, email=identifier.data, nickname=form.nickname.data) if not user: # TODO: more info return self.fail(_("Create user failed")) # 删除验证码 self.db.delete(identifier) self.db.commit() # TODO: 直接返回 sid , 便于用户一步登录? self.success()
class JobNewForm(Form): platform = StringField("Platform") title = StringField("Title") body = TextField("Body") body_markup = SelectField( "Body Markup", coerce=int, choices=MARKUP_CHOICES, validators=[validators.optional()], default=1 ) url = StringField("URL") checksum = StringField("Checksum") price = IntegerField("Price") city = StringField("City") categories = FieldList(StringField( "Category List", [validators.Length(max=128)] )) roles = FieldList(StringField( "Role List", [validators.Length(max=128)] )) skills = FieldList(StringField( "Skill List", [validators.Length(max=128)] )) # TODO: 校验 UTC string release_date = StringField(_("Release Date")) expire_date = StringField(_("Expire Date"))
class ArticleBaseForm(Form): category_id = StringField(_("Category ID")) catalog_id = StringField(_("Catalog ID")) # FIXME: [validators.Optional(), validators.Length(min=8)] title = StringField(_("Title")) abstract = TextField(_("Abstract")) body = TextField(_("Body")) body_markup = SelectField(_("Body Markup"), coerce=int, choices=MARKUP_CHOICES, validators=[validators.optional()], default=1) is_public = BooleanField(_("Is Public"), default=False) tags = FieldList(StringField("Tag ID", [validators.Length(min=8)]))
def put(self): '''用户重置密码''' user = self.current_user form = PasswordResetForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) if not user.check_password(form.old_password.data): return self.fail(_("Old password is wrong.")) user.set_password(form.new_password.data) # TODO: 创建新 session , 方便重新登录? # Delete all old sessions, user need resignin. for s in user.sessions: self.db.delete(s) self.db.commit() self.success()
def post(self): '''新建标签''' form = TagNewForm.from_json(self.get_body_json()) if not form.validate(): return self.fail(errors=form.errors) tag = self.db.query(BlogTag).filter( and_(BlogTag.user_id == self.current_user.id, BlogTag.name == form.name.data)).first() if tag: return self.fail(_("tag exist")) tag = BlogTag(user=self.current_user, name=form.name.data, summary=form.summary.data, body=form.body.data, body_markup=form.body_markup.data) tag.uid = BlogTag.gen_uid(self.db) self.db.add(tag) self.db.commit() self.success(id=tag.uid)
# 网站标题 DEFAULT_HTML_TITLE = 'Y Web Framework -- The First Choice For Your Great Site.' # 是否启用 tornado 的 static 服务 # 生产环境中,通常由 nginx 等提供该服务 ENABLE_STATIC_SERVE = True # 安全 key SESSION_COOKIE_SECRET = "not set now!" # session 默认有效期为2天 SESSION_COOKIE_AGE = 2 * 24 * 3600 SUPPORTED_LANGUAGES = ('en_US', 'zh_CN') # 站点的 locale 目录 (除去 eva 和 apps 的 locale) LOCALE_PATHS = () SITE_TRANSLATION_FILES = ( '*.py', 'templates', ) PACKAGE_NAME = 'WEB' PACKAGE_VERSION = '1.0' from eva.utils.translation import ugettext_lazy as _ GENDER_CHOICES = ((1, _('Male')), (2, _('Female')), (0, _('Secret'))) DEFAULT_PAGE_SIZE = 12
# 是否启用 tornado 的 static 服务 # 生产环境中,通常由 nginx 等提供该服务 ENABLE_STATIC_SERVE = True # 安全 key SESSION_COOKIE_SECRET = "not set now!" # session 默认有效期为2天 SESSION_COOKIE_AGE = 2*24*3600 SUPPORTED_LANGUAGES = ('en_US', 'zh_CN') # 站点的 locale 目录 (除去 eva 和 apps 的 locale) LOCALE_PATHS = () SITE_TRANSLATION_FILES = ( '*.py', 'templates', ) PACKAGE_NAME = 'WEB' PACKAGE_VERSION = '1.0' from eva.utils.translation import ugettext_lazy as _ GENDER_CHOICES = ( (1, _('Male')), (2, _('Female')), (0, _('Secret')) ) DEFAULT_PAGE_SIZE = 12
from eva.orm import ORMBase from eva.utils.auth import enc_login_passwd, check_login_passwd from eva.utils.time_ import ( after_seconds, rfc3339_string ) from eva.utils.random_ import random_ascii, random_digit from eva.models.uuid import UUIDMixin from eva.conf import settings from eva.utils.translation import ugettext_lazy as _ from . import settings as auth_settings GENDER_CHOICES = ( ("male", _("Male")), ("female", _("Female")), ("secret", _("Secret")), ) user_groups = Table( 'auth_user__group', ORMBase.metadata, Column('user_id', Integer, ForeignKey('auth_user.id')), Column('group_id', Integer, ForeignKey('auth_group.id')) ) group_permissions = Table( 'auth_group__permission', ORMBase.metadata, Column('group_id', Integer, ForeignKey('auth_group.id')), Column('permission_id', Integer, ForeignKey('auth_permission.id')),
def uid(cls): return Column(String(8), nullable=False, unique=True, doc=_("Unique Identifier"))
from eva.utils.translation import ugettext_lazy as _ MARKUP_CHOICES = ( (1, _("Markdown")), (2, _("rst")), )
from eva.utils.translation import ugettext_lazy as _ MARKUP_CHOICES = ( (0, _("Txt")), (1, _("Markdown")), (2, _("rst")), )