[copr] master: foo (f2f38a0)
by Miroslav Suchý
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit f2f38a08482a68cce918db4e0fd7e7a7f3692aa9
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Mon Oct 12 10:18:44 2015 +0200
foo
>---------------------------------------------------------------
.../3ec22e1db75a_add_openid_group_column.py | 4 +-
frontend/coprs_frontend/coprs/helpers.py | 24 ++++++++++++++++++++
frontend/coprs_frontend/coprs/models.py | 5 +--
3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/frontend/coprs_frontend/alembic/versions/3ec22e1db75a_add_openid_group_column.py b/frontend/coprs_frontend/alembic/versions/3ec22e1db75a_add_openid_group_column.py
index ee166e3..bcbce64 100644
--- a/frontend/coprs_frontend/alembic/versions/3ec22e1db75a_add_openid_group_column.py
+++ b/frontend/coprs_frontend/alembic/versions/3ec22e1db75a_add_openid_group_column.py
@@ -12,10 +12,10 @@ down_revision = '3f4966a9cc0'
from alembic import op
import sqlalchemy as sa
-from sqlalchemy.dialects import postgresql
+from coprs.helpers import JSONEncodedDict
def upgrade():
- op.add_column('user', sa.Column('openid_groups', postgresql.JSON(), nullable=True))
+ op.add_column('user', sa.Column('openid_groups', JSONEncodedDict(), nullable=True))
def downgrade():
diff --git a/frontend/coprs_frontend/coprs/helpers.py b/frontend/coprs_frontend/coprs/helpers.py
index f949b88..c96ab9f 100644
--- a/frontend/coprs_frontend/coprs/helpers.py
+++ b/frontend/coprs_frontend/coprs/helpers.py
@@ -10,6 +10,8 @@ from dateutil import parser as dt_parser
from netaddr import IPAddress, IPNetwork
from redis import StrictRedis
from rpmUtils.miscutils import splitFilename
+from sqlalchemy.types import TypeDecorator, VARCHAR
+import json
from coprs import constants
from coprs import app
@@ -107,6 +109,28 @@ class FailTypeEnum(object):
"srpm_query_failed": 5}
+class JSONEncodedDict(TypeDecorator):
+ """Represents an immutable structure as a json-encoded string.
+
+ Usage::
+
+ JSONEncodedDict(255)
+
+ """
+
+ impl = VARCHAR
+
+ def process_bind_param(self, value, dialect):
+ if value is not None:
+ value = json.dumps(value)
+
+ return value
+
+ def process_result_value(self, value, dialect):
+ if value is not None:
+ value = json.loads(value)
+ return value
+
class Paginator(object):
def __init__(self, query, total_count, page=1,
diff --git a/frontend/coprs_frontend/coprs/models.py b/frontend/coprs_frontend/coprs/models.py
index 8555558..a9db0b1 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -5,7 +5,6 @@ import os
import flask
from sqlalchemy.ext.associationproxy import association_proxy
-from sqlalchemy.dialects.postgresql import JSON
from libravatar import libravatar_url
import zlib
@@ -16,7 +15,7 @@ from coprs import app
import itertools
import operator
-from coprs.helpers import BuildSourceEnum, StatusEnum, ActionTypeEnum
+from coprs.helpers import BuildSourceEnum, StatusEnum, ActionTypeEnum, JSONEncodedDict
class User(db.Model, helpers.Serializer):
@@ -51,7 +50,7 @@ class User(db.Model, helpers.Serializer):
db.Date, nullable=False, default=datetime.date(2000, 1, 1))
# list of groups as retrieved from openid
- openid_groups = db.Column(JSON)
+ openid_groups = db.Column(JSONEncodedDict)
@property
def name(self):
8 years, 7 months
[copr] master: [frontend][legacy api] support listing projects owned by a group (cf29fa2)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit cf29fa2498adcd66f243b6b618314cef2431b943
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Fri Oct 9 14:21:56 2015 +0200
[frontend][legacy api] support listing projects owned by a group
>---------------------------------------------------------------
.../coprs/views/api_ns/api_general.py | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/views/api_ns/api_general.py b/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
index 6c2d365..bf7aa86 100644
--- a/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
+++ b/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
@@ -195,8 +195,14 @@ def api_coprs_by_owner(username=None):
release_tmpl = "{chroot.os_release}-{chroot.os_version}-{chroot.arch}"
- query = CoprsLogic.join_builds(
- CoprsLogic.get_multiple_owned_by_username(username))
+ if username.startswith("@"):
+ group_name = username[1:]
+ query = CoprsLogic.get_multiple()
+ query = CoprsLogic.filter_by_group_name(query, group_name)
+ else:
+ query = CoprsLogic.get_multiple_owned_by_username(username)
+
+ query = CoprsLogic.join_builds(query)
query = CoprsLogic.set_query_order(query)
repos = query.all()
8 years, 7 months
[copr] master: [cli] build action: accept any character in the username (76d6864)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 76d68643eac373ff2bd8452007bb5cc144c565cf
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Fri Oct 9 13:21:28 2015 +0200
[cli] build action: accept any character in the username
>---------------------------------------------------------------
cli/copr_cli/main.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/cli/copr_cli/main.py b/cli/copr_cli/main.py
index 64aefc5..ba24054 100644
--- a/cli/copr_cli/main.py
+++ b/cli/copr_cli/main.py
@@ -153,7 +153,7 @@ class Commands(object):
"""
copr = args.copr
- m = re.match(r"(\w+)/(.*)", copr)
+ m = re.match(r"([^/]+)/(.*)", copr)
if m:
username = m.group(1)
copr = m.group(2)
8 years, 7 months
[copr] master: [frontend] typo (8234a21)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 8234a21d9d10f9faa0e9240aa55101e90d8e7de0
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Fri Oct 9 12:58:22 2015 +0200
[frontend] typo
>---------------------------------------------------------------
frontend/coprs_frontend/coprs/views/misc.py | 10 +++-------
1 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/views/misc.py b/frontend/coprs_frontend/coprs/views/misc.py
index 69530a9..714fe9a 100644
--- a/frontend/coprs_frontend/coprs/views/misc.py
+++ b/frontend/coprs_frontend/coprs/views/misc.py
@@ -165,7 +165,6 @@ def login():
@oid.after_login
def create_or_login(resp):
flask.session["openid"] = resp.identity_url
-
fasusername = resp.identity_url.replace(
".id.fedoraproject.org/", "").replace("http://", "")
@@ -185,8 +184,8 @@ def create_or_login(resp):
user.mail = resp.email
user.timezone = resp.timezone
if "lp" in resp.extensions:
- team_resp = resp.extensions['lp'] # name space for the teams extension
- user.openid_groups = { fas_groups: team_resp.teams }
+ team_resp = resp.extensions['lp'] # name space for the teams extension
+ user.openid_groups = {"fas_groups": team_resp.teams}
db.session.add(user)
db.session.commit()
@@ -198,10 +197,7 @@ def create_or_login(resp):
username=user.name))
return flask.redirect(oid.get_next_url())
else:
- # TODO: auto-fix, original line here. Check logic
- #flask.flash("User '{0}' is not allowed".format(user.name))
-
- flask.flash("User '{0}' is not allowed".format(fasusername.name))
+ flask.flash("User '{0}' is not allowed".format(fasusername))
return flask.redirect(oid.get_next_url())
8 years, 7 months
[copr] master: change logic to store team in db rather then in session (87eb4f8)
by Miroslav Suchý
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 87eb4f8c71e05f0e83e474fde6e5db1bf832ec4d
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Fri Oct 9 11:19:36 2015 +0200
change logic to store team in db rather then in session
>---------------------------------------------------------------
.../coprs_frontend/coprs/logic/complex_logic.py | 4 ++--
frontend/coprs_frontend/coprs/models.py | 8 +++++---
.../coprs/views/groups_ns/groups_general.py | 2 +-
frontend/coprs_frontend/coprs/views/misc.py | 7 +++----
4 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/logic/complex_logic.py b/frontend/coprs_frontend/coprs/logic/complex_logic.py
index 22a0d35..1f1b882 100644
--- a/frontend/coprs_frontend/coprs/logic/complex_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/complex_logic.py
@@ -113,8 +113,8 @@ class ComplexLogic(object):
@staticmethod
def get_active_groups_by_user(user_name):
- if "teams" in flask.session:
- names = flask.session["teams"]
+ names = flask.g.user.user_groups
+ if names:
query = UsersLogic.get_groups_by_names_list(names)
return query.filter(User.name == user_name)
else:
diff --git a/frontend/coprs_frontend/coprs/models.py b/frontend/coprs_frontend/coprs/models.py
index d113a9e..8555558 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -101,7 +101,10 @@ class User(db.Model, helpers.Serializer):
@property
def user_teams(self):
- return flask.session.get("teams", [])
+ if self.openid_groups and 'fas_groups' in self.openid_groups:
+ return self.openid_groups['fas_groups']
+ else:
+ return []
@property
def user_groups(self):
@@ -129,9 +132,8 @@ class User(db.Model, helpers.Serializer):
return True
- # a bit dirty code, here we access flask.session object
if copr.group is not None and \
- copr.group.fas_name in flask.session.get("teams", []):
+ copr.group.fas_name in self.user_teams:
return True
return False
diff --git a/frontend/coprs_frontend/coprs/views/groups_ns/groups_general.py b/frontend/coprs_frontend/coprs/views/groups_ns/groups_general.py
index 7e35d7b..22147ea 100644
--- a/frontend/coprs_frontend/coprs/views/groups_ns/groups_general.py
+++ b/frontend/coprs_frontend/coprs/views/groups_ns/groups_general.py
@@ -64,7 +64,7 @@ def list_projects_by_group(group_name, page=1):
@groups_ns.route("/list/my")
@login_required
def list_user_groups():
- teams = session.get("teams")
+ teams = flask.g.user.user_teams
active_map = {
group.fas_name: group.name for group in
UsersLogic.get_groups_by_fas_names_list(teams).all()
diff --git a/frontend/coprs_frontend/coprs/views/misc.py b/frontend/coprs_frontend/coprs/views/misc.py
index 7efcd2f..69530a9 100644
--- a/frontend/coprs_frontend/coprs/views/misc.py
+++ b/frontend/coprs_frontend/coprs/views/misc.py
@@ -169,10 +169,6 @@ def create_or_login(resp):
fasusername = resp.identity_url.replace(
".id.fedoraproject.org/", "").replace("http://", "")
- if "lp" in resp.extensions:
- team_resp = resp.extensions['lp'] # name space for the teams extension
- flask.session["teams"] = team_resp.teams
-
# kidding me.. or not
if fasusername and (
(
@@ -188,6 +184,9 @@ def create_or_login(resp):
else:
user.mail = resp.email
user.timezone = resp.timezone
+ if "lp" in resp.extensions:
+ team_resp = resp.extensions['lp'] # name space for the teams extension
+ user.openid_groups = { fas_groups: team_resp.teams }
db.session.add(user)
db.session.commit()
8 years, 7 months
[copr] master: add openid_groups column to user table (e4e9619)
by Miroslav Suchý
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit e4e9619cb34cbec7d7c00923bfce1ac9ec189106
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Fri Oct 9 10:00:06 2015 +0200
add openid_groups column to user table
>---------------------------------------------------------------
.../3ec22e1db75a_add_openid_group_column.py | 22 ++++++++++++++++++++
frontend/coprs_frontend/coprs/models.py | 4 +++
2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/frontend/coprs_frontend/alembic/versions/3ec22e1db75a_add_openid_group_column.py b/frontend/coprs_frontend/alembic/versions/3ec22e1db75a_add_openid_group_column.py
new file mode 100644
index 0000000..ee166e3
--- /dev/null
+++ b/frontend/coprs_frontend/alembic/versions/3ec22e1db75a_add_openid_group_column.py
@@ -0,0 +1,22 @@
+"""Add openid_group column
+
+Revision ID: 3ec22e1db75a
+Revises: 3f4966a9cc0
+Create Date: 2015-10-09 07:56:41.303179
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '3ec22e1db75a'
+down_revision = '3f4966a9cc0'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects import postgresql
+
+def upgrade():
+ op.add_column('user', sa.Column('openid_groups', postgresql.JSON(), nullable=True))
+
+
+def downgrade():
+ op.drop_column('user', 'openid_groups')
diff --git a/frontend/coprs_frontend/coprs/models.py b/frontend/coprs_frontend/coprs/models.py
index 75e6dc9..d113a9e 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -5,6 +5,7 @@ import os
import flask
from sqlalchemy.ext.associationproxy import association_proxy
+from sqlalchemy.dialects.postgresql import JSON
from libravatar import libravatar_url
import zlib
@@ -49,6 +50,9 @@ class User(db.Model, helpers.Serializer):
api_token_expiration = db.Column(
db.Date, nullable=False, default=datetime.date(2000, 1, 1))
+ # list of groups as retrieved from openid
+ openid_groups = db.Column(JSON)
+
@property
def name(self):
"""
8 years, 7 months
[copr] master: [frontend] Updating legacy API to support group projects: WIP (974d2c1)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 974d2c11f76548e4e9abf920cb06a66f2834e4df
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Thu Oct 8 17:42:27 2015 +0200
[frontend] Updating legacy API to support group projects: WIP
>---------------------------------------------------------------
frontend/coprs_frontend/coprs/exceptions.py | 12 +-
.../coprs_frontend/coprs/logic/complex_logic.py | 2 +-
.../coprs_frontend/coprs/views/api_ns/__init__.py | 31 +
.../coprs/views/api_ns/api_general.py | 681 +++++++++-----------
.../coprs/views/coprs_ns/__init__.py | 4 +-
5 files changed, 333 insertions(+), 397 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/exceptions.py b/frontend/coprs_frontend/coprs/exceptions.py
index 24bf57e..57c6fff 100644
--- a/frontend/coprs_frontend/coprs/exceptions.py
+++ b/frontend/coprs_frontend/coprs/exceptions.py
@@ -41,10 +41,12 @@ class ActionInProgressException(BaseException):
class CoprHttpException(Exception):
_default = "Generic copr exception"
- code = 500
+ _code = 500
- def __init__(self, message=None):
+ def __init__(self, message=None, code=None, **kwargs):
self.message = message
+ self.code = code or self._code
+ self.kwargs = kwargs
def __unicode__(self):
return self.message or self._default
@@ -63,3 +65,9 @@ class AccessRestricted(CoprHttpException):
_default = "You don't have required permission"
_code = 403
+
+
+class LegacyApiError(CoprHttpException):
+
+ _default = "API error"
+ _code = 500
diff --git a/frontend/coprs_frontend/coprs/logic/complex_logic.py b/frontend/coprs_frontend/coprs/logic/complex_logic.py
index 66fe984..22a0d35 100644
--- a/frontend/coprs_frontend/coprs/logic/complex_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/complex_logic.py
@@ -101,7 +101,7 @@ class ComplexLogic(object):
if not chroot:
raise ObjectNotFound(
- message="Chroot name {0} does not exist.".format(chroot_name))
+ message="Chroot name {} does not exist.".format(chroot_name))
return chroot
#
diff --git a/frontend/coprs_frontend/coprs/views/api_ns/__init__.py b/frontend/coprs_frontend/coprs/views/api_ns/__init__.py
index 11e81ae..80e7f33 100644
--- a/frontend/coprs_frontend/coprs/views/api_ns/__init__.py
+++ b/frontend/coprs_frontend/coprs/views/api_ns/__init__.py
@@ -1,3 +1,34 @@
+import json
+
import flask
+from flask import make_response
+
+from coprs.exceptions import CoprHttpException
+
api_ns = flask.Blueprint("api_ns", __name__, url_prefix="/api")
+
+
+def error_response(error):
+ """
+
+ :type error: CoprHttpException
+ :return:
+ """
+ body = {
+ "error": error.message,
+ "output": "notok"
+ }
+ if error.kwargs:
+ body.update(error.kwargs)
+ resp = make_response(json.dumps(body), error.code)
+ resp.mimetype = "application/json"
+
+ return resp
+
+
+(a)api_ns.errorhandler(CoprHttpException)
+def handle_api_errors(error):
+ return error_response(error)
+
+
diff --git a/frontend/coprs_frontend/coprs/views/api_ns/api_general.py b/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
index 57994d4..6c2d365 100644
--- a/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
+++ b/frontend/coprs_frontend/coprs/views/api_ns/api_general.py
@@ -1,5 +1,6 @@
import base64
import datetime
+from functools import wraps
import os
import shutil
import tempfile
@@ -17,6 +18,7 @@ from coprs import helpers
from coprs.helpers import fix_protocol_for_backend
from coprs.logic.api_logic import MonitorWrapper
from coprs.logic.complex_logic import ComplexLogic
+from coprs.logic.users_logic import UsersLogic
from coprs.views.misc import login_required, api_login_required
@@ -27,7 +29,24 @@ from coprs.logic import coprs_logic
from coprs.logic.coprs_logic import CoprsLogic, CoprChrootsLogic
from coprs.exceptions import (ActionInProgressException,
- InsufficientRightsException)
+ InsufficientRightsException,
+ LegacyApiError)
+
+
+def api_req_with_copr(f):
+ """
+ Dirty code, using until we migrate to the API 2
+ """
+ @wraps(f)
+ def wrapper(username, coprname, **kwargs):
+ if username.startswith("@"):
+ group_name = username[1:]
+ copr = ComplexLogic.get_group_copr_safe(group_name, coprname)
+ else:
+ copr = ComplexLogic.get_copr_safe(username, coprname)
+
+ return f(copr, **kwargs)
+ return wrapper
@api_ns.route("/")
@@ -80,15 +99,12 @@ def api_new_copr(username):
"""
form = forms.CoprFormFactory.create_form_cls()(csrf_enabled=False)
- httpcode = 200
# are there any arguments in POST which our form doesn't know?
# TODO: don't use WTFform for parsing and validation here
if any([post_key not in form.__dict__.keys()
for post_key in flask.request.form.keys()]):
- output = {"output": "notok",
- "error": "Unknown arguments passed (non-existing chroot probably)"}
- httpcode = 500
+ raise LegacyApiError("Unknown arguments passed (non-existing chroot probably)")
elif form.validate_on_submit():
infos = []
@@ -120,9 +136,8 @@ def api_new_copr(username):
output = {"output": "ok", "message": "\n".join(infos)}
db.session.commit()
except exceptions.DuplicateException as err:
- output = {"output": "notok", "error": err}
- httpcode = 500
db.session.rollback()
+ raise LegacyApiError(str(err))
else:
errormsg = "Validation error\n"
@@ -131,21 +146,18 @@ def api_new_copr(username):
errormsg += "- {0}: {1}\n".format(field, "\n".join(emsgs))
errormsg = errormsg.replace('"', "'")
- output = {"output": "notok", "error": errormsg}
- httpcode = 500
+ raise LegacyApiError(errormsg)
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ return flask.jsonify(output)
@api_ns.route("/coprs/<username>/<coprname>/delete/", methods=["POST"])
@api_login_required
-def api_copr_delete(username, coprname):
+@api_req_with_copr
+def api_copr_delete(copr):
""" Deletes selected user's project
"""
form = forms.CoprDeleteForm(csrf_enabled=False)
- copr = CoprsLogic.get(username, coprname).first()
httpcode = 200
if form.validate_on_submit() and copr:
@@ -153,20 +165,17 @@ def api_copr_delete(username, coprname):
ComplexLogic.delete_copr(copr)
except (exceptions.ActionInProgressException,
exceptions.InsufficientRightsException) as err:
- output = {"output": "notok", "error": err}
- httpcode = 500
+
db.session.rollback()
+ raise LegacyApiError(str(err))
else:
- message = "Project {0} has been deleted.".format(coprname)
+ message = "Project {0} has been deleted.".format(cop.rname)
output = {"output": "ok", "message": message}
db.session.commit()
else:
- output = {"output": "notok", "error": "Invalid request"}
- httpcode = 500
+ raise LegacyApiError("Invalid request")
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ return flask.jsonify(output)
@api_ns.route("/coprs/")
@@ -181,41 +190,39 @@ def api_coprs_by_owner(username=None):
"""
username = flask.request.args.get("username", None) or username
+ if username is None:
+ raise LegacyApiError("Invalid request: missing `username` ")
+
release_tmpl = "{chroot.os_release}-{chroot.os_version}-{chroot.arch}"
- httpcode = 200
- if username:
- query = CoprsLogic.join_builds(
- CoprsLogic.get_multiple_owned_by_username(username))
- query = CoprsLogic.set_query_order(query)
- repos = query.all()
- output = {"output": "ok", "repos": []}
- for repo in repos:
- yum_repos = {}
- for build in repo.builds:
- if build.results:
- for chroot in repo.active_chroots:
- release = release_tmpl.format(chroot=chroot)
- yum_repos[release] = fix_protocol_for_backend(
- os.path.join(build.results, release + '/'))
- break
-
- output["repos"].append({"name": repo.name,
- "additional_repos": repo.repos,
- "yum_repos": yum_repos,
- "description": repo.description,
- "instructions": repo.instructions})
- else:
- output = {"output": "notok", "error": "Invalid request"}
- httpcode = 500
+ query = CoprsLogic.join_builds(
+ CoprsLogic.get_multiple_owned_by_username(username))
+ query = CoprsLogic.set_query_order(query)
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ repos = query.all()
+ output = {"output": "ok", "repos": []}
+ for repo in repos:
+ yum_repos = {}
+ for build in repo.builds:
+ if build.results:
+ for chroot in repo.active_chroots:
+ release = release_tmpl.format(chroot=chroot)
+ yum_repos[release] = fix_protocol_for_backend(
+ os.path.join(build.results, release + '/'))
+ break
+
+ output["repos"].append({"name": repo.name,
+ "additional_repos": repo.repos,
+ "yum_repos": yum_repos,
+ "description": repo.description,
+ "instructions": repo.instructions})
+
+ return flask.jsonify(output)
@api_ns.route("/coprs/<username>/<coprname>/detail/")
-def api_coprs_by_owner_detail(username, coprname):
+@api_req_with_copr
+def api_coprs_by_owner_detail(copr):
""" Return detail of one project.
:arg username: the username of the person one would like to the
@@ -223,373 +230,272 @@ def api_coprs_by_owner_detail(username, coprname):
:arg coprname: the name of project.
"""
- if username.startswith("@"):
- copr = ComplexLogic.get_group_copr_safe(username[1:], coprname)
- else:
- copr = CoprsLogic.get(username, coprname).first()
-
release_tmpl = "{chroot.os_release}-{chroot.os_version}-{chroot.arch}"
- httpcode = 200
- if username and copr:
- output = {"output": "ok", "detail": {}}
- yum_repos = {}
- for build in copr.builds:
- if build.results:
- for chroot in copr.active_chroots:
- release = release_tmpl.format(chroot=chroot)
- yum_repos[release] = fix_protocol_for_backend(
- os.path.join(build.results, release + '/'))
- break
- output["detail"] = {
- "name": copr.name,
- "additional_repos": copr.repos,
- "yum_repos": yum_repos,
- "description": copr.description,
- "instructions": copr.instructions,
- "last_modified": builds_logic.BuildsLogic.last_modified(copr),
- "auto_createrepo": copr.auto_createrepo,
- }
- else:
- output = {"output": "notok", "error": "Copr with name {0} does not exist.".format(coprname)}
- httpcode = 500
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ output = {"output": "ok", "detail": {}}
+ yum_repos = {}
+ for build in copr.builds:
+ if build.results:
+ for chroot in copr.active_chroots:
+ release = release_tmpl.format(chroot=chroot)
+ yum_repos[release] = fix_protocol_for_backend(
+ os.path.join(build.results, release + '/'))
+ break
+ output["detail"] = {
+ "name": copr.name,
+ "additional_repos": copr.repos,
+ "yum_repos": yum_repos,
+ "description": copr.description,
+ "instructions": copr.instructions,
+ "last_modified": builds_logic.BuildsLogic.last_modified(copr),
+ "auto_createrepo": copr.auto_createrepo,
+ }
+ return flask.jsonify(output)
@api_ns.route("/coprs/<username>/<coprname>/new_build/", methods=["POST"])
@api_login_required
-def copr_new_build(username, coprname):
- copr = CoprsLogic.get(username, coprname).first()
- httpcode = 200
- if not copr:
- output = {"output": "notok", "error":
- "Copr with name {0} does not exist.".format(coprname)}
- httpcode = 500
+@api_req_with_copr
+def copr_new_build(copr):
- else:
- form = forms.BuildFormFactory.create_form_cls(
- copr.active_chroots)(csrf_enabled=False)
-
- # are there any arguments in POST which our form doesn't know?
- if any([post_key not in form.__dict__.keys()
- for post_key in flask.request.form.keys()]):
- output = {"output": "notok",
- "error": "Unknown arguments passed (non-existing chroot probably)"}
- httpcode = 500
-
- elif form.validate_on_submit() and flask.g.user.can_build_in(copr):
- # we're checking authorization above for now
- # and also creating separate build for each package
- pkgs = form.pkgs.data.split("\n")
- ids = []
- chroots = []
- for chroot in copr.active_chroots:
- if chroot.name in form.selected_chroots:
- chroots.append(chroot)
-
- for pkg in pkgs:
- # create json describing the build source
- source_type = helpers.BuildSourceEnum("srpm_link")
- source_json = json.dumps({"url": pkg})
-
- build = builds_logic.BuildsLogic.add(
- user=flask.g.user,
- pkgs=pkg,
- copr=copr,
- chroots=chroots,
- source_type=source_type,
- source_json=source_json)
-
- if flask.g.user.proven:
- build.memory_reqs = form.memory_reqs.data
- build.timeout = form.timeout.data
-
- db.session.commit()
- ids.append(build.id)
-
- output = {"output": "ok",
- "ids": ids,
- "message": "Build was added to {0}.".format(coprname)}
- else:
- output = {"output": "notok", "error": "Invalid request"}
- httpcode = 500
+ form = forms.BuildFormFactory.create_form_cls(
+ copr.active_chroots)(csrf_enabled=False)
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ # are there any arguments in POST which our form doesn't know?
+ if any([post_key not in form.__dict__.keys()
+ for post_key in flask.request.form.keys()]):
+ raise LegacyApiError("Unknown arguments passed (non-existing chroot probably)")
+
+ if not form.validate_on_submit():
+ raise LegacyApiError("Invalid request: bad request parameters")
+
+ if not flask.g.user.can_build_in(copr):
+ raise LegacyApiError("Invalid request: user {} is not allowed to build in the copr: {}"
+ .format(flask.g.user.username, copr))
+
+ # we're checking authorization above for now
+ # and also creating separate build for each package
+ pkgs = form.pkgs.data.split("\n")
+ ids = []
+ chroots = []
+ for chroot in copr.active_chroots:
+ if chroot.name in form.selected_chroots:
+ chroots.append(chroot)
+
+ for pkg in pkgs:
+ # create json describing the build source
+ source_type = helpers.BuildSourceEnum("srpm_link")
+ source_json = json.dumps({"url": pkg})
+
+ build = builds_logic.BuildsLogic.add(
+ user=flask.g.user,
+ pkgs=pkg,
+ copr=copr,
+ chroots=chroots,
+ source_type=source_type,
+ source_json=source_json)
+
+ if flask.g.user.proven:
+ build.memory_reqs = form.memory_reqs.data
+ build.timeout = form.timeout.data
+
+ db.session.commit()
+ ids.append(build.id)
+
+ output = {"output": "ok",
+ "ids": ids,
+ "message": "Build was added to {0}.".format(copr.name)}
+
+ return flask.jsonify(output)
@api_ns.route("/coprs/<username>/<coprname>/new_build_upload/", methods=["POST"])
@api_login_required
-def copr_new_build_upload(username, coprname):
- copr = coprs_logic.CoprsLogic.get(username, coprname).first()
- httpcode = 200
- if not copr:
- output = {"output": "notok", "error":
- "Copr with name {0} does not exist.".format(coprname)}
- httpcode = 500
+@api_req_with_copr
+def copr_new_build_upload(copr):
- else:
- form = forms.BuildFormUploadFactory.create_form_cls(
- copr.active_chroots)(csrf_enabled=False)
-
- # are there any arguments in POST which our form doesn't know?
- if any([post_key not in form.__dict__.keys()
- for post_key in flask.request.form.keys()]):
- output = {"output": "notok",
- "error": "Unknown arguments passed (non-existing chroot probably)"}
- httpcode = 500
-
- elif form.validate_on_submit():
- tmp = tempfile.mkdtemp(dir=app.config["SRPM_STORAGE_DIR"])
- tmp_name = os.path.basename(tmp)
- filename = secure_filename(form.pkgs.data.filename)
- file_path = os.path.join(tmp, filename)
- form.pkgs.data.save(file_path)
-
- # get the package name vithout version and release
- pkgname = helpers.parse_package_name(filename)
-
- # make the pkg public
- pkg_url = "https://{hostname}/tmp/{tmp_dir}/{srpm}".format(
- hostname=app.config["PUBLIC_COPR_HOSTNAME"],
- tmp_dir=tmp_name,
- srpm=filename)
-
- # check which chroots we need
- chroots = []
- for chroot in copr.active_chroots:
- if chroot.name in form.selected_chroots:
- chroots.append(chroot)
-
- # create json describing the build source
- source_type = helpers.BuildSourceEnum("srpm_upload")
- source_json = json.dumps({"tmp": tmp_name,
- "pkg": filename})
-
- # create a new build
- try:
- build = builds_logic.BuildsLogic.add(
- user=flask.g.user,
- pkgs=pkg_url,
- copr=copr,
- chroots=chroots,
- source_type=source_type,
- source_json=source_json,
- enable_net=form.enable_net.data)
-
- if flask.g.user.proven:
- build.memory_reqs = form.memory_reqs.data
- build.timeout = form.timeout.data
-
- db.session.commit()
-
- except (ActionInProgressException, InsufficientRightsException) as e:
- flask.flash(str(e))
- db.session.rollback()
- shutil.rmtree(tmp)
-
- output = {"output": "ok",
- "ids": [build.id],
- "message": "Build was added to {0}.".format(coprname)}
- else:
- output = {"output": "notok", "error": "Invalid request"}
- httpcode = 500
+ form = forms.BuildFormUploadFactory.create_form_cls(
+ copr.active_chroots)(csrf_enabled=False)
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ # are there any arguments in POST which our form doesn't know?
+ if any([post_key not in form.__dict__.keys()
+ for post_key in flask.request.form.keys()]):
+ raise LegacyApiError("Unknown arguments passed (non-existing chroot probably)")
+
+ if not form.validate_on_submit():
+ raise LegacyApiError("Invalid request: bad request parameters")
+
+ tmp = tempfile.mkdtemp(dir=app.config["SRPM_STORAGE_DIR"])
+ tmp_name = os.path.basename(tmp)
+ filename = secure_filename(form.pkgs.data.filename)
+ file_path = os.path.join(tmp, filename)
+ form.pkgs.data.save(file_path)
+
+ # make the pkg public
+ pkg_url = "https://{hostname}/tmp/{tmp_dir}/{srpm}".format(
+ hostname=app.config["PUBLIC_COPR_HOSTNAME"],
+ tmp_dir=tmp_name,
+ srpm=filename)
+
+ # check which chroots we need
+ chroots = []
+ for chroot in copr.active_chroots:
+ if chroot.name in form.selected_chroots:
+ chroots.append(chroot)
+
+ # create json describing the build source
+ source_type = helpers.BuildSourceEnum("srpm_upload")
+ source_json = json.dumps({"tmp": tmp_name,
+ "pkg": filename})
+
+ # create a new build
+ try:
+ build = builds_logic.BuildsLogic.add(
+ user=flask.g.user,
+ pkgs=pkg_url,
+ copr=copr,
+ chroots=chroots,
+ source_type=source_type,
+ source_json=source_json,
+ enable_net=form.enable_net.data)
+
+ if flask.g.user.proven:
+ build.memory_reqs = form.memory_reqs.data
+ build.timeout = form.timeout.data
+
+ db.session.commit()
+
+ except (ActionInProgressException, InsufficientRightsException) as e:
+ db.session.rollback()
+ shutil.rmtree(tmp)
+ raise LegacyApiError("Invalid request: {}".format(e))
+
+ output = {"output": "ok",
+ "ids": [build.id],
+ "message": "Build was added to {0}.".format(copr.name)}
+
+ return flask.jsonify(output)
@api_ns.route("/coprs/build_status/<build_id>/", methods=["GET"])
@api_login_required
def build_status(build_id):
- if build_id.isdigit():
- build = builds_logic.BuildsLogic.get(build_id).first()
- else:
- build = None
-
- if build:
- httpcode = 200
- output = {"output": "ok",
- "status": build.state}
- else:
- output = {"output": "notok", "error": "Invalid build"}
- httpcode = 404
-
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ build = ComplexLogic.get_build_safe(build_id)
+ output = {"output": "ok",
+ "status": build.state}
+ return flask.jsonify(output)
@api_ns.route("/coprs/build_detail/<build_id>/", methods=["GET"])
@api_ns.route("/coprs/build/<build_id>/", methods=["GET"])
def build_detail(build_id):
- if build_id.isdigit():
- build = builds_logic.BuildsLogic.get(build_id).first()
- else:
- build = None
-
- if build:
- httpcode = 200
- chroots = {}
- results_by_chroot = {}
- for chroot in build.build_chroots:
- chroots[chroot.name] = chroot.state
- results_by_chroot[chroot.name] = chroot.result_dir_url
-
- built_packages = None
- if build.built_packages:
- built_packages = build.built_packages.split("\n")
-
- output = {
- "output": "ok",
- "status": build.state,
- "project": build.copr.name,
- "owner": build.copr.owner.name,
- "results": build.results,
- "built_pkgs": built_packages,
- "src_version": build.pkg_version,
- "chroots": chroots,
- "submitted_on": build.submitted_on,
- "started_on": build.min_started_on,
- "ended_on": build.ended_on,
- "src_pkg": build.pkgs,
- "submitted_by": build.user.name,
- "results_by_chroot": results_by_chroot
- }
- else:
- output = {"output": "notok", "error": "Invalid build"}
- httpcode = 404
-
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ build = ComplexLogic.get_build_safe(build_id)
+
+ chroots = {}
+ results_by_chroot = {}
+ for chroot in build.build_chroots:
+ chroots[chroot.name] = chroot.state
+ results_by_chroot[chroot.name] = chroot.result_dir_url
+
+ built_packages = None
+ if build.built_packages:
+ built_packages = build.built_packages.split("\n")
+
+ output = {
+ "output": "ok",
+ "status": build.state,
+ "project": build.copr.name,
+ "owner": build.copr.owner.name,
+ "results": build.results,
+ "built_pkgs": built_packages,
+ "src_version": build.pkg_version,
+ "chroots": chroots,
+ "submitted_on": build.submitted_on,
+ "started_on": build.min_started_on,
+ "ended_on": build.ended_on,
+ "src_pkg": build.pkgs,
+ "submitted_by": build.user.name,
+ "results_by_chroot": results_by_chroot
+ }
+ return flask.jsonify(output)
@api_ns.route("/coprs/cancel_build/<build_id>/", methods=["POST"])
@api_login_required
def cancel_build(build_id):
- if build_id.isdigit():
- build = builds_logic.BuildsLogic.get(build_id).first()
- else:
- build = None
+ build = ComplexLogic.get_build_safe(build_id)
- if build:
- try:
- builds_logic.BuildsLogic.cancel_build(flask.g.user, build)
- except exceptions.InsufficientRightsException as e:
- output = {'output': 'notok', 'error': str(e)}
- httpcode = 500
- else:
- db.session.commit()
- httpcode = 200
- output = {'output': 'ok', 'status': "Build canceled"}
- else:
- output = {"output": "notok", "error": "Invalid build"}
- httpcode = 404
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ try:
+ builds_logic.BuildsLogic.cancel_build(flask.g.user, build)
+ db.session.commit()
+ except exceptions.InsufficientRightsException as e:
+ raise LegacyApiError("Invalid request: {}".format(e))
+
+ output = {'output': 'ok', 'status': "Build canceled"}
+ return flask.jsonify(output)
@api_ns.route('/coprs/<username>/<coprname>/modify/', methods=["POST"])
@api_login_required
-def copr_modify(username, coprname):
+@api_req_with_copr
+def copr_modify(copr):
form = forms.CoprModifyForm(csrf_enabled=False)
- copr = CoprsLogic.get(username, coprname).first()
-
- if copr is None:
- output = {'output': 'notok', 'error': 'Invalid copr name or username'}
- httpcode = 500
- elif not form.validate_on_submit():
- output = {'output': 'notok', 'error': 'Invalid request'}
- httpcode = 500
- else:
- # .raw_data needs to be inspected to figure out whether the field
- # was not sent or was sent empty
- if form.description.raw_data and len(form.description.raw_data):
- copr.description = form.description.data
- if form.instructions.raw_data and len(form.instructions.raw_data):
- copr.instructions = form.instructions.data
- if form.repos.raw_data and len(form.repos.raw_data):
- copr.repos = form.repos.data
- if form.disable_createrepo.raw_data and len(form.disable_createrepo.raw_data):
- copr.disable_createrepo = form.disable_createrepo.data
- try:
- CoprsLogic.update(flask.g.user, copr)
- except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as e:
- db.session.rollback()
-
- output = {'output': 'notok', 'error': str(e)}
- httpcode = 500
- else:
- db.session.commit()
+ if not form.validate_on_submit():
+ raise LegacyApiError("Invalid request: bad request parameters")
+
+ # .raw_data needs to be inspected to figure out whether the field
+ # was not sent or was sent empty
+ if form.description.raw_data and len(form.description.raw_data):
+ copr.description = form.description.data
+ if form.instructions.raw_data and len(form.instructions.raw_data):
+ copr.instructions = form.instructions.data
+ if form.repos.raw_data and len(form.repos.raw_data):
+ copr.repos = form.repos.data
+ if form.disable_createrepo.raw_data and len(form.disable_createrepo.raw_data):
+ copr.disable_createrepo = form.disable_createrepo.data
+
+ try:
+ CoprsLogic.update(flask.g.user, copr)
+ db.session.commit()
+ except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as e:
+ db.session.rollback()
+ raise LegacyApiError("Invalid request: {}".format(e))
- output = {
- 'output': 'ok',
- 'description': copr.description,
- 'instructions': copr.instructions,
- 'repos': copr.repos,
- }
- httpcode = 200
+ output = {
+ 'output': 'ok',
+ 'description': copr.description,
+ 'instructions': copr.instructions,
+ 'repos': copr.repos,
+ }
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ return flask.jsonify(output)
@api_ns.route('/coprs/<username>/<coprname>/modify/<chrootname>/', methods=["POST"])
@api_login_required
-def copr_modify_chroot(username, coprname, chrootname):
+@api_req_with_copr
+def copr_modify_chroot(copr, chrootname):
form = forms.ModifyChrootForm(csrf_enabled=False)
- copr = CoprsLogic.get(username, coprname).first()
# chroot = coprs_logic.MockChrootsLogic.get_from_name(chrootname, active_only=True).first()
- chroot = CoprChrootsLogic.get_by_name_safe(copr, chrootname)
-
- if copr is None:
- output = {'output': 'notok', 'error': 'Invalid copr name or username'}
- httpcode = 500
- elif chroot is None:
- output = {'output': 'notok', 'error': 'Invalid chroot name'}
- httpcode = 500
- elif not form.validate_on_submit():
- output = {'output': 'notok', 'error': 'Invalid request'}
- httpcode = 500
+ chroot = ComplexLogic.get_copr_chroot_safe(copr, chrootname)
+
+ if not form.validate_on_submit():
+ raise LegacyApiError("Invalid request: bad request parameters")
else:
coprs_logic.CoprChrootsLogic.update_chroot(flask.g.user, chroot, form.buildroot_pkgs.data)
db.session.commit()
- output = {'output': 'ok', 'buildroot_pkgs': chroot.buildroot_pkgs}
- httpcode = 200
-
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ output = {'output': 'ok', 'buildroot_pkgs': chroot.buildroot_pkgs}
+ return flask.jsonify(output)
@api_ns.route('/coprs/<username>/<coprname>/detail/<chrootname>/', methods=["GET"])
-def copr_chroot_details(username, coprname, chrootname):
- copr = CoprsLogic.get(username, coprname).first()
-
- if copr is None:
- output = {'output': 'notok', 'error': 'Invalid copr name or username'}
- httpcode = 500
- else:
- chroot = CoprChrootsLogic.get_by_name_safe(copr, chrootname)
- if chroot:
- output = {'output': 'ok', 'buildroot_pkgs': chroot.buildroot_pkgs}
- httpcode = 200
- else:
- output = {"output": "notok", "error": "Invalid chroot for this project."}
- httpcode = 404
-
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+@api_req_with_copr
+def copr_chroot_details(copr, chrootname):
+ chroot = ComplexLogic.get_copr_chroot_safe(copr, chrootname)
+ output = {'output': 'ok', 'buildroot_pkgs': chroot.buildroot_pkgs}
+ return flask.jsonify(output)
@api_ns.route("/coprs/search/")
@@ -603,27 +509,22 @@ def api_coprs_search_by_project(project=None):
"""
project = flask.request.args.get("project", None) or project
- httpcode = 200
- if project:
- try:
- query = CoprsLogic.get_multiple_fulltext(project)
+ if not project:
+ raise LegacyApiError("Invalid request")
- repos = query.all()
- output = {"output": "ok", "repos": []}
- for repo in repos:
- output["repos"].append({"username": repo.owner.name,
- "coprname": repo.name,
- "description": repo.description})
- except ValueError as e:
- output = {"output": "nook", "error": str(e)}
+ try:
+ query = CoprsLogic.get_multiple_fulltext(project)
- else:
- output = {"output": "notok", "error": "Invalid request"}
- httpcode = 500
+ repos = query.all()
+ output = {"output": "ok", "repos": []}
+ for repo in repos:
+ output["repos"].append({"username": repo.owner.name,
+ "coprname": repo.name,
+ "description": repo.description})
+ except ValueError as e:
+ raise LegacyApiError("Server error: {}".format(e))
- jsonout = flask.jsonify(output)
- jsonout.status_code = httpcode
- return jsonout
+ return flask.jsonify(output)
@api_ns.route("/playground/list/")
@@ -643,12 +544,8 @@ def playground_list():
@api_ns.route("/coprs/<username>/<coprname>/monitor/", methods=["GET"])
-def monitor(username, coprname):
- copr = CoprsLogic.get(username, coprname).first()
-
+@api_req_with_copr
+def monitor(copr):
monitor_data = builds_logic.BuildsMonitorLogic.get_monitor_data(copr)
output = MonitorWrapper(copr, monitor_data).to_dict()
-
- jsonout = flask.jsonify(output)
- jsonout.status_code = 200
- return jsonout
+ return flask.jsonify(output)
diff --git a/frontend/coprs_frontend/coprs/views/coprs_ns/__init__.py b/frontend/coprs_frontend/coprs/views/coprs_ns/__init__.py
index e149ced..877f30f 100644
--- a/frontend/coprs_frontend/coprs/views/coprs_ns/__init__.py
+++ b/frontend/coprs_frontend/coprs/views/coprs_ns/__init__.py
@@ -8,11 +8,11 @@ from coprs.exceptions import ObjectNotFound, AccessRestricted
coprs_ns = flask.Blueprint("coprs_ns", __name__, url_prefix="/coprs")
-(a)coprs_ns.app_errorhandler(ObjectNotFound)
+(a)coprs_ns.errorhandler(ObjectNotFound)
def handle_404(error):
return page_not_found(error.message)
-(a)coprs_ns.app_errorhandler(AccessRestricted)
+(a)coprs_ns.errorhandler(AccessRestricted)
def handle_403(error):
return access_restricted(error.message)
8 years, 7 months
[copr] master: make group overview page nicer (cf1bf29)
by Miroslav Suchý
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit cf1bf298de721a3d35e1839e8be3808400b87306
Author: Miroslav Suchý <msuchy(a)redhat.com>
Date: Thu Oct 8 12:12:06 2015 +0200
make group overview page nicer
>---------------------------------------------------------------
.../coprs/templates/coprs/show/group.html | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/templates/coprs/show/group.html b/frontend/coprs_frontend/coprs/templates/coprs/show/group.html
index 52e7fa7..db32ef3 100644
--- a/frontend/coprs_frontend/coprs/templates/coprs/show/group.html
+++ b/frontend/coprs_frontend/coprs/templates/coprs/show/group.html
@@ -15,12 +15,12 @@
{% block show_top %}
<div id="profile">
- <h1>Group <strong>@{{group.name|capitalize}}'s</strong> Profile</h1>
- <h2>group is managed in the FAS, under the name
- <a href="{{ fas_group_href(group.fas_name) }}">
- <strong>{{ group.fas_name }}</strong>
- </a>
- </h2>
+ <img src="https://seccdn.libravatar.org/avatar/" alt="" class="avatar">
+ <h1>@{{group.name|capitalize}}'s Group</h1>
+ <p>
+ <a href="https://admin.fedoraproject.org/accounts/group/view/{{ group.fas_name }}" title="{{ group.fas_name }}'s FAS details" target="_blank">FAS details</a> |
+ <a href="https://admin.fedoraproject.org/accounts/group/members/{{ group.fas_name }}" title="{{ group.fas_name }}'s Members" target="_blank">View Members</a>
+ </h>
</div>
<h2>Projects</h2>
8 years, 7 months
[copr] master: [frontend][taiga #68] Support for Group projects: CoprUniqueNameValidator should support group parameter (d0f2a24)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit d0f2a2484e65d98e87c0e727768dfafa021f1689
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Oct 7 17:53:11 2015 +0200
[frontend][taiga #68] Support for Group projects: CoprUniqueNameValidator should support group parameter
>---------------------------------------------------------------
frontend/coprs_frontend/coprs/forms.py | 22 +++++++++++++------
frontend/coprs_frontend/coprs/logic/coprs_logic.py | 11 ++++++++++
frontend/coprs_frontend/coprs/models.py | 2 +-
.../coprs/views/coprs_ns/coprs_general.py | 2 +-
4 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/forms.py b/frontend/coprs_frontend/coprs/forms.py
index b1f9c6c..e58455b 100644
--- a/frontend/coprs_frontend/coprs/forms.py
+++ b/frontend/coprs_frontend/coprs/forms.py
@@ -10,7 +10,7 @@ from flask.ext import wtf
from coprs import constants
from coprs import helpers
from coprs import models
-from coprs.logic import coprs_logic
+from coprs.logic.coprs_logic import CoprsLogic
class UrlListValidator(object):
@@ -83,17 +83,25 @@ class SrpmValidator(object):
class CoprUniqueNameValidator(object):
- def __init__(self, message=None, owner=None):
+ def __init__(self, message=None, owner=None, group=None):
if not message:
- message = "You already have project named '{0}'."
+ if group is None:
+ message = "You already have project named '{}'."
+ else:
+ message = "Group {} ".format(group) + "already have project named '{}'."
self.message = message
if not owner:
owner = flask.g.user
self.owner = owner
+ self.group = group
def __call__(self, form, field):
- existing = coprs_logic.CoprsLogic.exists_for_user(
- self.owner, field.data).first()
+ if self.group:
+ existing = CoprsLogic.exists_for_group(
+ self.group, field.data).first()
+ else:
+ existing = CoprsLogic.exists_for_user(
+ self.owner, field.data).first()
if existing and str(existing.id) != form.id.data:
raise wtforms.ValidationError(self.message.format(field.data))
@@ -152,7 +160,7 @@ class ValueToPermissionNumberFilter(object):
class CoprFormFactory(object):
@staticmethod
- def create_form_cls(mock_chroots=None, owner=None):
+ def create_form_cls(mock_chroots=None, owner=None, group=None):
class F(wtf.Form):
# also use id here, to be able to find out whether user
# is updating a copr if so, we don't want to shout
@@ -168,7 +176,7 @@ class CoprFormFactory(object):
re.compile(r"^[\w.-]+$"),
message="Name must contain only letters,"
"digits, underscores, dashes and dots."),
- CoprUniqueNameValidator(owner=owner),
+ CoprUniqueNameValidator(owner=owner, group=group),
NameNotNumberValidator()
])
diff --git a/frontend/coprs_frontend/coprs/logic/coprs_logic.py b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
index cd9f0e3..9fb4a91 100644
--- a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
@@ -259,6 +259,17 @@ class CoprsLogic(object):
return existing
@classmethod
+ def exists_for_group(cls, group, coprname, incl_deleted=False):
+ existing = (models.Copr.query
+ .filter(models.Copr.name == coprname)
+ .filter(models.Copr.group_id == group.id))
+
+ if not incl_deleted:
+ existing = existing.filter(models.Copr.deleted == False)
+
+ return existing
+
+ @classmethod
def unfinished_blocking_actions_for(cls, copr):
blocking_actions = [helpers.ActionTypeEnum("rename"),
helpers.ActionTypeEnum("delete")]
diff --git a/frontend/coprs_frontend/coprs/models.py b/frontend/coprs_frontend/coprs/models.py
index eb59af6..75e6dc9 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -929,4 +929,4 @@ class Group(db.Model, helpers.Serializer):
return self.__unicode__()
def __unicode__(self):
- return "{0} ({1})".format(self.name, self.fas_name)
+ return "{} (fas: {})".format(self.name, self.fas_name)
diff --git a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
index 0b540c3..9bc0090 100644
--- a/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
+++ b/frontend/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
@@ -147,7 +147,7 @@ def group_copr_add(group_name):
@login_required
def group_copr_new(group_name):
group = ComplexLogic.get_group_by_name_safe(group_name)
- form = forms.CoprFormFactory.create_form_cls()()
+ form = forms.CoprFormFactory.create_form_cls(group=group)()
if form.validate_on_submit():
copr = coprs_logic.CoprsLogic.add(
8 years, 7 months
[copr] master: [frontend][api 2] Partial support for Group projects in the API; need to solve problems of getting group info using token for auth. (f6ed4a9)
by vgologuz@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit f6ed4a9bdfa5dc40c2d5dc9fb3cc49ddf25a4b18
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Oct 7 17:40:44 2015 +0200
[frontend][api 2] Partial support for Group projects in the API; need to solve problems of getting group info using token for auth.
>---------------------------------------------------------------
.../coprs_frontend/coprs/logic/builds_logic.py | 13 +++++++++++++
frontend/coprs_frontend/coprs/logic/coprs_logic.py | 18 ++++++------------
frontend/coprs_frontend/coprs/models.py | 4 ++++
.../coprs/rest_api/resources/build.py | 4 ++++
.../coprs/rest_api/resources/build_task.py | 3 +++
.../coprs/rest_api/resources/project.py | 4 ++++
frontend/coprs_frontend/coprs/rest_api/schemas.py | 5 +++++
7 files changed, 39 insertions(+), 12 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/logic/builds_logic.py b/frontend/coprs_frontend/coprs/logic/builds_logic.py
index 35990b8..34bbc8c 100644
--- a/frontend/coprs_frontend/coprs/logic/builds_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/builds_logic.py
@@ -123,6 +123,10 @@ class BuildsLogic(object):
models.Copr.owner == user)
@classmethod
+ def join_group(cls, query):
+ return query.join(models.Copr).outerjoin(models.Group)
+
+ @classmethod
def get_multiple_by_name(cls, username, coprname):
query = cls.get_multiple()
return (query.join(models.Build.copr)
@@ -523,6 +527,10 @@ class BuildsLogic(object):
else:
return query.filter(models.Build.ended_on.is_(None))
+ @classmethod
+ def filter_by_group_name(cls, query, group_name):
+ return query.filter(models.Group.name == group_name)
+
class BuildChrootsLogic(object):
@classmethod
@@ -543,6 +551,7 @@ class BuildChrootsLogic(object):
.join(models.BuildChroot.mock_chroot)
.join(models.Build.copr)
.join(models.Copr.owner)
+ .outerjoin(models.Group)
)
return query
@@ -562,6 +571,10 @@ class BuildChrootsLogic(object):
def filter_by_state(cls, query, state):
return query.filter(models.BuildChroot.status == StatusEnum(state))
+ @classmethod
+ def filter_by_group_name(cls, query, group_name):
+ return query.filter(models.Group.name == group_name)
+
class BuildsMonitorLogic(object):
@classmethod
diff --git a/frontend/coprs_frontend/coprs/logic/coprs_logic.py b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
index 08305f0..cd9f0e3 100644
--- a/frontend/coprs_frontend/coprs/logic/coprs_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/coprs_logic.py
@@ -103,6 +103,7 @@ class CoprsLogic(object):
query = (
db.session.query(models.Copr)
.join(models.Copr.owner)
+ .outerjoin(models.Group)
.options(db.contains_eager(models.Copr.owner))
)
@@ -125,18 +126,6 @@ class CoprsLogic(object):
query = cls.get_multiple()
return query.filter(models.User.username == username)
- # user_relation="allowed", username=username, with_mock_chroots=False)
- @classmethod
- def get_multiple_allowed_to_username(cls, username):
- query = cls.get_multiple()
- aliased_user = db.aliased(models.User)
-
- return (query.join(models.CoprPermission, models.Copr.copr_permissions)
- .filter(models.CoprPermission.copr_builder ==
- helpers.PermissionEnum('approved'))
- .join(aliased_user, models.CoprPermission.user)
- .filter(aliased_user.username == username))
-
@classmethod
def filter_by_name(cls, query, name):
return query.filter(models.Copr.name == name)
@@ -147,6 +136,11 @@ class CoprsLogic(object):
return query.filter(models.User.username == username)
@classmethod
+ def filter_by_group_name(cls, query, group_name):
+ # should be already joined with the Group table
+ return query.filter(models.Group.name == group_name)
+
+ @classmethod
def join_builds(cls, query):
return (query.outerjoin(models.Copr.builds)
.options(db.contains_eager(models.Copr.builds))
diff --git a/frontend/coprs_frontend/coprs/models.py b/frontend/coprs_frontend/coprs/models.py
index 475bd02..eb59af6 100644
--- a/frontend/coprs_frontend/coprs/models.py
+++ b/frontend/coprs_frontend/coprs/models.py
@@ -208,6 +208,10 @@ class Copr(db.Model, helpers.Serializer):
return self.owner.name
@property
+ def group_name(self):
+ return self.group.name
+
+ @property
def repos_list(self):
"""
Return repos of this copr as a list of strings
diff --git a/frontend/coprs_frontend/coprs/rest_api/resources/build.py b/frontend/coprs_frontend/coprs/rest_api/resources/build.py
index 082bb25..eaf6dbd 100644
--- a/frontend/coprs_frontend/coprs/rest_api/resources/build.py
+++ b/frontend/coprs_frontend/coprs/rest_api/resources/build.py
@@ -23,6 +23,7 @@ class BuildListR(Resource):
parser.add_argument('owner', type=str,)
parser.add_argument('project_id', type=int)
+ parser.add_argument('group', type=str)
parser.add_argument('limit', type=int)
parser.add_argument('offset', type=int)
@@ -41,6 +42,9 @@ class BuildListR(Resource):
else:
query = BuildsLogic.get_multiple()
+ if req_args["group"]:
+ query = BuildsLogic.filter_by_group_name(query, req_args["group"])
+
if req_args["is_finished"] is not None:
is_finished = req_args["is_finished"]
query = BuildsLogic.filter_is_finished(query, is_finished)
diff --git a/frontend/coprs_frontend/coprs/rest_api/resources/build_task.py b/frontend/coprs_frontend/coprs/rest_api/resources/build_task.py
index 4c2109c..45ea6d0 100644
--- a/frontend/coprs_frontend/coprs/rest_api/resources/build_task.py
+++ b/frontend/coprs_frontend/coprs/rest_api/resources/build_task.py
@@ -34,6 +34,7 @@ class BuildTaskListR(Resource):
parser.add_argument('owner', type=str,)
parser.add_argument('project_id', type=int)
parser.add_argument('build_id', type=int)
+ parser.add_argument('group', type=str)
parser.add_argument('limit', type=int)
parser.add_argument('offset', type=int)
@@ -56,6 +57,8 @@ class BuildTaskListR(Resource):
elif self_params.get("owner") is not None:
query = BuildChrootsLogic.filter_by_project_owner_name(
query, self_params["owner"])
+ elif self_params.get("group") is not None:
+ query = BuildChrootsLogic.filter_by_group_name(query, req_args["group"])
state = self_params.get("state")
if state:
diff --git a/frontend/coprs_frontend/coprs/rest_api/resources/project.py b/frontend/coprs_frontend/coprs/rest_api/resources/project.py
index a9a84f0..26b6ab5 100644
--- a/frontend/coprs_frontend/coprs/rest_api/resources/project.py
+++ b/frontend/coprs_frontend/coprs/rest_api/resources/project.py
@@ -53,6 +53,7 @@ class ProjectListR(Resource):
def get(self):
parser = get_request_parser()
parser.add_argument('owner', type=str)
+ parser.add_argument('group', type=str)
parser.add_argument('name', type=str)
parser.add_argument('limit', type=int)
parser.add_argument('offset', type=int)
@@ -70,6 +71,9 @@ class ProjectListR(Resource):
if req_args["owner"]:
query = CoprsLogic.filter_by_owner_name(query, req_args["owner"])
+ if req_args["group"]:
+ query = CoprsLogic.filter_by_group_name(query, req_args["group"])
+
if req_args["name"]:
query = CoprsLogic.filter_by_name(query, req_args["name"])
diff --git a/frontend/coprs_frontend/coprs/rest_api/schemas.py b/frontend/coprs_frontend/coprs/rest_api/schemas.py
index 2144b54..fd17e38 100644
--- a/frontend/coprs_frontend/coprs/rest_api/schemas.py
+++ b/frontend/coprs_frontend/coprs/rest_api/schemas.py
@@ -43,6 +43,7 @@ class SpaceSeparatedList(fields.Field):
else:
return " ".join(value)
+
class BuiltPackages(fields.Field):
""" stored in db as a string:
"python3-marshmallow 2.0.0b5\npython-marshmallow 2.0.0b5"
@@ -85,6 +86,9 @@ class ProjectSchema(Schema):
name = fields.Str(dump_only=True)
owner = fields.Str(attribute="owner_name", dump_only=True)
+ is_a_group_project = fields.Bool(dump_only=True)
+ group = fields.Str(attribute="group_name", dump_only=True)
+
description = fields.Str(allow_none=True)
instructions = fields.Str(allow_none=True)
homepage = fields.Url(allow_none=True)
@@ -111,6 +115,7 @@ class ProjectCreateSchema(ProjectSchema):
"digits, underscores, dashes and dots."
"And starts with letter"),
])
+ group = fields.Str(load_only=True, allow_none=True)
chroots = SpaceSeparatedList(load_only=True, default=list)
8 years, 7 months