diff --git a/.gitignore b/.gitignore index 13b0528..3b764c7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ auth-keys-gen +cgit-config-gen bash-gitonly *.so *.o diff --git a/Makefile b/Makefile index ac179d3..c8ad7a6 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: all install -all: bash-gitonly pam_oath_key.so auth-keys-gen +all: bash-gitonly pam_oath_key.so auth-keys-gen cgit-config-gen argvt.o: nargv/nargv.c gcc -c nargv/nargv.c -o argvt.o @@ -12,6 +12,8 @@ pam_oath_key.so: pam_oath_key.c auth-keys-gen: authKeysPg.c gcc authKeysPg.c -o auth-keys-gen -L/usr/server/postgresql/lib -I/usr/server/postgresql/include -lpq +cgit-config-gen: cgit-config-gen.c + gcc cgit-config-gen.c -o cgit-config-gen -L/usr/server/postgresql/lib -I/usr/server/postgresql/include -lpq $(CFLAGS) install: all @@ -19,3 +21,4 @@ install: all cp pam_oath_key.so /usr/libraries/lib/security/ cp bash-gitonly /srv/git/bin cp auth-keys-gen /srv/etc/auth-git-keys + cp cgit-config-gen /srv/etc/cgit-config-gen diff --git a/cgit-config-gen.c b/cgit-config-gen.c new file mode 100644 index 0000000..76144fe --- /dev/null +++ b/cgit-config-gen.c @@ -0,0 +1,107 @@ +#include +#include +#include "libpq-fe.h" +#include + +#include +#include +#include +#include + +#define BDD_PASS_FILE "/srv/bdd/pipi-system.pass" +#define BDD_CONN_LENGTH 255 + +#define CGITRC_BASE_FILE "/srv/etc/cgitrc.base" + +int +main(int argc, char **argv) +{ + char connInfo[BDD_CONN_LENGTH] = "dbname='pipi' user=pipisys password='"; + FILE *dbPassFile; + char ch; + int pos = strlen(connInfo); + + PGconn *conn; + PGresult *res; + int i; + + // Affichage de la première partie du rc + FILE* fd = fopen(CGITRC_BASE_FILE, "rb"); + if (fd == NULL) { + fprintf(stderr,"Z'arrive pas à ouvrir le fichier '%s' : %s\n", CGITRC_BASE_FILE, strerror(errno)); + return 1; + } + char c = fgetc(fd); + while (!feof(fd)) + { + printf ("%c", c); + c = fgetc(fd); + } + fclose(fd); + + printf("## Maintenant les repos ##\n\n"); + + // Récupère le mdp à la BDD + dbPassFile = fopen(BDD_PASS_FILE,"r"); + if (dbPassFile == NULL) { + fprintf(stderr,"Cannot open file %s, on peut pas se connecter à la base de données pour lister les clés en tant que %d -> fopen error %d\n", BDD_PASS_FILE,geteuid(),errno); + return 1; + } + while (feof(dbPassFile)) + { + connInfo[pos] = fgetc(dbPassFile); + pos++; + } + fclose(dbPassFile); + connInfo[pos] = '\''; + + // Connecte à la BDD + conn = PQconnectdb(connInfo); + if (PQstatus(conn) != CONNECTION_OK) + { + fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn)); + PQfinish(conn); + return 1; + } + res = PQexec(conn, + "SELECT pg_catalog.set_config('search_path', '', false)"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return 1; + } + PQclear(res); + + + // Demande les données à la BDD + const char const * sqlParamValues[] = {"1"}; + res = PQexecParams(conn,"SELECT path,owner,description,logoUrl FROM git.\"ReadableRepos\"($1)",1,NULL,sqlParamValues,NULL,NULL,1); + if (PQresultStatus(res) != PGRES_TUPLES_OK) { + fprintf(stderr,"Impossible de lancer la requête SQL pour la liste des repos: %s",PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return 1; + } + + // Renvoie le résultat à travers stdout + for (i = 0; i < PQntuples(res); i++) + { + printf("repo.url=%s\n",PQgetvalue(res,i,0)); + printf("repo.path=/srv/git/%s\n",PQgetvalue(res,i,0)); + if(PQgetisnull(res,i,1)!=1) + printf("repo.owner=%s\n",PQgetvalue(res,i,1)); + if(PQgetisnull(res,i,2)!=1) + printf("repo.desc=%s\n",PQgetvalue(res,i,2)); + if(PQgetisnull(res,i,3)!=1) + printf("repo.logo=%s\n",PQgetvalue(res,i,3)); + printf("\n"); + } + + + PQclear(res); + PQfinish(conn); + return 0; +} + diff --git a/sql/AccessType.sql b/sql/AccessType.sql new file mode 100644 index 0000000..4fd0b3c --- /dev/null +++ b/sql/AccessType.sql @@ -0,0 +1,59 @@ +CREATE OR REPLACE FUNCTION git."AccessType" ( + gituserid integer, + gitrepo character varying +) +RETURNS git.gitrepoaccesstype +LANGUAGE plpgsql +AS $code$ +DECLARE + selectedrepo git.gitrepoaccesstype; +BEGIN + + /* user.repo */ + SELECT MAX("accessType") + INTO selectedrepo + FROM git.perms + JOIN git.repos ON "repoID"=repos."ID" + WHERE repos.path=gitrepo AND "userID"=gituserid; + + RETURN selectedrepo; + + IF selectedrepo != NULL + THEN RETURN selectedrepo; + END IF; + + /* groupe.repo */ + SELECT MAX('accessType') + INTO selectedrepo + FROM git.perms + JOIN git.repos ON repoID=repos."ID" + JOIN git.appartenances ON appartenances."groupeID"=-perms."userID" + WHERE repos.path=gitrepo AND appartenances.utilisateurID=gituserid; + + IF selectedrepo != NULL + THEN RETURN selectedrepo; + END IF; + + /* user.repoGroup */ + SELECT MAX('accessType') + INTO selectedrepo + FROM git.perms + JOIN git.repos ON repoID=-repos."groupeID" + WHERE repos.path=gitrepo AND userID=gituserid; + + IF selectedrepo != NULL + THEN RETURN selectedrepo; + END IF; + + /* groupe.repoGroupe */ + SELECT MAX('accessType') + INTO selectedrepo + FROM git.perms + JOIN git.appartenances ON appartenances."groupeID"=-perms."userID" + JOIN git.repos ON "repoID"=-repos."groupeID" + WHERE repos.path=gitrepo AND userID=gituserid; + + RETURN selectedRepo; + +END +$code$ diff --git a/sql/ReadableRepos.sql b/sql/ReadableRepos.sql new file mode 100644 index 0000000..12cf75e --- /dev/null +++ b/sql/ReadableRepos.sql @@ -0,0 +1,43 @@ +CREATE OR REPLACE FUNCTION git."ReadableRepos" ( + gituserid integer +) +RETURNS table( + ID integer, + path character varying(255), + name character varying(255), + owner character varying(255), + description character varying, + groupeID integer, + logoUrl character varying(255) +) +LANGUAGE plpgsql +AS $code$ +BEGIN + RETURN QUERY + /* user.repo */ + SELECT repos.* + FROM git.perms + JOIN git.repos ON "repoID"=repos."ID" + WHERE "accessType">'READ' AND "userID"=gituserid + UNION + /* groupe.repo */ + SELECT repos.* + FROM git.perms + JOIN git.repos ON "repoID"=repos."ID" + JOIN git.appartenances ON appartenances."groupeID"=-perms."userID" + WHERE "accessType">'READ' AND appartenances."utilisateurID"=gituserid + UNION + /* user.repoGroup */ + SELECT repos.* + FROM git.perms + JOIN git.repos ON "repoID"=-repos."groupeID" + WHERE "accessType">'READ' AND "userID"=gituserid + UNION + /* groupe.repoGroupe */ + SELECT repos.* + FROM git.perms + JOIN git.appartenances ON appartenances."groupeID"=-perms."userID" + JOIN git.repos ON "repoID"=-repos."groupeID" + WHERE "accessType">'READ' AND "userID"=gituserid; +END +$code$