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

 gitHTTP.py

View raw Download
text/x-script.python • 4.62 kiB
Python script, ASCII text executable
        
            
1
import uuid
2
3
from app import app, gitCommand, User, Repo, Commit, RepoAccess, getPermissionLevel, getVisibility, db, bcrypt
4
import os
5
import shutil
6
import config
7
import flask
8
import git
9
import subprocess
10
from flask_httpauth import HTTPBasicAuth
11
import zlib
12
import re
13
import datetime
14
15
auth = HTTPBasicAuth(realm=config.AUTH_REALM)
16
17
18
authRequired = flask.Response("Unauthorized Access", 401, {"WWW-Authenticate": 'Basic realm="Login Required"'})
19
20
21
@auth.verify_password
22
def verifyPassword(username, password):
23
user = User.query.filter_by(username=username).first()
24
25
if user and bcrypt.check_password_hash(user.passwordHashed, password):
26
flask.g.user = username
27
return True
28
29
return False
30
31
32
@app.route("/<username>/<repository>/git-upload-pack", methods=["POST"])
33
@app.route("/git/<username>/<repository>/git-upload-pack", methods=["POST"])
34
@auth.login_required(optional=True)
35
def gitUploadPack(username, repository):
36
if auth.current_user() is None and not getVisibility(username, repository):
37
return authRequired
38
if not (getVisibility(username, repository) or getPermissionLevel(flask.g.user, username, repository) is not None):
39
flask.abort(403)
40
41
serverRepoLocation = os.path.join(config.REPOS_PATH, username, repository, ".git")
42
text = gitCommand(serverRepoLocation, flask.request.data, "upload-pack", "--stateless-rpc", ".")
43
44
return flask.Response(text, content_type="application/x-git-upload-pack-result")
45
46
47
@app.route("/<username>/<repository>/git-receive-pack", methods=["POST"])
48
@app.route("/git/<username>/<repository>/git-receive-pack", methods=["POST"])
49
@auth.login_required
50
def gitReceivePack(username, repository):
51
if not getPermissionLevel(flask.g.user, username, repository):
52
flask.abort(403)
53
54
serverRepoLocation = os.path.join(config.REPOS_PATH, username, repository, ".git")
55
text = gitCommand(serverRepoLocation, flask.request.data, "receive-pack", "--stateless-rpc", ".")
56
57
sha = flask.request.data.split(b" ", 2)[1].decode()
58
info = gitCommand(serverRepoLocation, None, "show", "-s", "--format='%H%n%at%n%cn <%ce>%n%B'", sha).decode()
59
60
if re.match("^[0-9a-fA-F]{40}$", info[:40]):
61
print(info.split("\n", 3))
62
sha, time, identity, body = info.split("\n", 3)
63
login = flask.g.user
64
65
user = User.query.filter_by(username=login).first()
66
repo = Repo.query.filter_by(route=f"/{username}/{repository}").first()
67
commit = Commit(sha, user, repo, time, body, identity)
68
69
db.session.add(commit)
70
db.session.commit()
71
72
return flask.Response(text, content_type="application/x-git-receive-pack-result")
73
74
75
@app.route("/<username>/<repository>/info/refs", methods=["GET", "POST"])
76
@app.route("/git/<username>/<repository>/info/refs", methods=["GET", "POST"])
77
@auth.login_required(optional=True)
78
def gitInfoRefs(username, repository):
79
serverRepoLocation = os.path.join(config.REPOS_PATH, username, repository, ".git")
80
81
repo = git.Repo(serverRepoLocation)
82
repoData = Repo.query.filter_by(route=f"/{username}/{repository}").first()
83
if not repoData.defaultBranch:
84
if repo.heads:
85
repoData.defaultBranch = repo.heads[0].name
86
repo.git.checkout("-f", repoData.defaultBranch)
87
88
if auth.current_user() is None and (not getVisibility(username, repository) or flask.request.args.get("service") == "git-receive-pack"):
89
return authRequired
90
try:
91
if not (getVisibility(username, repository) or getPermissionLevel(flask.g.user, username, repository) is not None):
92
flask.abort(403)
93
except AttributeError:
94
return authRequired
95
96
service = flask.request.args.get("service")
97
98
if service.startswith("git"):
99
service = service[4:]
100
else:
101
flask.abort(403)
102
103
if service == "receive-pack":
104
try:
105
if not getPermissionLevel(flask.g.user, username, repository):
106
flask.abort(403)
107
except AttributeError:
108
return authRequired
109
110
serviceLine = f"# service=git-{service}\n"
111
serviceLine = (f"{len(serviceLine) + 4:04x}" + serviceLine).encode()
112
113
if service == "upload-pack":
114
text = serviceLine + b"0000" + gitCommand(serverRepoLocation, None, "upload-pack", "--stateless-rpc", "--advertise-refs", "--http-backend-info-refs", ".")
115
elif service == "receive-pack":
116
refs = gitCommand(serverRepoLocation, None, "receive-pack", "--http-backend-info-refs", ".")
117
text = serviceLine + b"0000" + refs
118
else:
119
flask.abort(403)
120
121
response = flask.Response(text, content_type=f"application/x-git-{service}-advertisement")
122
response.headers["Cache-Control"] = "no-cache"
123
124
return response
125
126