class Game(db.Model): id = db.Column(db.Integer, primary_key=True) #accessname = db.Column(db.String(255), unique=True, nullable=True) status = db.Column(db.Integer, default=0) #1 if active, 0 if not active game_type_id = db.Column( db.Integer, db.ForeignKey("game_type.id", ondelete="SET NULL")) host_id = db.Column( db.Integer, db.ForeignKey( "player.id", ondelete="SET NULL")) #One of the players has to be a host tournament_id = db.Column( db.Integer, db.ForeignKey( "tournament.id", ondelete="SET NULL")) #Being part of a tournament is optional game_token = db.Column(db.String(20), unique=True, nullable=False) created_at = db.Column(db.DateTime, nullable=False, default=func.now()) finished_at = db.Column(db.DateTime) #Relationships to other models game_type = db.relationship("GameType", back_populates="game") host = db.relationship("Player", back_populates="game") scores = db.relationship("PlayerScore", cascade="all, delete-orphan", back_populates="game") tournament = db.relationship("Tournament", back_populates="game")
class Answer(BaseDateTimeModel): __tablename__ = 'answers' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) # noqa: A003 text = db.Column(db.Text(), nullable=False) is_approve = db.Column(db.Boolean, default=False) question_id = db.Column(db.Integer, db.ForeignKey('questions.id')) likes_count = db.Column(db.Integer, default=0, nullable=False) user_relation = db.relationship( 'AnswerUsersRelations', back_populates='answers', ) owner_id = db.Column(db.Integer, db.ForeignKey('users.id')) users = db.relationship('User', back_populates='answers') def update_likes_count(self, like_status: int, on_created=False): if on_created and like_status: self.likes_count += 1 elif on_created and not like_status: self.likes_count -= 1 elif not on_created and like_status: self.likes_count += 2 else: self.likes_count -= 2
class Player(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.VARCHAR(255), nullable=False, unique=True, index=True) score = db.relationship("PlayerScore", cascade="all, delete-orphan", back_populates="player") lboard = db.relationship("Leaderboard", cascade="all, delete-orphan", back_populates="player") game = db.relationship("Game", back_populates="host")
class Chapter(db.Model): __tablename__ = 'chapters' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer(), primary_key=True) # noqa: A003 name = db.Column(db.Text(), nullable=False) order_number = db.Column(db.Integer, nullable=False) questions = db.relationship('Question', back_populates='chapter') section_id = db.Column(db.Integer, db.ForeignKey('sections.id')) section = db.relationship('Section', back_populates='chapters')
class GameType(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255), unique=True, nullable=False) max_players = db.Column(db.Integer) min_players = db.Column(db.Integer) #Relationships to other models game = db.relationship("Game", back_populates="game_type") lboard = db.relationship("Leaderboard", cascade="all, delete-orphan", back_populates="game_type")
class TestCase(db.Model): """Question test cases set model.""" __tablename__ = 'test_cases' id = db.Column(db.Integer, primary_key=True) # noqa: A003 question_id = db.Column(db.Integer, db.ForeignKey('questions.id')) question = db.relationship('Question', back_populates='test_case') test_questions = db.relationship('TestQuestion', back_populates='test_case') def __str__(self): return f'Тесты для {self.question}'
class PlayerScore(db.Model): id = db.Column(db.Integer, primary_key=True) player_id = db.Column(db.Integer, db.ForeignKey("player.id", ondelete="CASCADE"), nullable=False) score = db.Column(db.Float(24)) game_id = db.Column(db.Integer, db.ForeignKey("game.id", ondelete="CASCADE"), nullable=False) #Relationships to other models player = db.relationship("Player", back_populates="score") game = db.relationship("Game", back_populates="scores") __table__args__ = (db.UniqueConstraint('player_id', 'game_id', '_player_id_game_id_uc'), )
class RequestsThemesModel(db.Model): __tablename__ = 'request_themes' id = db.Column(db.Text(length=36), default=lambda: str(uuid.uuid4()), primary_key=True) tag = db.Column(db.String(80), unique=True, nullable=False) requests = db.relationship("RequestModel", lazy="dynamic", cascade="all, delete-orphan") @classmethod def find_by_id(cls, _id: int) -> "RequestsThemesModel": return cls.query.filter_by(id=_id).first() @classmethod def find_by_tag(cls, tag: str) -> "RequestsThemesModel": return cls.query.filter_by(tag=tag).first() def turn_to_json(self) -> dict: return { "id": self.id, "tag": self.tag, "requests": [request.turn_to_json() for request in self.requests.all()] } def save_to_db(self): db.session.add(self) db.session.commit() def delete_from_db(self): db.session.delete(self) db.session.commit()
class AnswerUsersRelations(BaseDateTimeModel): __tablename__ = 'answer_users_relations' id = db.Column(db.Integer, primary_key=True) # noqa: A003 answer_id = db.Column( db.Integer, db.ForeignKey('answers.id'), ) answers = db.relationship( 'Answer', back_populates='user_relation', ) user_id = db.Column(db.Integer, db.ForeignKey('users.id')) user = db.relationship( 'User', back_populates='answer_relation', )
class Tournament(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255), unique=True, nullable=False) status = db.Column(db.Integer, default=0) created_at = db.Column(db.DateTime, nullable=False, default=func.now()) finished_at = db.Column(db.DateTime) game = db.relationship("Game", back_populates="tournament")
class Section(db.Model): __tablename__ = 'sections' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer(), primary_key=True) # noqa: A003 name = db.Column(db.Text(), nullable=False) order_number = db.Column(db.Integer, nullable=False) chapters = db.relationship('Chapter', back_populates='section')
class TestAnswer(db.Model): __tablename__ = 'test_answers' id = db.Column(db.Integer, primary_key=True) # noqa: A003 text = db.Column(db.Text, nullable=False) right = db.Column(db.Boolean, nullable=False, default=False) question_id = db.Column(db.Integer, db.ForeignKey('test_questions.id')) question = db.relationship('TestQuestion', back_populates='answers')
class Question(BaseDateTimeModel): __tablename__ = 'questions' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer(), primary_key=True) # noqa: A003 text = db.Column(db.Text(), nullable=False) order_number = db.Column(db.Integer, nullable=False) user = db.Column(db.Integer, db.ForeignKey('users.id')) answers = db.relationship( 'Answer', backref='questions', lazy='dynamic', ) chapter_id = db.Column(db.Integer, db.ForeignKey('chapters.id')) chapter = db.relationship( 'Chapter', back_populates='questions') test_case = db.relationship( 'TestCase', back_populates='question', uselist=False) def __str__(self): return f'Вопрос #{self.order_number} {self.text}'
class TestQuestion(db.Model): """Question for test case.""" __tablename__ = 'test_questions' id = db.Column(db.Integer, primary_key=True) # noqa: A003 text = db.Column(db.Text, nullable=False) question_type = db.Column(db.Integer, nullable=False) test_case_id = db.Column(db.Integer, db.ForeignKey('test_cases.id')) test_case = db.relationship('TestCase', back_populates='test_questions') user_relation = db.relationship( 'TestQuestionUserRelation', back_populates='test_question', ) answers = db.relationship('TestAnswer', back_populates='question') def __str__(self): slise_size = 50 return f'{self.text[:slise_size]}, тест кейс: {self.test_case}'
class Leaderboard(db.Model): id = db.Column(db.Integer, primary_key=True) player_id = db.Column(db.Integer, db.ForeignKey("player.id", ondelete="CASCADE"), nullable=False, index=True) game_type_id = db.Column(db.Integer, db.ForeignKey("game_type.id", ondelete="CASCADE"), nullable=False, index=True) wins = db.Column(db.Integer, nullable=False) losses = db.Column(db.Integer, nullable=False) #Relationships to other models game_type = db.relationship("GameType", back_populates="lboard") player = db.relationship("Player", back_populates="lboard") #every player_id and game_type_id combination is unique __table__args__ = (db.UniqueConstraint('player_id', 'game_type_id', '_player_id_game_type_id_uc'), )
class Answer(BaseDateTimeModel): __tablename__ = 'answers' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) # noqa: A003 text = db.Column(db.Text(), nullable=False) is_approve = db.Column(db.Boolean, default=False) question_id = db.Column(db.Integer, db.ForeignKey('questions.id')) likes_count = db.Column(db.Integer, default=0, nullable=False) user_relation = db.relationship( 'AnswerUsersRelations', back_populates='answers', )
class TestQuestionUserRelation(db.Model): """Relation with User and TestQuestion.""" __tablename__ = 'test_questions_users_relations' id = db.Column(db.Integer, primary_key=True) # noqa: A003 completed = db.Column(db.Boolean, nullable=False, default=False) test_question_id = db.Column( db.Integer, db.ForeignKey('test_questions.id'), ) test_question = db.relationship( 'TestQuestion', back_populates='user_relation', ) user_id = db.Column(db.Integer, db.ForeignKey('users.id')) user = db.relationship( 'User', back_populates='question_relation', ) def __str__(self): return f'Связь пользователя {self.user} и вопроса {self.test_question}'
class Chat(db.Model): """ Telegram chat. One user can have multiple chats. """ __tablename__ = "chats" # Columns id = db.Column(db.Integer, primary_key=True) telegram_id = db.Column( db.BigInteger, unique=True, index=True, nullable=False, comment="Unique ID to identificate chat in Telegram") type = db.Column(db.Enum(ChatType), nullable=False, comment="Type of Telegram chat") user_id = db.Column( db.Integer, db.ForeignKey("users.id"), nullable=False, comment="Through this chat message can be sent to this user") # Relationships user = db.relationship("User", back_populates="chats", uselist=False) def __repr__(self): return f"<Chat {self.id}>" @staticmethod def create_fake(user): """ Creates fake chat. :param user: User to associate created chat with. """ from faker import Faker fake = Faker() random_number = fake.pyint(min_value=1, max_value=10, step=1) result = Chat(user=user) result.telegram_id = fake.pyint(min_value=10000000, max_value=10000000000, step=1) result.type = (fake.random_element(list(ChatType)) if (random_number % 10 == 0) else ChatType.PRIVATE) return result
class Contact(db.Model): """ Contact Model """ id = db.Column(db.Integer, unique=True, primary_key=True, autoincrement=True) username = db.Column(db.String(50), nullable=False, unique=True) first_name = db.Column(db.String(250), nullable=False) last_name = db.Column(db.String(250), nullable=False) date_created = db.Column(db.DateTime(), nullable=False) emails = db.relationship('Email', backref='contact', cascade='all, delete, delete-orphan', single_parent=True) def __repr__(self): return f"<Contact(username='******')>"
class ConfirmationModel(db.Model): __tablename__ = 'confirmations' id = db.Column(db.String(50), primary_key=True) expire_at = db.Column(db.Integer, nullable=False) confirmed = db.Column(db.Boolean, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) user = db.relationship("UserModel") def __init__(self, user_id: int, **kwargs): super().__init__(**kwargs) self.user_id = user_id self.id = uuid4().hex self.expire_at = int(time.time()) + EXPIRATION_DELTA self.confirmed = False @property def expired(self) -> bool: return time.time() > self.expire_at def force_to_expire(self) -> None: if not self.expired: self.expire_at = time.time() self.save_to_db() @classmethod def find_by_id(cls, _id: str) -> "ConfirmationModel": return cls.query.filter_by(id=_id).first() def save_to_db(self) -> None: db.session.add(self) db.session.commit() def delete_from_db(self) -> None: db.session.add(self) db.session.commit()
class UserModel(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), nullable=False, unique=True, index=True) name = db.Column(db.String(80)) surname = db.Column(db.String(80)) profile_pic = db.Column(db.String(64), nullable=False, default="gg_default_profile_pic.png") locality = db.Column(db.String(120)) password = db.Column(db.String(80), nullable=False) email = db.Column(db.String(120), nullable=False, unique=True) sha_private = db.Column(db.String(256), nullable=False) # just for development balance = db.Column(db.Integer, default=0) second_fa_enabled = db.Column(db.Boolean, nullable=False, default=False) # MAY BE NOT PRODUCTION IMPLEMENTING token_2fa = db.Column(db.String(120)) confirmation = db.relationship( "ConfirmationModel", lazy="dynamic", cascade="all, delete-orphan" ) @property def most_recent_confirmation(self) -> "ConfirmationModel": return self.confirmation.order_by(db.desc(ConfirmationModel.expire_at)).first() def turn_to_json(self): return {"username": self.username, "id": self.id, "locality": self.locality, "profile_pic": self.profile_pic } @classmethod def find_by_id(cls, _id: int) -> "UserModel": return cls.query.get(_id) @classmethod def find_by_email(cls, email: str) -> "UserModel": return cls.query.filter_by(email=email).first() @classmethod def find_by_username(cls, username: str) -> "UserModel": return cls.query.filter_by(username=username).first() @classmethod # TODO: TESTING VERSION MAYBE def find_by_token_2fa(cls, token: str) -> "UserModel": return cls.query.filter_by(token_2fa=token).first() @classmethod def find_by_sha_token(cls, token: str) -> "UserModel": return cls.query.filter_by(sha_private=token).first() @classmethod def find_by_locality(cls, locality: str): pass def confirm(self) -> Response: link = request.url_root[0:-1] + url_for( "confirmation", confirmation_id=self.most_recent_confirmation.id ) subject = f"{response_quote('user_registration_confirmation_subject')}" text = f"{response_quote('user_registration_confirmation_text')} {link}" html = f'<html>{response_quote("user_registration_confirmation_text")}: <a href="{link}">{link}</a></html>' return MailGun.send_email_message([self.email], subject, text, html) def send_email_2fa_code(self, code: str) -> Response: subject = response_quote("email2fa_code_mail_subject") text = response_quote("email2fa_code_mail_text") html = f'<html>' \ f'{response_quote("email2fa_code_mail_text").format(EmailSecondFA.token_expiration_delta().seconds // 60)} ' \ f'<h4>{code}</h4></html>' return MailGun.send_email_message([self.email], subject, text, html) def save_to_db(self) -> None: db.session.add(self) db.session.commit() def delete_from_db(self) -> None: db.session.delete(self) db.session.commit()
class User(db.Model): # noqa: WPS230 __tablename__ = 'users' __table_args__ = {'extend_existing': True} def __init__( # noqa: S107 WPS211 self, login: str, email: str, password: str = '', firstname: str = '', middlename: str = '', lastname: str = '', image: str = '', gravatar: str = '', github_id: str = None, yandex_id: str = None, is_oauth: bool = False, is_superuser: bool = False, is_aproved: bool = False, ): self.login = login self.password = password self.email = email self.firstname = firstname self.middlename = middlename self.lastname = lastname self.image = image self.gravatar = gravatar self.github_id = github_id self.yandex_id = yandex_id self.is_oauth = is_oauth self.is_superuser = is_superuser self.is_aproved = is_aproved id = db.Column(db.Integer, primary_key=True) # noqa: A003 login = db.Column(db.String(), unique=True) password = db.Column(db.String()) email = db.Column(db.String(), unique=True) firstname = db.Column(db.String(), nullable=True) middlename = db.Column(db.String(), nullable=True) lastname = db.Column(db.String(), nullable=True) image = db.Column(db.String(), default=email, nullable=True) gravatar = db.Column( db.Enum('gravatar', 'face', ''), default='gravatar', name='avatar_type', nullable=True, ) github_id = db.Column(db.String(), nullable=True) yandex_id = db.Column(db.String(), nullable=True) is_oauth = db.Column(db.Boolean, default=False, nullable=False) is_superuser = db.Column(db.Boolean, default=False, nullable=False) is_aproved = db.Column(db.Boolean, default=False, nullable=True) db.relationship( # noqa: WPS604 'User', backref='users', lazy='dynamic', ) question_relation = db.relationship( 'TestQuestionUserRelation', back_populates='user', ) answer_relation = db.relationship( 'AnswerUsersRelations', back_populates='user', ) answers = db.relationship('Answer', back_populates='users', uselist=False) def __str__(self): return '{0} <id {1}>'.format(self.login, self.id) def avatar(self, size): # если нет строки с картинкой, используется email # и обновляется БД - теперь в картинке email if self.image is None: image_str = self.email User.query.filter_by(id=session['auth'].user.id).update( {'image': self.email}) db.session.commit() else: image_str = self.image if not self.gravatar or self.gravatar == 'gravatar': digest = md5(image_str.encode('utf-8')).hexdigest() image_str = f'{os.getenv("GRAVATAR_API")}{digest}?d=identicon&s={size}' if self.gravatar == 'face': image_str = f'{os.getenv("FACE_API")}{size}/{self.image}.png' return image_str def __repr__(self): return '<id {0}>'.format(self.id) @classmethod def hash_password(cls, password: str): return generate_password_hash(password=password) def check_password(self, password): if not self.password: return False return check_password_hash(self.password, password) def get_token_for_mail_aproved(self, expires_in=600): """Функция генерации токена. Она нужна для подтверждения регистрации пользователя через электронную почту expires_in - время действия токена в секундах """ return jwt.encode({ 'user_id': self.id, 'exp': time() + expires_in }, junior_app.config['SECRET_KEY'], algorithm='HS256').decode('utf-8') def get_oauth_dict(self): """Возвращает словарь сервисов OAuth, связанных с аккаунтом. Если не связан, то в качестве ключа пустота. """ backends = dict() user_data = self.__dict__ for backend in junior_app.config['OAUTH_BACKEND']: backends[backend] = user_data.get(f'{backend}_id', False) return backends @classmethod def verify_token_for_mail_aproved(cls, token): """Функция для проверки токена. Она нужна для подтверждения пользователя через электронную почту """ try: user_id = jwt.decode( token, junior_app.config['SECRET_KEY'], algorithms=['HS256'], )['user_id'] except jwt.ExpiredSignatureError: flash('Ссылка устарела') return redirect(url_for('auth.login')) try: user = User.query.get(user_id) except User.DoesNotExist(): return None user.is_aproved = True return user
class User(BaseModel): __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(100), nullable=False) password_hash = db.Column(db.Text, nullable=False) email = db.Column(db.String(200), unique=True, nullable=False) gender = db.Column(db.Integer, nullable=False) desc = db.Column(db.Text, nullable=False) credit = db.Column(db.Integer, nullable=False) role = db.Column(db.String(20), nullable=False) status = db.Column(db.Integer, nullable=False) created_time = db.Column(UTCDateTime(timezone=True), default=time_utcnow, nullable=False) updated_time = db.Column(UTCDateTime(timezone=True), default=time_utcnow, nullable=False) posts = db.relationship("Post", backref="user", lazy="dynamic") def __init__(self, username, password_hash, email, gender, *args, **kwargs): self.username = username self.password_hash = password_hash self.email = email self.gender = gender self.desc = '' self.credit = 0 self.role = 'user' self.status = 1 self.created_time = datetime.now() self.updated_time = datetime.now() if kwargs and kwargs['id']: self.id = kwargs['id'] # Properties @property def is_active(self): """ 用户状态是否有效 :return: """ return self.status == 1 @property def is_admin(self): """ 用户是否是管理员 :return: """ return self.role == 'admin' @classmethod def authenticate(cls, username, password): """ 用户认证 :param username: :param password: :return: """ session = db_session() user = session.query(User).filter_by(username=username).first() if user and user._verify_password(password): return user return None def all_posts(self): return Post.query.\ filter(Post.user_id == self.id).\ order_by(Post.id.desc()).all() def get_id(self): return self.id def _verify_password(self, password): """ 验证用户密码 :param password: :return: """ return check_password_hash(self.password_hash, password)
class Post(db.Model): __tablename__ = 'posts' id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(128), nullable=False) description = db.Column(db.Text, nullable=False) contents = db.Column(db.Text, nullable=False) tags = db.Column(ARRAY(db.String)) comments = db.relationship( 'Comment', backref='post', lazy='dynamic', cascade='save-update, merge, delete, delete-orphan') owner_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) favorited_by = db.relationship( 'User', secondary=favorites_assoc, backref=db.backref('favorites', lazy='dynamic'), # Eager load the users who favorited this post using an # additional SELECT IN query lazy='selectin') created_at = db.Column(db.DateTime, nullable=False, default=dt.datetime.now) modified_at = db.Column(db.DateTime, nullable=False, default=dt.datetime.now) def save(self): self.modified_at = dt.datetime.now() db.session.add(self) db.session.commit() def update(self, **kwargs): for attr, value in kwargs.items(): setattr(self, attr, value) self.save() def delete(self): db.session.delete(self) db.session.commit() def favorite(self, user): self.favorited_by.append(user) self.save() def unfavorite(self, user): try: self.favorited_by.remove(user) self.save() except ValueError: pass @staticmethod def get_all(): return Post.query.all() @staticmethod def get_one(_id): return Post.query.get(_id) @hybrid_property def favorites_count(self): return len(self.favorited_by) def __repr__(self): return f"<id {self.id}>"
class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128), nullable=False) bio = db.Column(db.String(300), nullable=True) username = db.Column(db.String(128), nullable=False, unique=True) email = db.Column(db.String(128), unique=True, nullable=False) password = db.Column(db.String(128), nullable=True) avatar = db.Column(db.String(300), nullable=True) posts = db.relationship( 'Post', # Eager load the author of each post using an INNER JOIN # NOTE: joined loading is more commonly used to load # many-to-one not null relationships, not collections backref=db.backref('author', lazy='joined', innerjoin=True), lazy='dynamic') comments = db.relationship( 'Comment', # Eager load the author of each comment using an INNER JOIN backref=db.backref('author', lazy='joined', innerjoin=True), lazy=True) created_at = db.Column(db.DateTime, nullable=False, default=dt.datetime.now) modified_at = db.Column(db.DateTime, nullable=False, default=dt.datetime.now) def __init__(self, name, username, email, password, bio='', avatar=''): self.name = name self.email = email self.username = username self.bio = bio self.avatar = avatar self.set_password(password) def save(self): self.modified_at = dt.datetime.now() db.session.add(self) db.session.commit() def update(self, **kwargs): for attr, value in kwargs.items(): if attr == 'password': self.set_password(value) else: setattr(self, attr, value) self.save() def delete(self): db.session.delete(self) db.session.commit() @staticmethod def get_all(): return User.query.all() @staticmethod def get_one(_id): return User.query.get(_id) @staticmethod def get_by_email(email): return User.query.filter_by(email=email).first() @staticmethod def get_by_username(username): return User.query.filter_by(username=username).first() @property def picture(self): if self.avatar: return url_for('static', filename=f"uploads/{self.avatar}", _external=True) return None def set_password(self, password): self.password = bcrypt.generate_password_hash( password, rounds=10).decode('utf-8') def check_hash(self, password): return bcrypt.check_password_hash(self.password, password) def __repr__(self): return f"<id {self.id}>"
class User(db.Model): # noqa: WPS230 __tablename__ = 'users' __table_args__ = {'extend_existing': True} def __init__( # noqa: S107 WPS211 self, login: str, email: str, password: str = '', firstname: str = '', middlename: str = '', lastname: str = '', image: bytes = '', github_id: str = None, is_oauth: bool = False, is_superuser: bool = False, is_aproved: bool = False, ): self.login = login self.password = password self.email = email self.firstname = firstname self.middlename = middlename self.lastname = lastname self.image = image self.github_id = github_id self.is_oauth = is_oauth self.is_superuser = is_superuser self.is_aproved = is_aproved id = db.Column(db.Integer, primary_key=True) # noqa: A003 login = db.Column(db.String(), unique=True) password = db.Column(db.String()) email = db.Column(db.String(), unique=True) firstname = db.Column(db.String(), nullable=True) middlename = db.Column(db.String(), nullable=True) lastname = db.Column(db.String(), nullable=True) image = db.Column(db.String(), nullable=True) github_id = db.Column(db.String(), nullable=True) is_oauth = db.Column(db.Boolean, default=False, nullable=False) is_superuser = db.Column(db.Boolean, default=False, nullable=False) is_aproved = db.Column(db.Boolean, default=False, nullable=True) db.relationship( # noqa: WPS604 'User', backref='users', lazy='dynamic', ) question_relation = db.relationship( 'TestQuestionUserRelation', back_populates='user', ) def __str__(self): return '{0} <id {1}>'.format(self.login, self.id) def avatar(self, size): if self.image is None: image_str = self.email User.query.filter_by(id=self.context['auth'].user.id).update( {'image': self.email}) db.session.commit() else: image_str = self.image digest = md5(image_str.encode('utf-8')).hexdigest() return f'https://www.gravatar.com/avatar/{digest}?d=identicon&s={size}' def __repr__(self): return '<id {0}>'.format(self.id) @classmethod def hash_password(cls, password: str): return generate_password_hash(password=password) def check_password(self, password): if not self.password: return False return check_password_hash(self.password, password) def get_token_for_mail_aproved(self, expires_in=600): """Функция генерации токена. Она нужна для подтверждения регистрации пользователя через электронную почту expires_in - время действия токена в секундах """ return jwt.encode({ 'user_id': self.id, 'exp': time() + expires_in }, junior_app.config['SECRET_KEY'], algorithm='HS256').decode('utf-8') @classmethod def verify_token_for_mail_aproved(cls, token): """Функция для проверки токена. Она нужна для подтверждения пользователя через электронную почту """ try: user_id = jwt.decode( token, junior_app.config['SECRET_KEY'], algorithms=['HS256'], )['user_id'] except jwt.ExpiredSignatureError: flash('Ссылка устарела') return redirect(url_for('auth.login')) try: user = User.query.get(user_id) except User.DoesNotExist(): return None user.is_aproved = True return user