Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""LICENSE
2Copyright 2020 Hermann Krumrey <hermann@krumreyh.com>
4This file is part of jerrycan.
6jerrycan is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
11jerrycan is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
16You should have received a copy of the GNU General Public License
17along with jerrycan. If not, see <http://www.gnu.org/licenses/>.
18LICENSE"""
20from typing import Optional, TYPE_CHECKING, List
21from jerrycan.Config import Config
22from jerrycan.base import db
23from jerrycan.db.IDModelMixin import IDModelMixin
24from puffotter.crypto import verify_password
25if TYPE_CHECKING: # pragma: no cover
26 from jerrycan.db.ApiKey import ApiKey
27 from jerrycan.db.TelegramChatId import TelegramChatId
30class User(IDModelMixin, db.Model):
31 """
32 Model that describes the 'users' SQL table
33 A User stores a user's information, including their email address, username
34 and password hash
35 """
37 __tablename__ = "users"
38 """
39 The name of the table
40 """
42 username: str = db.Column(
43 db.String(Config.MAX_USERNAME_LENGTH),
44 nullable=False,
45 unique=True
46 )
47 """
48 The user's username
49 """
51 email: str = db.Column(db.String(150), nullable=False, unique=True)
52 """
53 The user's email address
54 """
56 password_hash: str = db.Column(db.String(255), nullable=False)
57 """
58 The user's hashed password, salted and hashed.
59 """
61 confirmed: bool = db.Column(db.Boolean, nullable=False, default=False)
62 """
63 The account's confirmation status. Logins should be impossible as long as
64 this value is False.
65 """
67 confirmation_hash: str = db.Column(db.String(255), nullable=False)
68 """
69 The account's confirmation hash. This is the hash of a key emailed to
70 the user. Only once the user follows the link in the email containing the
71 key will their account be activated
72 """
74 telegram_chat_id: Optional["TelegramChatId"] = db.relationship(
75 "TelegramChatId",
76 uselist=False,
77 back_populates="user",
78 cascade="all, delete"
79 )
80 """
81 Telegram chat ID for the user if set up
82 """
84 api_keys: List["ApiKey"] = db.relationship(
85 "ApiKey", back_populates="user", cascade="all, delete"
86 )
87 """
88 API keys for this user
89 """
91 @property
92 def is_authenticated(self) -> bool:
93 """
94 Property required by flask-login
95 :return: True if the user is confirmed, False otherwise
96 """
97 return True
99 @property
100 def is_anonymous(self) -> bool:
101 """
102 Property required by flask-login
103 :return: True if the user is not confirmed, False otherwise
104 """
105 return not self.is_authenticated # pragma: no cover
107 @property
108 def is_active(self) -> bool:
109 """
110 Property required by flask-login
111 :return: True
112 """
113 return self.confirmed
115 def get_id(self) -> str:
116 """
117 Method required by flask-login
118 :return: The user's ID as a unicode string
119 """
120 return str(self.id)
122 def verify_password(self, password: str) -> bool:
123 """
124 Verifies a password against the password hash
125 :param password: The password to check
126 :return: True if the password matches, False otherwise
127 """
128 return verify_password(password, self.password_hash)
130 def verify_confirmation(self, confirmation_key: str) -> bool:
131 """
132 Verifies a confirmation key against the confirmation hash
133 :param confirmation_key: The key to check
134 :return: True if the key matches, False otherwise
135 """
136 return verify_password(confirmation_key, self.confirmation_hash)