-
Notifications
You must be signed in to change notification settings - Fork 37
/
models.py
141 lines (129 loc) · 4.67 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
from datetime import datetime
import jwt
from fittrackee_api import bcrypt, db
from flask import current_app
from sqlalchemy import func
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.sql.expression import select
from ..activities.models import Activity
from .utils_token import decode_user_token, get_user_token
class User(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(255), nullable=False)
created_at = db.Column(db.DateTime, nullable=False)
admin = db.Column(db.Boolean, default=False, nullable=False)
first_name = db.Column(db.String(80), nullable=True)
last_name = db.Column(db.String(80), nullable=True)
birth_date = db.Column(db.DateTime, nullable=True)
location = db.Column(db.String(80), nullable=True)
bio = db.Column(db.String(200), nullable=True)
picture = db.Column(db.String(255), nullable=True)
timezone = db.Column(db.String(50), nullable=True)
# does the week start Monday?
weekm = db.Column(db.Boolean(50), default=False, nullable=False)
activities = db.relationship(
'Activity', lazy=True, backref=db.backref('user', lazy='joined')
)
records = db.relationship(
'Record', lazy=True, backref=db.backref('user', lazy='joined')
)
language = db.Column(db.String(50), nullable=True)
def __repr__(self):
return f'<User {self.username!r}>'
def __init__(
self, username, email, password, created_at=datetime.utcnow()
):
self.username = username
self.email = email
self.password = bcrypt.generate_password_hash(
password, current_app.config.get('BCRYPT_LOG_ROUNDS')
).decode()
self.created_at = created_at
@staticmethod
def encode_auth_token(user_id):
"""
Generates the auth token
:param user_id: -
:return: JWToken
"""
try:
return get_user_token(user_id)
except Exception as e:
return e
@staticmethod
def encode_password_reset_token(user_id):
"""
Generates the auth token
:param user_id: -
:return: JWToken
"""
try:
return get_user_token(user_id, password_reset=True)
except Exception as e:
return e
@staticmethod
def decode_auth_token(auth_token):
"""
Decodes the auth token
:param auth_token: -
:return: integer|string
"""
try:
return decode_user_token(auth_token)
except jwt.ExpiredSignatureError:
return 'Signature expired. Please log in again.'
except jwt.InvalidTokenError:
return 'Invalid token. Please log in again.'
@hybrid_property
def activities_count(self):
return Activity.query.filter(Activity.user_id == self.id).count()
@activities_count.expression
def activities_count(self):
return (
select([func.count(Activity.id)])
.where(Activity.user_id == self.id)
.label("activities_count")
)
def serialize(self):
sports = []
total = (None, None)
if self.activities_count > 0:
sports = (
db.session.query(Activity.sport_id)
.filter(Activity.user_id == self.id)
.group_by(Activity.sport_id)
.order_by(Activity.sport_id)
.all()
)
total = (
db.session.query(
func.sum(Activity.distance), func.sum(Activity.duration)
)
.filter(Activity.user_id == self.id)
.first()
)
return {
'username': self.username,
'email': self.email,
'created_at': self.created_at,
'admin': self.admin,
'first_name': self.first_name,
'last_name': self.last_name,
'bio': self.bio,
'location': self.location,
'birth_date': self.birth_date,
'picture': self.picture is not None,
'timezone': self.timezone,
'weekm': self.weekm,
'language': self.language,
'nb_activities': self.activities_count,
'nb_sports': len(sports),
'sports_list': [
sport for sportslist in sports for sport in sportslist
],
'total_distance': float(total[0]) if total[0] else 0,
'total_duration': str(total[1]) if total[1] else "0:00:00",
}