roundabout,
created on Monday, 25 December 2023, 15:50:49 (1703519449),
received on Wednesday, 31 July 2024, 06:54:40 (1722408880)
Author identity: vlad <vlad.muntoiu@gmail.com>
872b642119b0343f8066d3e056802c04959d3d4c
app.py
@@ -33,6 +33,7 @@ app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
migrate = Migrate(app, db)
from models import *
def gitCommand(repo, data, *args):
@@ -60,194 +61,6 @@ def onlyChars(string, chars):
return True
with app.app_context():
class RepoAccess(db.Model):
id = db.Column(db.Integer, primary_key=True)
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
repoRoute = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
accessLevel = db.Column(db.SmallInteger(), nullable=False) # 0 read-only, 1 read-write, 2 admin
user = db.relationship("User", back_populates="repoAccess")
repo = db.relationship("Repo", back_populates="repoAccess")
__table_args__ = (db.UniqueConstraint("userUsername", "repoRoute", name="_user_repo_uc"),)
def __init__(self, user, repo, level):
self.userUsername = user.username
self.repoRoute = repo.route
self.accessLevel = level
class RepoFavourite(db.Model):
id = db.Column(db.Integer, primary_key=True)
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
repoRoute = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
user = db.relationship("User", back_populates="favourites")
repo = db.relationship("Repo", back_populates="favourites")
__table_args__ = (db.UniqueConstraint("userUsername", "repoRoute", name="_user_repo_uc1"),)
def __init__(self, user, repo):
self.userUsername = user.username
self.repoRoute = repo.route
class PostVote(db.Model):
id = db.Column(db.Integer, primary_key=True)
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
postIdentifier = db.Column(db.String(109), db.ForeignKey("post.identifier"), nullable=False)
voteScore = db.Column(db.SmallInteger(), nullable=False)
user = db.relationship("User", back_populates="votes")
post = db.relationship("Post", back_populates="votes")
__table_args__ = (db.UniqueConstraint("userUsername", "postIdentifier", name="_user_post_uc"),)
def __init__(self, user, post, score):
self.userUsername = user.username
self.postIdentifier = post.identifier
self.voteScore = score
class User(db.Model):
username = db.Column(db.String(32), unique=True, nullable=False, primary_key=True)
displayName = db.Column(db.Unicode(128), unique=False, nullable=True)
bio = db.Column(db.Unicode(512), unique=False, nullable=True)
passwordHashed = db.Column(db.String(60), nullable=False)
email = db.Column(db.String(254), nullable=True)
company = db.Column(db.Unicode(64), nullable=True)
companyURL = db.Column(db.String(256), nullable=True)
URL = db.Column(db.String(256), nullable=True)
showMail = db.Column(db.Boolean, default=False, nullable=False)
location = db.Column(db.Unicode(64), nullable=True)
creationDate = db.Column(db.DateTime, default=datetime.utcnow)
repositories = db.relationship("Repo", back_populates="owner")
repoAccess = db.relationship("RepoAccess", back_populates="user")
votes = db.relationship("PostVote", back_populates="user")
favourites = db.relationship("RepoFavourite", back_populates="user")
commits = db.relationship("Commit", back_populates="owner")
posts = db.relationship("Post", back_populates="owner")
def __init__(self, username, password, email=None, displayName=None):
self.username = username
self.passwordHashed = bcrypt.generate_password_hash(password, config.HASHING_ROUNDS).decode("utf-8")
self.email = email
self.displayName = displayName
# Create the user's directory
if not os.path.exists(os.path.join(config.REPOS_PATH, username)):
os.makedirs(os.path.join(config.REPOS_PATH, username))
if not os.path.exists(os.path.join(config.USERDATA_PATH, username)):
os.makedirs(os.path.join(config.USERDATA_PATH, username))
avatarName = random.choice(os.listdir(config.DEFAULT_AVATARS_PATH))
if os.path.join(config.DEFAULT_AVATARS_PATH, avatarName).endswith(".svg"):
cairosvg.svg2png(url=os.path.join(config.DEFAULT_AVATARS_PATH, avatarName),
write_to="/tmp/roundabout-avatar.png")
avatar = Image.open("/tmp/roundabout-avatar.png")
else:
avatar = Image.open(os.path.join(config.DEFAULT_AVATARS_PATH, avatarName))
avatar.thumbnail(config.AVATAR_SIZE)
avatar.save(os.path.join(config.USERDATA_PATH, username, "avatar.png"))
class Repo(db.Model):
route = db.Column(db.String(98), unique=True, nullable=False, primary_key=True)
ownerName = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
name = db.Column(db.String(64), nullable=False)
owner = db.relationship("User", back_populates="repositories")
visibility = db.Column(db.SmallInteger(), nullable=False)
info = db.Column(db.Unicode(512), nullable=True)
URL = db.Column(db.String(256), nullable=True)
creationDate = db.Column(db.DateTime, default=datetime.utcnow)
defaultBranch = db.Column(db.String(64), nullable=True, default="")
commits = db.relationship("Commit", back_populates="repo")
posts = db.relationship("Post", back_populates="repo")
repoAccess = db.relationship("RepoAccess", back_populates="repo")
favourites = db.relationship("RepoFavourite", back_populates="repo")
lastPostID = db.Column(db.Integer, nullable=False, default=0)
def __init__(self, owner, name, visibility):
self.route = f"/{owner.username}/{name}"
self.name = name
self.ownerName = owner.username
self.owner = owner
self.visibility = visibility
# Add the owner as an admin
repoAccess = RepoAccess(owner, self, 2)
db.session.add(repoAccess)
class Commit(db.Model):
identifier = db.Column(db.String(227), unique=True, nullable=False, primary_key=True)
sha = db.Column(db.String(128), nullable=False)
repoName = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
ownerName = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
ownerIdentity = db.Column(db.String(321))
receiveDate = db.Column(db.DateTime, default=datetime.now)
authorDate = db.Column(db.DateTime)
message = db.Column(db.UnicodeText)
repo = db.relationship("Repo", back_populates="commits")
owner = db.relationship("User", back_populates="commits")
def __init__(self, sha, owner, repo, date, message, ownerIdentity):
self.identifier = f"{repo.route}/{sha}"
self.sha = sha
self.repoName = repo.route
self.repo = repo
self.ownerName = owner.username
self.owner = owner
self.authorDate = datetime.fromtimestamp(int(date))
self.message = message
self.ownerIdentity = ownerIdentity
class Post(db.Model):
identifier = db.Column(db.String(109), unique=True, nullable=False, primary_key=True)
number = db.Column(db.Integer, nullable=False)
repoName = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
ownerName = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
votes = db.relationship("PostVote", back_populates="post")
voteSum = db.Column(db.Integer, nullable=False, default=0)
parentID = db.Column(db.String(109), db.ForeignKey("post.identifier"), nullable=True)
state = db.Column(db.SmallInteger, nullable=True, default=1)
date = db.Column(db.DateTime, default=datetime.now)
lastUpdated = db.Column(db.DateTime, default=datetime.now)
subject = db.Column(db.Unicode(384))
message = db.Column(db.UnicodeText)
repo = db.relationship("Repo", back_populates="posts")
owner = db.relationship("User", back_populates="posts")
parent = db.relationship("Post", back_populates="children", remote_side="Post.identifier")
children = db.relationship("Post", back_populates="parent", remote_side="Post.parentID")
def __init__(self, owner, repo, parent, subject, message):
self.identifier = f"{repo.route}/{repo.lastPostID}"
self.number = repo.lastPostID
self.repoName = repo.route
self.repo = repo
self.ownerName = owner.username
self.owner = owner
self.subject = subject
self.message = message
self.parent = parent
repo.lastPostID += 1
def updateDate(self):
self.lastUpdated = datetime.now()
with db.session.no_autoflush:
if self.parent is not None:
self.parent.updateDate()
def getPermissionLevel(loggedIn, username, repository):
user = User.query.filter_by(username=loggedIn).first()
repo = Repo.query.filter_by(route=f"/{username}/{repository}").first()
gitHTTP.py
@@ -1,6 +1,7 @@
import uuid
from app import app, gitCommand, User, Repo, Commit, RepoAccess, getPermissionLevel, getVisibility, db, bcrypt
from models import *
from app import app, gitCommand, getPermissionLevel, getVisibility, db, bcrypt
import os
import shutil
import config
models.py
@@ -0,0 +1,193 @@
from app import app, db
import git
from datetime import datetime
from enum import Enum
from PIL import Image
from cairosvg import svg2png
with app.app_context():
class RepoAccess(db.Model):
id = db.Column(db.Integer, primary_key=True)
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
repoRoute = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
accessLevel = db.Column(db.SmallInteger(), nullable=False) # 0 read-only, 1 read-write, 2 admin
user = db.relationship("User", back_populates="repoAccess")
repo = db.relationship("Repo", back_populates="repoAccess")
__table_args__ = (db.UniqueConstraint("userUsername", "repoRoute", name="_user_repo_uc"),)
def __init__(self, user, repo, level):
self.userUsername = user.username
self.repoRoute = repo.route
self.accessLevel = level
class RepoFavourite(db.Model):
id = db.Column(db.Integer, primary_key=True)
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
repoRoute = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
user = db.relationship("User", back_populates="favourites")
repo = db.relationship("Repo", back_populates="favourites")
__table_args__ = (db.UniqueConstraint("userUsername", "repoRoute", name="_user_repo_uc1"),)
def __init__(self, user, repo):
self.userUsername = user.username
self.repoRoute = repo.route
class PostVote(db.Model):
id = db.Column(db.Integer, primary_key=True)
userUsername = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
postIdentifier = db.Column(db.String(109), db.ForeignKey("post.identifier"), nullable=False)
voteScore = db.Column(db.SmallInteger(), nullable=False)
user = db.relationship("User", back_populates="votes")
post = db.relationship("Post", back_populates="votes")
__table_args__ = (db.UniqueConstraint("userUsername", "postIdentifier", name="_user_post_uc"),)
def __init__(self, user, post, score):
self.userUsername = user.username
self.postIdentifier = post.identifier
self.voteScore = score
class User(db.Model):
username = db.Column(db.String(32), unique=True, nullable=False, primary_key=True)
displayName = db.Column(db.Unicode(128), unique=False, nullable=True)
bio = db.Column(db.Unicode(512), unique=False, nullable=True)
passwordHashed = db.Column(db.String(60), nullable=False)
email = db.Column(db.String(254), nullable=True)
company = db.Column(db.Unicode(64), nullable=True)
companyURL = db.Column(db.String(256), nullable=True)
URL = db.Column(db.String(256), nullable=True)
showMail = db.Column(db.Boolean, default=False, nullable=False)
location = db.Column(db.Unicode(64), nullable=True)
creationDate = db.Column(db.DateTime, default=datetime.utcnow)
repositories = db.relationship("Repo", back_populates="owner")
repoAccess = db.relationship("RepoAccess", back_populates="user")
votes = db.relationship("PostVote", back_populates="user")
favourites = db.relationship("RepoFavourite", back_populates="user")
commits = db.relationship("Commit", back_populates="owner")
posts = db.relationship("Post", back_populates="owner")
def __init__(self, username, password, email=None, displayName=None):
self.username = username
self.passwordHashed = bcrypt.generate_password_hash(password, config.HASHING_ROUNDS).decode("utf-8")
self.email = email
self.displayName = displayName
# Create the user's directory
if not os.path.exists(os.path.join(config.REPOS_PATH, username)):
os.makedirs(os.path.join(config.REPOS_PATH, username))
if not os.path.exists(os.path.join(config.USERDATA_PATH, username)):
os.makedirs(os.path.join(config.USERDATA_PATH, username))
avatarName = random.choice(os.listdir(config.DEFAULT_AVATARS_PATH))
if os.path.join(config.DEFAULT_AVATARS_PATH, avatarName).endswith(".svg"):
cairosvg.svg2png(url=os.path.join(config.DEFAULT_AVATARS_PATH, avatarName),
write_to="/tmp/roundabout-avatar.png")
avatar = Image.open("/tmp/roundabout-avatar.png")
else:
avatar = Image.open(os.path.join(config.DEFAULT_AVATARS_PATH, avatarName))
avatar.thumbnail(config.AVATAR_SIZE)
avatar.save(os.path.join(config.USERDATA_PATH, username, "avatar.png"))
class Repo(db.Model):
route = db.Column(db.String(98), unique=True, nullable=False, primary_key=True)
ownerName = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
name = db.Column(db.String(64), nullable=False)
owner = db.relationship("User", back_populates="repositories")
visibility = db.Column(db.SmallInteger(), nullable=False)
info = db.Column(db.Unicode(512), nullable=True)
URL = db.Column(db.String(256), nullable=True)
creationDate = db.Column(db.DateTime, default=datetime.utcnow)
defaultBranch = db.Column(db.String(64), nullable=True, default="")
commits = db.relationship("Commit", back_populates="repo")
posts = db.relationship("Post", back_populates="repo")
repoAccess = db.relationship("RepoAccess", back_populates="repo")
favourites = db.relationship("RepoFavourite", back_populates="repo")
lastPostID = db.Column(db.Integer, nullable=False, default=0)
def __init__(self, owner, name, visibility):
self.route = f"/{owner.username}/{name}"
self.name = name
self.ownerName = owner.username
self.owner = owner
self.visibility = visibility
# Add the owner as an admin
repoAccess = RepoAccess(owner, self, 2)
db.session.add(repoAccess)
class Commit(db.Model):
identifier = db.Column(db.String(227), unique=True, nullable=False, primary_key=True)
sha = db.Column(db.String(128), nullable=False)
repoName = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
ownerName = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
ownerIdentity = db.Column(db.String(321))
receiveDate = db.Column(db.DateTime, default=datetime.now)
authorDate = db.Column(db.DateTime)
message = db.Column(db.UnicodeText)
repo = db.relationship("Repo", back_populates="commits")
owner = db.relationship("User", back_populates="commits")
def __init__(self, sha, owner, repo, date, message, ownerIdentity):
self.identifier = f"{repo.route}/{sha}"
self.sha = sha
self.repoName = repo.route
self.repo = repo
self.ownerName = owner.username
self.owner = owner
self.authorDate = datetime.fromtimestamp(int(date))
self.message = message
self.ownerIdentity = ownerIdentity
class Post(db.Model):
identifier = db.Column(db.String(109), unique=True, nullable=False, primary_key=True)
number = db.Column(db.Integer, nullable=False)
repoName = db.Column(db.String(98), db.ForeignKey("repo.route"), nullable=False)
ownerName = db.Column(db.String(32), db.ForeignKey("user.username"), nullable=False)
votes = db.relationship("PostVote", back_populates="post")
voteSum = db.Column(db.Integer, nullable=False, default=0)
parentID = db.Column(db.String(109), db.ForeignKey("post.identifier"), nullable=True)
state = db.Column(db.SmallInteger, nullable=True, default=1)
date = db.Column(db.DateTime, default=datetime.now)
lastUpdated = db.Column(db.DateTime, default=datetime.now)
subject = db.Column(db.Unicode(384))
message = db.Column(db.UnicodeText)
repo = db.relationship("Repo", back_populates="posts")
owner = db.relationship("User", back_populates="posts")
parent = db.relationship("Post", back_populates="children", remote_side="Post.identifier")
children = db.relationship("Post", back_populates="parent", remote_side="Post.parentID")
def __init__(self, owner, repo, parent, subject, message):
self.identifier = f"{repo.route}/{repo.lastPostID}"
self.number = repo.lastPostID
self.repoName = repo.route
self.repo = repo
self.ownerName = owner.username
self.owner = owner
self.subject = subject
self.message = message
self.parent = parent
repo.lastPostID += 1
def updateDate(self):
self.lastUpdated = datetime.now()
with db.session.no_autoflush:
if self.parent is not None:
self.parent.updateDate()