2018-07-03 06:22:58 +00:00
|
|
|
# Calendar.social
|
|
|
|
# Copyright (C) 2018 Gergely Polonkai
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU Affero General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
"""Database models for Calendar.social
|
|
|
|
"""
|
|
|
|
|
2018-06-28 12:41:14 +00:00
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
from flask_security import UserMixin, RoleMixin
|
|
|
|
from flask_sqlalchemy import SQLAlchemy
|
|
|
|
|
|
|
|
db = SQLAlchemy()
|
|
|
|
users_roles = db.Table(
|
|
|
|
'users_roles',
|
|
|
|
db.Column('user_id', db.Integer(), db.ForeignKey('users.id')),
|
|
|
|
db.Column('role_id', db.Integer(), db.ForeignKey('roles.id')))
|
|
|
|
|
|
|
|
|
|
|
|
class User(db.Model, UserMixin):
|
2018-07-03 06:22:58 +00:00
|
|
|
"""Database model for users
|
|
|
|
"""
|
|
|
|
|
2018-06-28 12:41:14 +00:00
|
|
|
__tablename__ = 'users'
|
|
|
|
id = db.Column(db.Integer(), primary_key=True)
|
|
|
|
|
|
|
|
#: The username of the user. This is also the display name and thus is immutable
|
|
|
|
username = db.Column(db.String(length=50), unique=True, nullable=False)
|
|
|
|
|
|
|
|
#: The email address of the user
|
|
|
|
email = db.Column(db.String(length=255), unique=True, nullable=True)
|
|
|
|
|
|
|
|
#: The (hashed) password of the user
|
|
|
|
password = db.Column(db.String(length=255))
|
|
|
|
|
|
|
|
#: A flag to show whether the user is enabled (active) or not
|
|
|
|
active = db.Column(db.Boolean(), default=False)
|
|
|
|
|
|
|
|
#: The timestamp when this user was created
|
|
|
|
created_at = db.Column(db.DateTime(), default=datetime.utcnow)
|
|
|
|
|
|
|
|
#: The timestamp when the user was activated
|
|
|
|
confirmed_at = db.Column(db.DateTime())
|
|
|
|
|
|
|
|
#: The roles of the user
|
|
|
|
roles = db.relationship('Role',
|
|
|
|
secondary=users_roles,
|
|
|
|
backref=db.backref('users', lazy='dynamic'))
|
|
|
|
|
2018-06-29 11:24:54 +00:00
|
|
|
def __repr__(self):
|
2018-06-28 12:41:14 +00:00
|
|
|
return f'<User {self.id}({self.username})>'
|
|
|
|
|
|
|
|
|
|
|
|
class Role(db.Model, RoleMixin):
|
2018-07-03 06:22:58 +00:00
|
|
|
"""Database model for roles
|
|
|
|
"""
|
|
|
|
|
2018-06-28 12:41:14 +00:00
|
|
|
__tablename__ = 'roles'
|
|
|
|
id = db.Column(db.Integer(), primary_key=True)
|
|
|
|
|
|
|
|
#: The name of the role
|
|
|
|
name = db.Column(db.Unicode(length=80), unique=True)
|
|
|
|
|
|
|
|
#: A description of the role
|
|
|
|
description = db.Column(db.UnicodeText)
|
2018-06-29 11:24:54 +00:00
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return f'<Role {self.id}({self.name})>'
|
2018-06-29 11:25:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Event(db.Model):
|
2018-07-03 06:22:58 +00:00
|
|
|
"""Database model for events
|
|
|
|
"""
|
|
|
|
|
2018-06-29 11:25:09 +00:00
|
|
|
__tablename__ = 'events'
|
|
|
|
id = db.Column(db.Integer(), primary_key=True)
|
|
|
|
|
|
|
|
#: The ID of the user who created the event
|
|
|
|
user_id = db.Column(db.Integer(), db.ForeignKey('users.id'), nullable=False)
|
|
|
|
|
|
|
|
user = db.relationship('User', backref=db.backref('events', lazy='dynamic'))
|
|
|
|
|
|
|
|
#: The title of the event
|
|
|
|
title = db.Column(db.Unicode(length=200), nullable=False)
|
|
|
|
|
|
|
|
#: The time zone to be used for `start_time` and `end_time`
|
|
|
|
time_zone = db.Column(db.String(length=80), nullable=False)
|
|
|
|
|
2018-07-03 06:22:58 +00:00
|
|
|
#: The starting timestamp of the event. It is in the UTC time zone
|
2018-06-29 11:25:09 +00:00
|
|
|
start_time = db.Column(db.DateTime(), nullable=False)
|
|
|
|
|
2018-07-03 06:22:58 +00:00
|
|
|
#: The ending timestamp of the event. It is in the UTC time zone
|
2018-06-29 11:25:09 +00:00
|
|
|
end_time = db.Column(db.DateTime(), nullable=False)
|
|
|
|
|
|
|
|
#: If `True`, the event is a whole-day event
|
|
|
|
all_day = db.Column(db.Boolean(), default=False)
|
|
|
|
|
|
|
|
#: The description of the event
|
|
|
|
description = db.Column(db.UnicodeText())
|
|
|
|
|
2018-07-03 10:03:54 +00:00
|
|
|
def __as_tz(self, timestamp, as_timezone=None):
|
|
|
|
from pytz import timezone, UTC
|
2018-07-02 13:07:53 +00:00
|
|
|
|
2018-07-03 10:03:54 +00:00
|
|
|
utc_timestamp = UTC.localize(timestamp)
|
|
|
|
|
|
|
|
return utc_timestamp.astimezone(as_timezone or timezone(self.time_zone))
|
2018-07-02 13:07:53 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def start_time_tz(self):
|
2018-07-03 06:22:58 +00:00
|
|
|
"""The same timestamp as `start_time`, but in the time zone specified by `time_zone`.
|
|
|
|
"""
|
|
|
|
|
2018-07-02 13:07:53 +00:00
|
|
|
return self.__as_tz(self.start_time)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def end_time_tz(self):
|
2018-07-03 06:22:58 +00:00
|
|
|
"""The same timestamp as `end_time`, but in the time zone specified by `time_zone`.
|
|
|
|
"""
|
|
|
|
|
2018-07-02 13:07:53 +00:00
|
|
|
return self.__as_tz(self.end_time)
|
|
|
|
|
2018-06-29 11:25:09 +00:00
|
|
|
def __repr__(self):
|
|
|
|
return f'<Event {self.id} ({self.title}) of {self.user}>'
|