]> git.lizzy.rs Git - cheatdb.git/blob - app/models.py
67adcbf9574a7ad68cad7db80c7b7b0da9d89f13
[cheatdb.git] / app / models.py
1 from flask import Flask, url_for
2 from flask_sqlalchemy import SQLAlchemy
3 from app import app
4 from datetime import datetime
5 from sqlalchemy.orm import validates
6 from flask_user import login_required, UserManager, UserMixin, SQLAlchemyAdapter
7 import enum
8
9 # Initialise database
10 db = SQLAlchemy(app)
11
12
13 class UserRank(enum.Enum):
14         NOT_JOINED = 0
15         NEW_MEMBER = 1
16         MEMBER     = 2
17         EDITOR     = 3
18         MODERATOR  = 4
19         ADMIN      = 5
20
21         def atLeast(self, min):
22                 return self.value >= min.value
23
24         def getTitle(self):
25                 return self.name.replace("_", " ").title()
26
27
28 class Permission(enum.Enum):
29         EDIT_PACKAGE    = "EDIT_PACKAGE"
30         APPROVE_CHANGES = "APPROVE_CHANGES"
31         DELETE_PACKAGE  = "DELETE_PACKAGE"
32         CHANGE_AUTHOR   = "CHANGE_AUTHOR"
33         APPROVE_RELEASE = "APPROVE_RELEASE"
34         APPROVE_NEW     = "APPROVE_NEW"
35
36
37 class User(db.Model, UserMixin):
38         id = db.Column(db.Integer, primary_key=True)
39
40         # User authentication information
41         username = db.Column(db.String(50), nullable=False, unique=True)
42         password = db.Column(db.String(255), nullable=False, server_default='')
43         reset_password_token = db.Column(db.String(100), nullable=False, server_default='')
44
45         rank = db.Column(db.Enum(UserRank))
46
47         # Account linking
48         github_username = db.Column(db.String(50), nullable=True, unique=True)
49         forums_username = db.Column(db.String(50), nullable=True, unique=True)
50
51         # User email information
52         email = db.Column(db.String(255), nullable=True, unique=True)
53         confirmed_at = db.Column(db.DateTime())
54
55         # User information
56         active = db.Column('is_active', db.Boolean, nullable=False, server_default='0')
57         display_name = db.Column(db.String(100), nullable=False, server_default='')
58
59         # Content
60         packages = db.relationship('Package', backref='author', lazy='dynamic')
61
62         def __init__(self, username):
63                 import datetime
64
65                 self.username = username
66                 self.confirmed_at = datetime.datetime.now() - datetime.timedelta(days=6000)
67                 self.display_name = username
68                 self.rank = UserRank.NOT_JOINED
69
70         def isClaimed(self):
71                 return self.password is not None and self.password != ""
72
73 class PackageType(enum.Enum):
74         MOD  = "Mod"
75         GAME = "Game"
76         TXP  = "Texture Pack"
77
78         def toName(self):
79                 return self.name.lower()
80
81         def __str__(self):
82                 return self.name
83
84         @classmethod
85         def choices(cls):
86                 return [(choice, choice.value) for choice in cls]
87
88         @classmethod
89         def coerce(cls, item):
90                 return item if type(item) == PackageType else PackageType[item]
91
92 class Package(db.Model):
93         id           = db.Column(db.Integer, primary_key=True)
94
95         # Basic details
96         author_id    = db.Column(db.Integer, db.ForeignKey('user.id'))
97         name         = db.Column(db.String(100), nullable=False)
98         title        = db.Column(db.String(100), nullable=False)
99         shortDesc    = db.Column(db.Text, nullable=True)
100         desc         = db.Column(db.Text, nullable=True)
101         type         = db.Column(db.Enum(PackageType))
102
103         # Downloads
104         repo         = db.Column(db.String(200), nullable=True)
105         website      = db.Column(db.String(200), nullable=True)
106         issueTracker = db.Column(db.String(200), nullable=True)
107         forums       = db.Column(db.String(200), nullable=False)
108
109         def getDetailsURL(self):
110                 return url_for("package_page",
111                                 type=self.type.toName(),
112                                 author=self.author.username, name=self.name)
113
114         def getEditURL(self):
115                 return url_for("edit_package_page",
116                                 type=self.type.toName(),
117                                 author=self.author.username, name=self.name)
118
119         def checkPerm(self, user, perm):
120                 if not user.is_authenticated:
121                         return False
122
123                 if type(perm) == str:
124                         perm = Permission[perm]
125                 elif type(perm) != Permission:
126                         raise Exception("Unknown permission given to Package.checkPerm()")
127
128                 isOwner = user == self.author
129
130                 # Members can edit their own packages, and editors can edit any packages
131                 if perm == Permission.EDIT_PACKAGE or perm == Permission.APPROVE_CHANGES:
132                         return user.rank.atLeast(UserRank.MEMBER if isOwner else UserRank.EDITOR)
133
134                 # Editors can change authors, approve new packages, and approve releases
135                 elif perm == Permission.CHANGE_AUTHOR or perm == Permission.APPROVE_NEW \
136                                 or perm == Permission.APPROVE_RELEASE:
137                         return user.rank.atLeast(UserRank.EDITOR)
138
139                 # Moderators can delete packages
140                 elif perm == Permission.DELETE_PACKAGE:
141                         return user.rank.atLeast(UserRank.MODERATOR)
142
143                 else:
144                         raise Exception("Permission {} is not related to packages".format(perm.name))
145
146 # Setup Flask-User
147 db_adapter = SQLAlchemyAdapter(db, User)        # Register the User model
148 user_manager = UserManager(db_adapter, app)     # Initialize Flask-User