aboutsummaryrefslogtreecommitdiffstats
path: root/pysite
diff options
context:
space:
mode:
authorGravatar momothereal <[email protected]>2018-06-23 02:10:47 -0400
committerGravatar momothereal <[email protected]>2018-06-23 02:10:47 -0400
commitbb60c29b8c51c26fba4e9678cb2d743e5dfc2e62 (patch)
treedde45d3b5c39d0a7ad0743da1dc9a8fe33362bd7 /pysite
parentAdd button to jam index in team list (diff)
GitLab team repo storage, edit form, etc.
Diffstat (limited to 'pysite')
-rw-r--r--pysite/constants.py2
-rw-r--r--pysite/tables.py3
-rw-r--r--pysite/views/main/jams/jam_team_list.py2
-rw-r--r--pysite/views/main/jams/team_edit_repo.py118
4 files changed, 123 insertions, 2 deletions
diff --git a/pysite/constants.py b/pysite/constants.py
index 016ab9c5..fa5dbab2 100644
--- a/pysite/constants.py
+++ b/pysite/constants.py
@@ -53,6 +53,8 @@ DISCORD_OAUTH_SECRET = environ.get('DISCORD_OAUTH_SECRET', '')
DISCORD_OAUTH_SCOPE = 'identify'
OAUTH_DATABASE = "oauth_data"
+GITLAB_ACCESS_TOKEN = environ.get("GITLAB_ACCESS_TOKEN", '')
+
PREFERRED_URL_SCHEME = environ.get("PREFERRED_URL_SCHEME", "http")
ERROR_DESCRIPTIONS = {
diff --git a/pysite/tables.py b/pysite/tables.py
index cf38a698..191b52bd 100644
--- a/pysite/tables.py
+++ b/pysite/tables.py
@@ -93,7 +93,8 @@ TABLES = {
keys=sorted([
"id", # uuid
"name", # str
- "members" # list[str]
+ "members", # list[str]
+ "repo" # str
])
),
diff --git a/pysite/views/main/jams/jam_team_list.py b/pysite/views/main/jams/jam_team_list.py
index 474c8f77..8165f235 100644
--- a/pysite/views/main/jams/jam_team_list.py
+++ b/pysite/views/main/jams/jam_team_list.py
@@ -9,7 +9,7 @@ from pysite.mixins import DBMixin, OAuthMixin
log = logging.getLogger(__name__)
-class JamsUserTeamListView(RouteView, DBMixin, OAuthMixin):
+class JamsTeamListView(RouteView, DBMixin, OAuthMixin):
path = "/jams/teams/<int:jam_id>"
name = "jams.jam_team_list"
diff --git a/pysite/views/main/jams/team_edit_repo.py b/pysite/views/main/jams/team_edit_repo.py
new file mode 100644
index 00000000..1b41335c
--- /dev/null
+++ b/pysite/views/main/jams/team_edit_repo.py
@@ -0,0 +1,118 @@
+import logging
+import re
+from urllib.parse import quote
+
+import requests
+from flask import jsonify, request
+from rethinkdb import ReqlNonExistenceError
+from urllib3.util import parse_url
+from werkzeug.exceptions import NotFound, Unauthorized, BadRequest
+
+from pysite.base_route import RouteView
+from pysite.constants import GITLAB_ACCESS_TOKEN
+from pysite.decorators import csrf
+from pysite.mixins import DBMixin, OAuthMixin
+
+log = logging.getLogger(__name__)
+
+
+class JamsTeamEditRepo(RouteView, DBMixin, OAuthMixin):
+ path = "/jams/teams/<string:team_id>/edit_repo"
+ name = "jams.team.edit_repo"
+
+ table_name = "code_jam_teams"
+ jams_table = "code_jams"
+
+ gitlab_projects_api_endpoint = "https://gitlab.com/api/v4/projects/{0}"
+
+ @csrf
+ def post(self, team_id):
+ if not self.user_data:
+ return self.redirect_login()
+
+ try:
+ query = self.db.query(self.table_name).get(team_id).merge(
+ lambda team: {
+ "jam":
+ self.db.query("code_jams").filter(
+ lambda jam: jam["teams"].contains(team["id"])
+ ).coerce_to("array")[0]
+ }
+ )
+
+ team = self.db.run(query)
+ except ReqlNonExistenceError:
+ log.exception("Failed RethinkDB query")
+ raise NotFound()
+
+ if not self.user_data["user_id"] in team["members"]:
+ raise Unauthorized()
+
+ repo_url = request.form.get("repo_url").strip()
+
+ # check if repo is a valid GitLab repo URI
+ url = parse_url(repo_url)
+
+ if url.host != "gitlab.com" or url.path is None:
+ raise BadRequest()
+
+ project_path = url.path.strip("/")
+ if len(project_path.split("/")) < 2:
+ raise BadRequest()
+
+ word_regex = re.compile("^[\-\w]+$")
+ for segment in project_path.split("/"):
+ if not word_regex.fullmatch(segment):
+ raise BadRequest()
+
+ project_path_encoded = quote(project_path, safe='')
+ if not self.validate_project(team, project_path_encoded):
+ return
+
+ team_obj = self.db.get(self.table_name, team_id)
+ team_obj["repo"] = project_path
+ self.db.insert(self.table_name, team_obj, conflict="update")
+
+ return jsonify(
+ {
+ "project_path": project_path
+ }
+ )
+
+ def validate_project(self, team, project_path):
+ # check on GitLab if the project exists, and is a fork
+ query_response = self.request_project(project_path)
+
+ if query_response.status_code != 200:
+ raise BadRequest()
+
+ project_data = query_response.json()
+ if "forked_from_project" not in project_data:
+ raise BadRequest()
+
+ # check if it's a fork for the right repo
+ forked_from_project = project_data["forked_from_project"]
+
+ jam_repo = team["jam"]["repo"]
+ if not jam_repo or jam_repo == "":
+ return True
+
+ jam_repo_path = quote(parse_url(jam_repo).path.strip("/"), safe='')
+ jam_repo_response = self.request_project(jam_repo_path)
+
+ if jam_repo_response.status_code != 200:
+ return True
+
+ jam_repo_data = jam_repo_response.json()
+ if jam_repo_data["id"] != forked_from_project["id"]:
+ raise BadRequest()
+
+ return True
+
+ def request_project(self, project_path):
+ return requests.get(
+ self.gitlab_projects_api_endpoint.format(project_path),
+ params={
+ "private_token": GITLAB_ACCESS_TOKEN
+ }
+ )