-
-
Save adrianlzt/f30a4d7004671c5eea5b21ba6ef967d3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
Este git hook pre-receive comprueba si el usuario que hace push esta presente | |
en el array de key "dsmctools" dentro del fichero /usuarios.json. | |
En este caso, puede hacer push de cualquier fichero. | |
Si no pertenece a este grupo, se comprueba el path de los ficheros pusheados, | |
dando por hecho que el primer directorio es el nombre del proyecto. | |
Se comprueba si el usuario pertenece al dicho proyecto (array con clave el | |
nombre del proyecto). | |
""" | |
import sys | |
import os | |
import subprocess | |
import json | |
def git(args, **kwargs): | |
environ = os.environ.copy() | |
if 'repo' in kwargs: | |
environ['GIT_DIR'] = kwargs['repo'] | |
if 'work' in kwargs: | |
environ['GIT_WORK_TREE'] = kwargs['work'] | |
proc = subprocess.Popen(args, stdout=subprocess.PIPE, env=environ) | |
return proc.communicate() | |
def get_changed_files(base, commit, ref, **kw): | |
""" | |
Obtenemos los ficheros modificados entre el los commit 'base' y 'commit' | |
Si base es 00000... es que tenemos una rama nueva, y compararemos 'commit' con el commit anterior al primer commit de la rama | |
""" | |
results = "" | |
if base == "0000000000000000000000000000000000000000": | |
(results2, code) = git(('git', 'rev-list', commit, '--not', '--branches=*'), **kw) | |
lista_commits = results2.decode("utf-8").strip().split('\n') | |
(results, code) = git(('git', 'diff', '--numstat', '--name-only', "%s^..%s" % (lista_commits[-1], lista_commits[0])), **kw) | |
else: | |
(results, code) = git(('git', 'diff', '--numstat', '--name-only', "%s..%s" % (base, commit)), **kw) | |
return results.decode("utf-8").strip().split('\n') | |
def get_new_file(filename, commit): | |
(results, code) = git(('git', 'show', '%s:%s' % (commit, filename))) | |
return results.decode("utf-8") | |
def get_permissions(): | |
(results, code) = git(('git', 'show', '%s:%s' % ("HEAD", "usuarios.json"))) | |
permData = json.loads(results.decode("utf-8")) | |
return permData | |
def check_if_user_can_modify_file(user, git_file): | |
try: | |
projects = get_permissions() | |
except Exception as ex: | |
# En caso de fallo no contemplado, dejamos pushear | |
print("Excepcion leyendo el fichero de permissions: %s" % ex) | |
return True | |
# Si el usuario pertenece al grupo dsmctools, paso libre | |
try: | |
projects.get("dsmctools").index(user) | |
print("Perteneces a DSMC Tools. Edicion libre") | |
return True | |
except ValueError as ex: | |
# El usuario no pertenece al grupo dsmctools | |
pass | |
except AttributeError as ex: | |
# No existe el grupo dsmctools | |
pass | |
except Exception as ex: | |
# En caso de fallo no contemplado, dejamos pushear | |
print("Excepcion comprobando si un usuario pertenece a dsmctools: " + ex) | |
return True | |
# Obtenemos el directorio (proyecto) del fichero que se esta modificando | |
project = git_file.split("/")[0] | |
try: | |
projects.get(project).index(user) | |
return True | |
except ValueError as ex: | |
# El usuario no pertenece al grupo del fichero que quiere modificar | |
pass | |
except AttributeError as ex: | |
# No existe el grupo para ese proyecto | |
print("Pedir a [email protected] que se cree el mapeo para este proyecto") | |
pass | |
print("Lo siento, pero tu usuario no tiene permisos para editar el fichero '" + git_file + "'") | |
return False | |
if os.environ['GITHUB_REPO_NAME'] != "dsmc/dsmc-monitoring": | |
print("Has configurado el pre-receive hook para dsmc/dsmc-monitoring. Seguramente te hayas equivocado") | |
sys.exit(0) | |
repo = os.getcwd() | |
basedir = os.path.join(repo, "..") | |
line = sys.stdin.read() | |
(base, commit, ref) = line.strip().split() | |
#print("base: ", base) | |
#print("commit: ", commit) | |
#print("ref: ", ref) | |
modified = get_changed_files(base, commit, ref) | |
#print("Ficheros modificados: %s" % modified) | |
user = os.environ['GITHUB_USER_LOGIN'] | |
# Si no es github enterprise usar os.environ['USER'] | |
print("Chequeando permisos de push para el usuario '%s'" % user) | |
for fname in modified: | |
if not check_if_user_can_modify_file(user, fname): | |
sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment