ui-repolist: add ability to control what repos a user see
The auth-filter works at the repository level but still shows
repositories in ui-repolist. This change allows you to limit what
a user sees based on the STDOUT of a command.
The existing filter code doesn't handle the capture of stdout, so
a new mechanism was created just for this.
Signed-off-by: Andy Doan <andy.doan@linaro.org>
diff --git a/cgit.c b/cgit.c
index c4320f0..3a14622 100644
--- a/cgit.c
+++ b/cgit.c
@@ -227,6 +227,8 @@
ctx.cfg.owner_filter = cgit_new_filter(value, OWNER);
else if (!strcmp(name, "auth-filter"))
ctx.cfg.auth_filter = cgit_new_filter(value, AUTH);
+ else if (!strcmp(name, "allowed-repos-cmd"))
+ ctx.cfg.allowed_repos_cmd = xstrdup(expand_macros(value));
else if (!strcmp(name, "embedded"))
ctx.cfg.embedded = atoi(value);
else if (!strcmp(name, "max-atom-items"))
diff --git a/cgit.h b/cgit.h
index 7ec46b4..50e65f8 100644
--- a/cgit.h
+++ b/cgit.h
@@ -270,6 +270,7 @@
struct cgit_filter *email_filter;
struct cgit_filter *owner_filter;
struct cgit_filter *auth_filter;
+ char *allowed_repos_cmd;
};
struct cgit_page {
diff --git a/ui-repolist.c b/ui-repolist.c
index 9c0c47a..ce7c8cd 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -10,6 +10,14 @@
#include "ui-repolist.h"
#include "html.h"
#include "ui-shared.h"
+#include "run-command.h"
+
+
+struct allowed_repos {
+ const char *name;
+ struct allowed_repos *next;
+};
+
static time_t read_agefile(const char *path)
{
@@ -97,6 +105,38 @@
return 0;
}
+static struct allowed_repos* find_allowed_repos(void)
+{
+ struct strbuf buf = STRBUF_INIT;
+ struct child_process cp = CHILD_PROCESS_INIT;
+ const char *argv[] = {ctx.cfg.allowed_repos_cmd, NULL};
+ char *result, *token;
+ struct allowed_repos *allowed = NULL, *prev=NULL;
+
+ cp.argv = argv;
+ cp.no_stdin = 1;
+
+ if (!capture_command(&cp, &buf, 1024)) {
+ strbuf_trim(&buf);
+ result = strbuf_detach(&buf, NULL);
+
+ token = strtok(result, "\n");
+ while( token != NULL ) {
+ if (!prev) {
+ allowed = xmalloc(sizeof(*allowed));
+ prev = allowed;
+ } else {
+ prev->next = xmalloc(sizeof(*allowed));
+ prev = prev->next;
+ }
+ prev->name = token;
+ prev->next = NULL;
+ token = strtok(NULL, "\n");
+ }
+ }
+ return allowed;
+}
+
static int is_in_url(struct cgit_repo *repo)
{
if (!ctx.qry.url)
@@ -106,21 +146,28 @@
return 0;
}
-static int is_visible(struct cgit_repo *repo)
+static int is_visible(struct allowed_repos *allowed, struct cgit_repo *repo)
{
if (repo->hide || repo->ignore)
return 0;
if (!(is_match(repo) && is_in_url(repo)))
return 0;
+ if (ctx.cfg.allowed_repos_cmd) {
+ while(allowed) {
+ if (!strcmp(repo->url, allowed->name))
+ return 1;
+ allowed = allowed->next;
+ }
+ return 0;
+ }
return 1;
}
-static int any_repos_visible(void)
+static int any_repos_visible(struct allowed_repos *allowed)
{
int i;
-
for (i = 0; i < cgit_repolist.count; i++) {
- if (is_visible(&cgit_repolist.repos[i]))
+ if (is_visible(allowed, &cgit_repolist.repos[i]))
return 1;
}
return 0;
@@ -272,8 +319,12 @@
char *section;
char *repourl;
int sorted = 0;
+ struct allowed_repos * allowed = NULL;
- if (!any_repos_visible()) {
+ if (ctx.cfg.allowed_repos_cmd)
+ allowed = find_allowed_repos();
+
+ if (!any_repos_visible(allowed)) {
cgit_print_error_page(404, "Not found", "No repositories found");
return;
}
@@ -296,7 +347,7 @@
html("<table summary='repository list' class='list nowrap'>");
for (i = 0; i < cgit_repolist.count; i++) {
ctx.repo = &cgit_repolist.repos[i];
- if (!is_visible(ctx.repo))
+ if (!is_visible(allowed, ctx.repo))
continue;
hits++;
if (hits <= ctx.qry.ofs)