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