From 167e9887825ca5ddc9e1138826c0f8fb5a784343 Mon Sep 17 00:00:00 2001
From: Vincent Le Gallic <legallic@crans.org>
Date: Fri, 12 Apr 2013 20:57:48 +0200
Subject: [PATCH] Doc sphinx-like serveur

---
 clientconfig.example.py |  5 +++-
 server                  |  1 +
 server.py               | 56 ++++++++++++++++++-----------------------
 serverconfig.example.py | 20 +++++++++------
 4 files changed, 42 insertions(+), 40 deletions(-)

diff --git a/clientconfig.example.py b/clientconfig.example.py
index 3d8ea7f..12f7739 100755
--- a/clientconfig.example.py
+++ b/clientconfig.example.py
@@ -1,8 +1,12 @@
 #!/usr/bin/env python
 # -*- encoding: utf-8 -*-
 
+"""Configuration du client cranspasswords"""
+
 import os
 
+#: Serveurs distants utilisables,
+#: avec la commande distante à exécuter et l'username sur le serveur
 servers = {
     'default': {
         'server_cmd': ['/usr/bin/ssh', 'vert.adm.crans.org',\
@@ -17,4 +21,3 @@ servers = {
                                   # n'ayant pas le même login sur leur pc
     }
 }
-
diff --git a/server b/server
index ac12868..10f6457 100755
--- a/server
+++ b/server
@@ -1,2 +1,3 @@
 #!/bin/bash
+# sudo-wrapper pour exécuter cranspasswords côté serveur
 sudo /root/cranspasswords/server.py $*
diff --git a/server.py b/server.py
index 8599921..a32ee5c 100755
--- a/server.py
+++ b/server.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 # -*- encoding: utf-8 -*-
-"""cranspasswords-server.py: Serveur pour cranspasswords"""
+
+"""Serveur pour cranspasswords"""
 
 import glob
 import os
@@ -18,22 +19,23 @@ MYUID = pwd.getpwuid(os.getuid())[0]
 if MYUID == 'root':
     MYUID = os.environ['SUDO_USER']
 
-def validate(roles,mode='r'):
-    """Valide que l'appelant appartient bien aux roles précisés
+def validate(roles, mode='r'):
+    """Vérifie que l'appelant appartient bien aux roles précisés
     Si mode mode='w', recherche un rôle en écriture
     """
     for role in roles:
-        if mode == 'w': role+='-w'
+        if mode == 'w':
+            role += '-w'
         if ROLES.has_key(role) and MYUID in ROLES[role]:
             return True
     return False
 
-def getpath(filename,backup=False):
-    """Récupère le chemin du fichier `filename'"""
-    return os.path.join(STORE, '%s.%s' % (filename,'bak' if backup else 'json'))
+def getpath(filename, backup=False):
+    """Récupère le chemin du fichier ``filename``"""
+    return os.path.join(STORE, '%s.%s' % (filename, 'bak' if backup else 'json'))
 
 def writefile(filename, contents):
-    """Écrit le fichier de manière sécure"""
+    """Écrit le fichier avec les bons droits UNIX"""
     os.umask(0077)
     f = open(filename, 'w')
     f.write(contents)
@@ -44,26 +46,22 @@ def listroles():
     return ROLES
 
 def listkeys():
-    """Liste les uid et les clés correspondantes"""
+    """Liste les usernames et les (mail, fingerprint) correspondants"""
     return KEYS
 
 def listfiles():
     """Liste les fichiers dans l'espace de stockage, et les roles qui peuvent y accéder"""
     os.chdir(STORE)
-
+    
     filenames = glob.glob('*.json')
-
     files = {}
-    
     for filename in filenames:
         file_dict = json.loads(open(filename).read())
         files[filename[:-5]] = file_dict["roles"]
-        
     return files
     
 def getfile(filename):
-    """Récupère le fichier `filename'"""
-
+    """Récupère le fichier ``filename``"""
     filepath = getpath(filename)
     try:
         obj = json.loads(open(filepath).read())
@@ -75,19 +73,16 @@ def getfile(filename):
      
 
 def putfile(filename):
-    """Écrit le fichier `filename' avec les données reçues sur stdin."""
-
+    """Écrit le fichier ``filename`` avec les données reçues sur stdin."""
     filepath = getpath(filename)
-    
     stdin = sys.stdin.read()
     parsed_stdin = json.loads(stdin)
-
     try:
         roles = parsed_stdin['roles']
         contents = parsed_stdin['contents']
     except KeyError:
         return False
-
+    
     try:
         old = getfile(filename)
         oldroles = old['roles']
@@ -98,9 +93,9 @@ def putfile(filename):
         if not validate(oldroles,'w'):
             return False
     
-    notification("Modification de %s" % filename,\
-    "Le fichier %s a été modifié par %s." %\
-        (filename,MYUID),filename,old)
+    notification("Modification de %s" % filename,
+        "Le fichier %s a été modifié par %s." % (filename, MYUID),
+        filename, old)
 
 
     writefile(filepath, json.dumps({'roles': roles, 'contents': contents}))
@@ -123,22 +118,22 @@ def rmfile(filename):
             return False
     return True
 
-def notification(subject,corps,fname,old):
-    back = open(getpath(fname,True),'a')
+def backup(fname, old):
+    """Backupe l'ancienne version du fichier"""
+    back = open(getpath(fname, backup=True), 'a')
     back.write(json.dumps(old))
     back.write('\n')
     back.write('* %s: %s\n' % (str(datetime.datetime.now()),corps)) 
     back.close()
-
-    # Puis envoi du message
+    
+def notification(subject, corps, fname, old):
+    """Envoie par mail une notification de changement de fichier"""
     conn = smtplib.SMTP('localhost')
     frommail = CRANSP_MAIL
     tomail = DEST_MAIL
     msg = MIMEMultipart(_charset="utf-8")
     msg['Subject'] = subject
     msg['X-Mailer'] = "cranspasswords"
-    # me == the sender's email address
-    # family = the list of all recipients' email addresses
     msg['From'] = CRANSP_MAIL
     msg['To'] = DEST_MAIL
     msg.preamble = "cranspasswords report"
@@ -167,7 +162,7 @@ if __name__ == "__main__":
         filename = argv[1]
     except IndexError:
         pass
-
+    
     if command == "listroles":
         print json.dumps(listroles())
     elif command == "listkeys":
@@ -185,4 +180,3 @@ if __name__ == "__main__":
             print json.dumps(rmfile(filename))
         else:
             sys.exit(1)
-    
diff --git a/serverconfig.example.py b/serverconfig.example.py
index 414ce6a..10d68d6 100755
--- a/serverconfig.example.py
+++ b/serverconfig.example.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 # -*- encoding: utf-8 -*-
+
 """ Configuration Serveur de cranspasswords.
 Sont définis ici les utilisateurs et les rôles associés.
 Ce fichier est donné à titre d'exemple, mais n'est PAS
@@ -7,19 +8,19 @@ utilisé lorsque fonctionnement en mode client.
 Dans le futur, sera remplacé par une connexion ldap.
 """
 
+#: Répertoire de stockage des mots de passe
 STORE = '/root/cranspasswords/db/'
-""" Répertoire de stockage """
 
+#: Ce serveur est-il read-only (on ne peut pas y modifier les mots de passe)
 READONLY = False
-""" Ce serveur est-il read-only (on ne peut pas y modifier les mots de passe) """
 
+#: Expéditeur du mail de notification
 CRANSP_MAIL = "cranspasswords <root@crans.org>"
-""" Expéditeur du mail de notification """
 
+#: Destinataire du mail de notification
 DEST_MAIL = "root@crans.org"
-""" Destinataire du mail de notification """
-
 
+#: Mapping des utilisateurs et de leurs (mail, fingerprint GPG)
 KEYS = {
     'aza-vallina': ('Damien.Aza-Vallina@crans.org', None),
     'becue': ('becue@crans.org', '9AE04D986400E3B67528F4930D442664194974E2'),
@@ -62,11 +63,12 @@ KEYS = {
     'kviard': ('kviard@crans.org', None)
 }
 
-# Les variables suivantes sont utilisées pour définir le dictionnaire des
-# rôles.
+#: Les variables suivantes sont utilisées pour définir le dictionnaire des
+#: rôles.
 RTC=[
     "iffrig"
     ]
+#: Liste des usernames des nounous
 NOUNOUS=RTC+[
     "blockelet",
     "becue",
@@ -86,12 +88,14 @@ NOUNOUS=RTC+[
     ]
 
 # Autogen:
+#: Liste des usernames des apprentis
 APPRENTIS=['grande', 'bonaque', 'moisy-mabille', 'baste', 'duplouy', 'besson', 'pvincent', 'quelennec', 'pommeret', 'guiraud', 'serrano', 'kherouf', 'randazzo', 'tilquin', 'lasseri', 'epalle', 'soret', 'gstalter', 'kviard']
 
+#: Liste des usernames des membres du CA
 CA=[
 ]
 
-## Les vrais rôles !
+#: Les roles utilisés pour savoir qui a le droit le lire/écrire quoi
 ROLES = {
     "ca": CA,
     "ca-w": CA,
-- 
GitLab