By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.

Dismiss

 models.py

View raw Download
text/x-script.python • 11.79 kiB
Python script, ASCII text executable
        
            
1
from app import app, db
2
import git
3
from datetime import datetime
4
from enum import Enum
5
from PIL import Image
6
from cairosvg import svg2png
7
import os
8
import config
9
import bcrypt
10
import cairosvg
11
import random
12
13
__all__ = [
14
"RepoAccess",
15
"RepoFavourite",
16
"Repo",
17
"UserFollow",
18
"UserNotification",
19
"User",
20
"Notification",
21
"PostVote",
22
"Post",
23
"Commit",
24
]
25
26
with app.app_context():
27
class RepoAccess(db.Model):
28
id = db.Column(db.Integer, primary_key=True)
29
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
30
repoRoute = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
31
accessLevel = db.Column(db.SmallInteger(), nullable=False) # 0 read-only, 1 read-write, 2 admin
32
33
user = db.relationship("User", back_populates="repoAccess")
34
repo = db.relationship("Repo", back_populates="repoAccess")
35
36
__table_args__ = (db.UniqueConstraint("userUsername", "repoRoute", name="_user_repo_uc"),)
37
38
def __init__(self, user, repo, level):
39
self.userUsername = user.username
40
self.repoRoute = repo.route
41
self.accessLevel = level
42
43
44
class RepoFavourite(db.Model):
45
id = db.Column(db.Integer, primary_key=True)
46
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
47
repoRoute = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
48
49
user = db.relationship("User", back_populates="favourites")
50
repo = db.relationship("Repo", back_populates="favourites")
51
52
__table_args__ = (db.UniqueConstraint("userUsername", "repoRoute", name="_user_repo_uc1"),)
53
54
def __init__(self, user, repo):
55
self.userUsername = user.username
56
self.repoRoute = repo.route
57
58
59
class PostVote(db.Model):
60
id = db.Column(db.Integer, primary_key=True)
61
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
62
postIdentifier = db.Column(db.String(109), db.ForeignKey("post.identifier"), nullable=False)
63
voteScore = db.Column(db.SmallInteger(), nullable=False)
64
65
user = db.relationship("User", back_populates="votes")
66
post = db.relationship("Post", back_populates="votes")
67
68
__table_args__ = (db.UniqueConstraint("userUsername", "postIdentifier", name="_user_post_uc"),)
69
70
def __init__(self, user, post, score):
71
self.userUsername = user.username
72
self.postIdentifier = post.identifier
73
self.voteScore = score
74
75
76
class User(db.Model):
77
username = db.Column(db.String(32), unique=True, nullable=False, primary_key=True)
78
displayName = db.Column(db.Unicode(128), unique=False, nullable=True)
79
bio = db.Column(db.Unicode(512), unique=False, nullable=True)
80
passwordHashed = db.Column(db.String(60), nullable=False)
81
email = db.Column(db.String(254), nullable=True)
82
company = db.Column(db.Unicode(64), nullable=True)
83
companyURL = db.Column(db.String(256), nullable=True)
84
URL = db.Column(db.String(256), nullable=True)
85
showMail = db.Column(db.Boolean, default=False, nullable=False)
86
location = db.Column(db.Unicode(64), nullable=True)
87
creationDate = db.Column(db.DateTime, default=datetime.utcnow)
88
89
repositories = db.relationship("Repo", back_populates="owner")
90
followers = db.relationship("UserFollow", back_populates="followed", foreign_keys="[UserFollow.followedUsername]")
91
follows = db.relationship("UserFollow", back_populates="follower", foreign_keys="[UserFollow.followerUsername]")
92
repoAccess = db.relationship("RepoAccess", back_populates="user")
93
votes = db.relationship("PostVote", back_populates="user")
94
favourites = db.relationship("RepoFavourite", back_populates="user")
95
96
commits = db.relationship("Commit", back_populates="owner")
97
posts = db.relationship("Post", back_populates="owner")
98
notifications = db.relationship("UserNotification", back_populates="user")
99
100
def __init__(self, username, password, email=None, displayName=None):
101
self.username = username
102
self.passwordHashed = bcrypt.generate_password_hash(password, config.HASHING_ROUNDS).decode("utf-8")
103
self.email = email
104
self.displayName = displayName
105
106
# Create the user's directory
107
if not os.path.exists(os.path.join(config.REPOS_PATH, username)):
108
os.makedirs(os.path.join(config.REPOS_PATH, username))
109
if not os.path.exists(os.path.join(config.USERDATA_PATH, username)):
110
os.makedirs(os.path.join(config.USERDATA_PATH, username))
111
112
avatarName = random.choice(os.listdir(config.DEFAULT_AVATARS_PATH))
113
if os.path.join(config.DEFAULT_AVATARS_PATH, avatarName).endswith(".svg"):
114
cairosvg.svg2png(url=os.path.join(config.DEFAULT_AVATARS_PATH, avatarName),
115
write_to="/tmp/roundabout-avatar.png")
116
avatar = Image.open("/tmp/roundabout-avatar.png")
117
else:
118
avatar = Image.open(os.path.join(config.DEFAULT_AVATARS_PATH, avatarName))
119
avatar.thumbnail(config.AVATAR_SIZE)
120
avatar.save(os.path.join(config.USERDATA_PATH, username, "avatar.png"))
121
122
123
class Repo(db.Model):
124
route = db.Column(db.String(98), unique=True, nullable=False, primary_key=True)
125
ownerName = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
126
name = db.Column(db.String(64), nullable=False)
127
owner = db.relationship("User", back_populates="repositories")
128
visibility = db.Column(db.SmallInteger(), nullable=False)
129
info = db.Column(db.Unicode(512), nullable=True)
130
URL = db.Column(db.String(256), nullable=True)
131
creationDate = db.Column(db.DateTime, default=datetime.utcnow)
132
133
defaultBranch = db.Column(db.String(64), nullable=True, default="")
134
135
commits = db.relationship("Commit", back_populates="repo")
136
posts = db.relationship("Post", back_populates="repo")
137
repoAccess = db.relationship("RepoAccess", back_populates="repo")
138
favourites = db.relationship("RepoFavourite", back_populates="repo")
139
140
lastPostID = db.Column(db.Integer, nullable=False, default=0)
141
142
def __init__(self, owner, name, visibility):
143
self.route = f"/{owner.username}/{name}"
144
self.name = name
145
self.ownerName = owner.username
146
self.owner = owner
147
self.visibility = visibility
148
149
# Add the owner as an admin
150
repoAccess = RepoAccess(owner, self, 2)
151
db.session.add(repoAccess)
152
153
154
class Commit(db.Model):
155
identifier = db.Column(db.String(227), unique=True, nullable=False, primary_key=True)
156
sha = db.Column(db.String(128), nullable=False)
157
repoName = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
158
ownerName = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
159
ownerIdentity = db.Column(db.String(321))
160
receiveDate = db.Column(db.DateTime, default=datetime.now)
161
authorDate = db.Column(db.DateTime)
162
message = db.Column(db.UnicodeText)
163
repo = db.relationship("Repo", back_populates="commits")
164
owner = db.relationship("User", back_populates="commits")
165
166
def __init__(self, sha, owner, repo, date, message, ownerIdentity):
167
self.identifier = f"{repo.route}/{sha}"
168
self.sha = sha
169
self.repoName = repo.route
170
self.repo = repo
171
self.ownerName = owner.username
172
self.owner = owner
173
self.authorDate = datetime.fromtimestamp(int(date))
174
self.message = message
175
self.ownerIdentity = ownerIdentity
176
177
178
class Post(db.Model):
179
identifier = db.Column(db.String(109), unique=True, nullable=False, primary_key=True)
180
number = db.Column(db.Integer, nullable=False)
181
repoName = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
182
ownerName = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
183
votes = db.relationship("PostVote", back_populates="post")
184
voteSum = db.Column(db.Integer, nullable=False, default=0)
185
186
parentID = db.Column(db.String(109), db.ForeignKey("post.identifier"), nullable=True)
187
state = db.Column(db.SmallInteger, nullable=True, default=1)
188
189
date = db.Column(db.DateTime, default=datetime.now)
190
lastUpdated = db.Column(db.DateTime, default=datetime.now)
191
subject = db.Column(db.Unicode(384))
192
message = db.Column(db.UnicodeText)
193
repo = db.relationship("Repo", back_populates="posts")
194
owner = db.relationship("User", back_populates="posts")
195
parent = db.relationship("Post", back_populates="children", remote_side="Post.identifier")
196
children = db.relationship("Post", back_populates="parent", remote_side="Post.parentID")
197
198
def __init__(self, owner, repo, parent, subject, message):
199
self.identifier = f"{repo.route}/{repo.lastPostID}"
200
self.number = repo.lastPostID
201
self.repoName = repo.route
202
self.repo = repo
203
self.ownerName = owner.username
204
self.owner = owner
205
self.subject = subject
206
self.message = message
207
self.parent = parent
208
repo.lastPostID += 1
209
210
def updateDate(self):
211
self.lastUpdated = datetime.now()
212
with db.session.no_autoflush:
213
if self.parent is not None:
214
self.parent.updateDate()
215
216
217
class UserNotification(db.Model):
218
id = db.Column(db.Integer, primary_key=True)
219
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
220
notificationID = db.Column(db.BigInteger, db.ForeignKey("notification.id"))
221
attentionLevel = db.Column(db.SmallInteger, nullable=False) # 0 is read
222
readTime = db.Column(db.DateTime, nullable=True)
223
224
user = db.relationship("User", back_populates="notifications")
225
notification = db.relationship("Notification", back_populates="notifications")
226
227
__table_args__ = (db.UniqueConstraint("userUsername", "notificationID", name="_user_notification_uc"),)
228
229
def __init__(self, user, notification, level):
230
self.userUsername = user.username
231
self.notificationID = notification.id
232
self.attentionLevel = level
233
234
def read(self):
235
self.readTime = datetime.utcnow
236
self.attentionLevel = 0
237
238
239
class UserFollow(db.Model):
240
id = db.Column(db.Integer, primary_key=True)
241
followerUsername = db.Column(db.String(32), db.ForeignKey("user.username", ondelete="CASCADE"), nullable=False)
242
followedUsername = db.Column(db.String(32), db.ForeignKey("user.username", ondelete="CASCADE"), nullable=False)
243
244
follower = db.relationship("User", back_populates="follows", foreign_keys=[followedUsername])
245
followed = db.relationship("User", back_populates="followers", foreign_keys=[followerUsername])
246
247
def __init__(self, followerUsername, followedUsername):
248
self.followerUsername = followerUsername
249
self.followedUsername = followedUsername
250
251
252
class Notification(db.Model):
253
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
254
data = db.Column(db.dialects.postgresql.JSONB, nullable=False, default={})
255
notifications = db.relationship("UserNotification", back_populates="notification")
256
timestamp = db.Column(db.DateTime, nullable=False, default=datetime.now)
257
258
def __init__(self, json):
259
self.data = json
260
261
# def sendTo(self, users, level):
262
# for user in users:
263
# db.session.add(UserNotification(user, self, level))
264
265