]> git.ipfire.org Git - pbs.git/commitdiff
repos: Make repositories editable
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 25 Jun 2022 14:50:33 +0000 (14:50 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 25 Jun 2022 14:50:33 +0000 (14:50 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/buildservice/repository.py
src/templates/repos/edit.html [new file with mode: 0644]
src/templates/repos/show.html
src/templates/repository-edit.html [deleted file]
src/web/__init__.py
src/web/base.py
src/web/handlers.py
src/web/repos.py

index 76dd36ed1e475098ceb1b16795b72ea271ee4462..64d734a2cf46ff394e95ee031675856b74674a2d 100644 (file)
@@ -175,7 +175,6 @@ dist_templates_DATA = \
        src/templates/package-detail-list.html \
        src/templates/package-properties.html \
        src/templates/queue.html \
-       src/templates/repository-edit.html \
        src/templates/search.html \
        src/templates/source-list.html \
        src/templates/updates-index.html \
@@ -311,6 +310,7 @@ templates_modules_selectdir = $(templates_modulesdir)/select
 
 dist_templates_repos_DATA = \
        src/templates/repos/builds.html \
+       src/templates/repos/edit.html \
        src/templates/repos/show.html
 
 templates_reposdir = $(templatesdir)/repos
index 4fded82830183c17715b9bb7c769fd9d879c63b6..b72c0990894b12b37024009ef2309b83ec552436 100644 (file)
@@ -147,6 +147,21 @@ class Repository(base.DataObject):
 
        owner = property(get_owner, set_owner)
 
+       def has_perm(self, user):
+               """
+                       Returns True if the user has permission to manage this repository
+               """
+               # Admins can edit anything
+               if user.is_admin():
+                       return True
+
+               # If the user owns this repository, they may edit it
+               if self.owner == user:
+                       return True
+
+               # Nope
+               return False
+
        # Slug
 
        @property
@@ -214,10 +229,16 @@ class Repository(base.DataObject):
 
                return "\n".join(lines)
 
-       @property
-       def name(self):
+       # Name
+
+       def get_name(self):
                return self.data.name
 
+       def set_name(self, name):
+               self._set_attribute("name", name)
+
+       name = property(get_name, set_name)
+
        @property
        def summary(self):
                lines = self.description.splitlines()
@@ -227,10 +248,16 @@ class Repository(base.DataObject):
 
                return "N/A"
 
-       @property
-       def description(self):
+       # Description
+
+       def get_description(self):
                return self.data.description
 
+       def set_description(self, description):
+               self._set_attribute("description", description or "")
+
+       description = property(get_description, set_description)
+
        @property
        def parent_id(self):
                return self.data.parent_id
@@ -256,6 +283,16 @@ class Repository(base.DataObject):
 
        mirrored = property(get_mirrored, set_mirrored)
 
+       # Listed
+
+       def get_listed(self):
+               return self.data.listed
+
+       def set_listed(self, listed):
+               self._set_attribute("listed", listed)
+
+       listed = property(get_listed, set_listed)
+
        def _log_build(self, action, build, from_repo=None, to_repo=None, user=None):
                user_id = None
                if user:
diff --git a/src/templates/repos/edit.html b/src/templates/repos/edit.html
new file mode 100644 (file)
index 0000000..c09059a
--- /dev/null
@@ -0,0 +1,101 @@
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Repositories") }} - {{ repo }} - {{ _("Edit") }}{% end block %}
+
+{% block container %}
+       <nav aria-label="{{ _("You are here:") }}" role="navigation">
+               <ul class="breadcrumbs">
+                       <li>
+                               <a href="/">{{ _("Home") }}</a>
+                       </li>
+                       {% if repo.owner %}
+                               <li>
+                                       <a href="/users">{{ _("Users") }}</a>
+                               </li>
+                               <li>
+                                       <a href="/users/{{ repo.owner.name }}">{{ repo.owner }}</a>
+                               </li>
+                       {% else %}
+                               <li>
+                                       <a href="/distros">{{ _("Distributions") }}</a>
+                               </li>
+                               <li>
+                                       <a href="/distros/{{ repo.distro.slug }}">{{ repo.distro }}</a>
+                               </li>
+                       {% end %}
+                       <li>
+                               {{ _("Repositories") }}
+                       </li>
+                       <li>
+                               <a href="{% if repo.owner %}/users/{{ repo.owner.name }}{% else %}/distros/{{ repo.distro.slug }}{% end %}/repos/{{ repo.slug }}">
+                                       {{ repo }}
+                               </a>
+                       </li>
+                       <li>
+                               <span class="show-for-sr">{{ _("Current") }}: </span> {{ _("Edit") }}
+                       </li>
+               </ul>
+       </nav>
+
+       <div class="grid-x grid-padding-x">
+               <div class="cell large-6 float-center">
+                       <form method="POST" action="">
+                               <div class="callout">
+                                       {% raw xsrf_form_html() %}
+
+                                       <label>
+                                               {{ _("Name") }}
+
+                                               <input type="text" name="name" value="{{ repo.name }}" required>
+                                       </label>
+
+                                       <label>
+                                               {{ _("Description") }}
+
+                                               <textarea name="description" rows="6" placeholder="{{ _("Description") }}"
+                                                       aria-describedby="description-help">{{ repo.description }}</textarea>
+                                       </label>
+
+                                       <p class="help-text" id="description-help">
+                                               {{ _("Describe what this repository will contain") }}
+                                       </p>
+
+                                       <label>
+                                               {{ _("Priority") }}
+
+                                               <input type="number" name="priority" value="{{ repo.priority }}"
+                                                       min="0" max="1000">
+                                       </label>
+
+                                       {% if repo.owner %}
+                                               <input id="listed" type="checkbox" name="listed"
+                                                       {% if repo.listed %}checked{% end %} aria-describedby="listed-help">
+
+                                               <label for="listed">{{ _("Listed") }}</label>
+
+                                               <p class="help-text" id="listed-help">
+                                                       {{ _("By unchecking this box, you can hide this repository from being listed") }}
+                                               </p>
+                                       {% end %}
+
+                                       {% if current_user.is_admin() %}
+                                               <input id="mirrored" type="checkbox" name="mirrored"
+                                                       {% if repo.mirrored %}checked{% end %} aria-describedby="mirrored-help">
+
+                                               <label for="mirrored">{{ _("Enable Mirroring") }}</label>
+
+                                               <p class="help-text" id="mirrored-help">
+                                                       {{ _("If enabled, this repository will be made available on mirror servers") }}
+                                               </p>
+                                       {% end %}
+                               </div>
+
+                               <button class="success button expanded" type="submit">{{ _("Save") }}</button>
+
+                               <a class="small danger button expanded" href="{% if repo.owner %}/users/{{ repo.owner.name }}{% else %}/distros/{{ repo.distro.slug }}{% end %}/repos/{{ repo.slug }}/delete">
+                                       {{ _("Delete") }}
+                               </a>
+                       </form>
+               </div>
+       </div>
+{% end block %}
index 312e462b820e49fd1e7551f2ab70f77cf0a62b99..424f2c2a9e2c3469283bf0d1dafd486ae215c55b 100644 (file)
                </div>
        {% end %}
 
-       <a class="secondary small expanded button" href="{% if repo.owner %}/users/{{ repo.owner.name }}{% else %}/distros/{{ distro.slug }}{% end %}/repos/{{ repo.slug }}.repo">
+       <a class="secondary expanded button" href="{% if repo.owner %}/users/{{ repo.owner.name }}{% else %}/distros/{{ distro.slug }}{% end %}/repos/{{ repo.slug }}.repo">
                {{ _("Download Configuration") }}
        </a>
 
+       <a class="warning expanded button" href="{% if repo.owner %}/users/{{ repo.owner.name }}{% else %}/distros/{{ distro.slug }}{% end %}/repos/{{ repo.slug }}/edit">
+               {{ _("Edit") }}
+       </a>
+
        <div class="callout">
                <h5>{{ _("Statistics") }}</h5>
 
diff --git a/src/templates/repository-edit.html b/src/templates/repository-edit.html
deleted file mode 100644 (file)
index 33ce65a..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}{{ _("Edit repository %s") % repo.name }}{% end block %}
-
-{% block body %}
-       <h1>
-               {{ _("Edit repository %s") % repo.name }}
-               <span>- {{ _("Distribution") }}: {{ distro.name }}</span>
-       </h1>
-
-       <form method="post" action="">
-               {% raw xsrf_form_html() %}
-               <table class="form form3">
-                       <tr>
-                               <td class="col1">{{ _("Name") }}</td>
-                               <td class="col2">
-                                       <input name="name" type="text" value="{{ repo.name }}" />
-                               </td>
-                               <td class="col3">
-                                       {{ _("The name of the repository.") }}
-                                       {{ _("Must only contain of the lowercase characters.") }}
-                               </td>
-                       </tr>
-                       <tr>
-                               <td class="col1">{{ _("Description") }}</td>
-                               <td colspan="2">                
-                                       <textarea name="description">{{ repo.description }}</textarea>
-                               </td>
-                       </tr>
-               </table>
-               <div style="clear: both;">&nbsp;</div>
-
-               <h2>{{ _("Score settings") }}</h2>
-               <p>
-                       {{ _("These settings configure the automatic score feature.") }}
-                       {{ _("Builds that gained a certain score are moved to the next repository automatically and removed if the score is too bad.") }}
-               </p>
-               <table class="form form3">
-                       <tr>
-                               <td class="col1">{{ _("Needed score") }}</td>
-                               <td class="col2">
-                                       <input name="name" type="text" value="{{ repo.score_needed }}" />
-                               </td>
-                               <td class="col3">
-                                       {{ _("The score that is needed for builds to automatically be moved into this repository.") }}
-                               </td>
-                       </tr>
-                       <tr>
-                               <td class="col1">{{ _("Minimum time") }}</td>
-                               <td class="col2">
-                                       <input name="name" type="text" value="{{ repo.time_min }}" />
-                               </td>
-                               <td class="col3">
-                                       {{ _("Every build must stay a minimum time in a repository.") }}
-                                       {{ _("This is to ensure that a package gets tested well.") }}
-                                       {{ _("Enter zero to disable the feature.") }}
-                               </td>
-                       </tr>
-                       <tr>
-                               <td class="col1">{{ _("Maximum time") }}</td>
-                               <td class="col2">
-                                       <input name="name" type="text" value="{{ repo.time_max }}" />
-                               </td>
-                               <td class="col3">
-                                       {{ _("If a build is more than a certain amount of time in a repository, it will automatically be removed.") }}
-                                       {{ _("This is to ensure that packages are not forgotten to be pushed.") }}
-                                       {{ _("Enter zero to disable the feature.") }}
-                               </td>
-                       </tr>
-               </table>
-               <div style="clear: both;">&nbsp;</div>
-
-               <h2>{{ _("Build settings") }}</h2>
-               <table class="form form3">
-                       <tr>
-                               <td class="col1">{{ _("Use package for builds?") }}</td>
-                               <td class="col2">
-                                       <input type="checkbox" name="enabled_for_builds" {%if repo.enabled_for_builds %}checked="checked"{% end %} />
-                               </td>
-                               <td class="col3">
-                                       {{ _("Should the package be selected for builds by default?") }}
-                                       {{ _("Use with caution!") }}
-                               </td>
-                       </tr>
-               </table>
-               <div style="clear: both;">&nbsp;</div>
-
-               <table class="form form3">
-                       <tr>
-                               <td colspan="3" class="buttons">
-                                       <input type="submit" value="{{ _("Save") }}" />
-                               </td>
-                       </tr>
-               </table>
-       </form>
-{% end block %}
index 891729446e04d6ba6b7b4b293ccdc88842500024..e537b8892ef7f358241504f5bbd582cba330d6fd 100644 (file)
@@ -117,6 +117,8 @@ class Application(tornado.web.Application):
                                repos.ConfigHandler),
                        (r"/users/(?P<user_slug>\w+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/builds",
                                repos.BuildsHandler),
+                       (r"/users/(?P<user_slug>\w+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/edit",
+                               repos.EditHandler),
                        (r"/users/(?P<user_slug>\w+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/mirrorlist",
                                repos.MirrorlistHandler),
                        (r"/user/(\w+)/impersonate", users.UserImpersonateHandler),
@@ -169,12 +171,11 @@ class Application(tornado.web.Application):
                                repos.ConfigHandler),
                        (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/builds",
                                repos.BuildsHandler),
+                       (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/edit",
+                               repos.EditHandler),
                        (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/mirrorlist",
                                repos.MirrorlistHandler),
 
-                       (r"/distro/([A-Za-z0-9\-\.]+)/repo/([A-Za-z0-9\-]+)/edit",
-                               RepositoryEditHandler),
-
                        (r"/distro/([A-Za-z0-9\-\.]+)/source/([A-Za-z0-9\-\.]+)",
                                distributions.DistroSourceDetailHandler),
                        (r"/distro/([A-Za-z0-9\-\.]+)/source/([A-Za-z0-9\-\.]+)/commits",
index ae4992fbda58e2ec7045ea5ec290c7ef636cd4a7..59eaec2fc5f7c1c01a9bbcf103b4f40ed196b9d3 100644 (file)
@@ -110,9 +110,18 @@ class BaseHandler(tornado.web.RequestHandler):
 
        # Typed Arguments
 
+       def get_argument_bool(self, name):
+               arg = self.get_argument(name, default=None)
+
+               return arg == "on"
+
        def get_argument_int(self, *args, **kwargs):
                arg = self.get_argument(*args, **kwargs)
 
+               # Return nothing
+               if not arg:
+                       return None
+
                try:
                        return int(arg)
                except (TypeError, ValueError):
index c7abfb1d99d357aa29a3a6282d9fe0d41614e8b0..794ed5ed59de846745af8920304fe4b28f6a09ff 100644 (file)
@@ -33,22 +33,6 @@ class LogHandler(base.BaseHandler):
                self.render("log.html", log=self.backend.log)
 
 
-class RepositoryEditHandler(base.BaseHandler):
-       @tornado.web.authenticated
-       def get(self, distro, repo):
-               distro = self.backend.distros.get_by_slug(distro)
-               if not distro:
-                       raise tornado.web.HTTPError(404)
-
-               repo = distro.get_repo(repo)
-               if not repo:
-                       raise tornado.web.HTTPError(404)
-
-               # XXX check if user has permissions to do this
-
-               self.render("repository-edit.html", distro=distro, repo=repo)
-
-
 class RepoActionHandler(base.BaseHandler):
        @tornado.web.authenticated
        def post(self, type):
index e77d3f6e91605838dec34d746037334f414c69d1..02edd7659514bc212d13412416a8fca4dd68df98 100644 (file)
@@ -80,6 +80,48 @@ class ConfigHandler(BaseHandler):
                self.finish(config)
 
 
+class EditHandler(BaseHandler):
+       @tornado.web.authenticated
+       def get(self, **kwargs):
+               # Fetch the repository
+               repo = self._get_repo(**kwargs)
+
+               # Check for permissions
+               if not repo.has_perm(self.current_user):
+                       raise tornado.web.HTTPError(403, "%s cannot edit this repository" % self.current_user)
+
+               self.render("repos/edit.html", repo=repo)
+
+       @tornado.web.authenticated
+       def post(self, **kwargs):
+               # Fetch the repository
+               repo = self._get_repo(**kwargs)
+
+               # Check for permissions
+               if not repo.has_perm(self.current_user):
+                       raise tornado.web.HTTPError(403, "%s cannot edit this repository" % self.current_user)
+
+               with self.db.transaction():
+                       repo.name        = self.get_argument("name")
+                       repo.description = self.get_argument("description", None)
+                       repo.priority    = self.get_argument_int("priority", None)
+
+                       # Attributes for custom repositories
+                       if repo.owner:
+                               repo.listed = self.get_argument_bool("listed")
+
+                       # Admin settings
+                       if self.current_user.is_admin():
+                               repo.mirrored = self.get_argument_bool("mirrored")
+
+               if repo.owner:
+                       url = "/users/%s/repos/%s" % (repo.owner.name, repo.slug)
+               else:
+                       url = "/distros/%s/repos/%s" % (repo.distro.slug, repo.slug)
+
+               self.redirect(url)
+
+
 class MirrorlistHandler(BaseHandler):
        def get(self, **kwargs):
                # Fetch the repository