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