CransWiki:

API du serveur d'écoute de la NoteKfet2015

Cette page explique le protocole de communication entre le serveur de la NoteKfet2015 et un de ses clients. Si ce n'est pas ce que vous cherchiez, allez demander votre chemin ici.

Codé en python, le serveur tourne en permanence et écoute sur le port 4242 (par défaut) et traite les requêtes envoyées par les clients.

Il est le seul à s'interfacer avec la base PostgreSQL, et tous les clients doivent lui parler à lui. Il est responsable de l'authentification et du système de droits. Les clients (comme l'interface HTTP) n'ont pas à s'en soucier et peuvent éventuellement faire croire à l'utilisateur qu'il a plus/moins de droit que ce qu'il a réellement.

Toute communication se fait en TLS. Avant même un hello ou un login, le serveur passe la connexion en TLS et le client doit le faire aussi s'il veut pouvoir communiquer correctement. La clé et le certificat sont stockés dans les chemins d'accès correspondants (keyfile (qui est (ou sera) enlevé du dépôt git) et certfile) modifiables dans config.py

Système de droits

Il y a des utilisateurs spéciaux (leurs informations sont stockées en JSON dans le fichier dont le path est dans config.authfile) et des utilisateurs normaux stockés dans la base de données.

Les droits sont stockés pour chaque utilisateur sous forme d'une chaîne de caractères, où les droits sont séparés par des virgules et un droit est un mot matchant [a-z][a-z_]+. Exemple de contenu du champ droits : "login,search"

Des aliases servent à donner plusieurs droits en un seul. (On ne peut pas faire d'alias d'alias)

En général ils ont le même nom que la fonction qu'ils permettent d'exécuter.

NB : les alias "root" et "all", hardcodés, donnent tous les droits.

Dans les faits, les droits sont chargés en mémoire depuis la BDD au moment du login et sont conservés dans une variable python. Certaines actions (notamment une modification des droits) vident cette variable qui sera donc repuisé dans la BDD dès qu'il y en aura besoin. [Tout ceci n'étant valable que pour les users bdd, les special users gardent leur droits pendant toute une session.]

API

Protocole de communication

Protocole

Tous les objets sont envoyés entre le client et le serveur encodés en JSON (grâce à la librairie python du même nom).

Le protocole est asymétrique. Voici la descriptions des objets envoyés dans chaque sens :

Les différents codes de retour possibles

#TODO : documenter les codes > 900 qui sont liés au WEI dans WeiFonctions.py

Les commandes

Commandes basiques

hello

Droit nécessaire : aucun (même pas d'authentification nécessaire)

Attend en paramètre une chaîne de caractère qui est la version du client.

["hello", "v0.0"]

help

Droit nécessaire : aucun (même pas d'authentification nécessaire)

N'attend aucun paramètre.

Renvoie la liste des commandes existantes.

["help"] 

man

Droit nécessaire : aucun (même pas d'authentification nécessaire)

Attend en paramètre une chaîne de caractère.

Renvoie de l'aide sur la commande fournie.

["man", "login"] 

login

Droit nécessaire : login

Attend en paramètre une liste.  [<pseudo>, <passwd>, <auth_type>, <masque>] 

["login", ["20-100", "plop", "bdd", [[], [], true]]] 

En se connectant de cette façon, on ne pourra pas utiliser les droits supreme, même si on les a.

myconnection

Droit nécessaire : aucun (même pas d'authentification nécessaire)

N'attend aucun paramètre.

Renvoie les informations sur la connection courante: ip, port émetteur (+ userid, username s'il y a lieu).

["myconnection"] 

Commandes des utilisateurs spéciaux

die

Droit nécessaire : die (utilisateurs spéciaux uniquement)

N'attend aucun paramètre.

Éteint le serveur.

["die"] 

adduser

Droit nécessaire : adduser (utilisateurs spéciaux uniquement)

Attend en paramètre une liste [<pseudo>, <password>, <newacl>]

Ajoute/met à jour un utilisateur spécial.

["adduser", ["vincent", "plop", ["login", "die"]]] 

deluser

Droit nécessaire : deluser (utilisateurs spéciaux uniquement)

Attend en paramètre un string (le pseudo de l'user).

Supprime l'utilisateur spécial (NB : on ne peut pas se supprimer soi-même).

["deluser", "vincent"] 

users

Droit nécessaire : users (utilisateurs spéciaux uniquement)

N'attend aucun paramètre.

Donne la liste des utilisateurs spéciaux existants avec leurs droits.

["users"] 

Commandes who

who

Droit nécessaire : who (utilisateurs spéciaux uniquement)

N'attend aucun paramètre.

Donne la liste des clients connectés avec leur ip,port (+ userid, username s'il y a lieu).

N'est en réalité qu'un alias de "whowith {}"

["who"] 

whowith

Droit nécessaire : who (utilisateurs spéciaux uniquement)

Attend en paramètre un dico {"ip": <listip>, "userid": <listid>, "username": <listnames>, "client": <listclient>}, chacune des clés pouvant être absente (en revanche, fournir une des trois listes vide serait stupide).

Donne la liste des clients connectés qui vérifient la propriété : (client.ip in listip) AND (client.userid in listid) AND (client.username in listnames) AND (client.version in listclient). Si une clé est omise, aucun filtrage n'est fait sur ce paramètre.

["whowith", {"userid": ["vincent"], "client": ["manual"]}] 

whospecial

Droit nécessaire : who (utilisateurs spéciaux uniquement)

N'attend aucun paramètre.

Alias de  ["who", {"userid": ["special"]}] 

whomanualclient

Droit nécessaire : who (utilisateurs spéciaux uniquement)

N'attend aucun paramètre.

Alias de ["who", {"client": ["manual"]}] 

whohttpclient

Droit nécessaire : who (utilisateurs spéciaux uniquement)

N'attend aucun paramètre.

Alias de  ["who", {"client": ["http"]}] 

whononeclient

Droit nécessaire : who (utilisateurs spéciaux uniquement)

N'attend aucun paramètre.

Alias de  ["who", {"client": ["None"]}] 

Commandes de communications

client_speak

Droit nécessaire : speak (utilisateurs spéciaux uniquement)

Attend en paramètre :  [<id>, <message>] 

Envoie le message (re-JSONizé) au server numéro <id>, précédé de "Message from <username> (<idServer>) :\n".

Répond "Done" ou "Ce client n'existe pas ou a été déconnecté.".

["client_speak", [1, "Salut n°1"]] 

client_broadcast

Droit nécessaire : broadcast (utilisateurs spéciaux uniquement)

Attend en paramètre : un message, quelconque du moment qu'il est dé-JSONizable

Envoie le message (re-JSONizé) à tous les clients connectés précédé de "Broadcast from <username> (<idServer>) :\n"

["client_broadcast", "Attention tout le monde, je reboote le serveur."] 

Les fonctions de note

Recherche et affichages

Droit nécessaire : search (ou full_search pour certains champs)

Fait une recherche sur les comptes.

Peut nécessiter les droits full_search en fonction des champs demandés.

data = [flags, liste_de_fields, terme_de_recherche] OU data = [flags, <dico {field: terme_de_recherche}>]

Une recherche est faite sur tous les champs avec les options précisées par les flags puis est renvoyée la liste des [idbde, nom, prenom, pseudo, mail, solde, section] qui matchent. Attention, si plusieurs champs de recherche sont fournis, le test est une disjonction.

Les idbde<0 sont ignorés.

["search", ["ai", {"idbde": "2", "nom": "hello"}]] 

Renverra tous les comptes (en affichant leurs aliases) dont l'idbde contient un 2 OU dont le nom contient "hello" (sans tenir compte de la casse).

["search", ["bi", ["pseudo", "nom"], "Ch"]] 

Renverra tous les comptes dont le nom OU le pseudo commence par "ch" (aussi case insensitive).

Droit nécessaire : search

data = [<terme>, <flag "o" (facultatif)>]

Effectue une recherche simple :

Ne renvoie que ce qui a matché et l'idbde correspondant et l'appelle "terme" (que ce soit un pseudo, alias ou historique)

Rajoute également un champ "was" qui peut être "pseudo", "alias" ou "historique" pour qu'on puisse savoir ce qui a matché (pour une mise en forme différente, par exemple). Donne également des infos sur la négativité du compte, dans le champ "negatif" :

Les idbde<0 sont ignorés.

["quick_search", ["plo"]] 

Renvoie une liste de dictionnaires :  {"idbde": <idbde>, "negatif": <n \in [[0, 3]]>, "nom": <nom>, "prenom": <prenom>, "solde": <solde>, "terme": <matching_term>, "was": <"pseudo" ou "alias" ou "historique">}  où <mathcing_terme> commence par "plo" (sans tenir compte de la casse).

["quick_search", ["#3", "o"]] 

Renvoie une liste de dictionnaires analogues mais où "was" sera forcément "idbde" et <matching_terme> commencera par 3. De plus, des comptes qui ne sont pas à jour d'adhésion sont susceptibles d'être renvoyés.

whoami

Droit nécessaire : myself

N'attend aucun paramètre.

Renvoie la totalité des données de l'utilisateur courant (pas la photo). Pas de vérification de droits puisqu'un user peut tout voir sur son compte.

Ça marche aussi pour un user spécial même si ce qui est affiché est loin d'être passionnant…

["whoami"] 

compte ou adherent

Droit nécessaire : adherents_weak

Attend en paramètre : un entier

Renvoie les informations détaillées du compte.

N'affiche pas numsecu ni pbsante si l'utilisateur n'a pas les droits wei.

["compte", 1] 

Modifications

update_photo

Droit nécessaire : adherents_weak (si c'est la photo d'un autre) ou myself si c'est la sienne

Attend en paramètre une liste [<idbde>, <taille>].

Ensuite il faut lui envoyer (avec un deuxième send) la base64 du fichier qu'on veut envoyer. (elle a intérêt à ne pas dépasser taille, sinon on va avoir des problèmes…)

Le fichier est décodé à l'arrivée, convertit en png et sotcké dans /home/note/Note_Kfet_2015_server/photos/<idbde>.png

La liste des format acceptés est dans config.py (ImageMagick est utilisé pour faire la conversion).

["update_photo", [1, "VGhlIGFuc3dlciB0byBsaWZlLCB0aGUgdW5pdmVyc2UgYW5kIGV2ZXJ5dGhpbmcuCg==", "bmp"]] 

preinscrire

Droit nécessaire : preinscriptions (inclus dans "basic")

Attend en paramètre un dictionnaire du genre {"nom":"Dupond","prenom":"Jean","mail":"dupond@crans.org", ...} Seuls les champs "nom", "prenom" et "mail" sont obligatoires.

Enregistre une préinscription (dans la table du même nom). Remplace tous les champs non renseignés par leur valeur par défaut.

Vérifie que nom et prenom sont non vides et les met en casse .title(), et fait une vérification (assez faible) sur le format de l'adresse mail.

["preinscrire", {"type": personne", "nom": "Dupond", "prenom": "Jean", "mail": "plouf@crans.org", "section": "42A0", "sexe": "M", "normalien": true}] 

inscrire

Droit nécessaire : inscriptions (inclus dans "note")

Attend en paramètre une liste [<preid>, <dico>, <paiement>] où <preid> est l'identifiant de la préinscription qu'on cherche à valider, <dico> contient des données sur l'adhérent (dont au moins "wei" (booléen), et "annee" (entier), ainsi que "section" si il n'a pas été fourni à la préinscription).

["inscrire" [1, {"wei": true, "annee": 2015, "adresse": "G999"}, [1000, "cheque", {"nom": "Dupond", "prenom": "Jean", "banque": "Sogé"}]]] 

alias

Droit nécessaire : aliases

Attend en paramètre :  [<idbde>, <alias>] 

Ajoute un alias à un compte.

["alias", [5, "toto"]] 

unalias

Droit nécessaire : aliases

Attend en paramètre : un alias ou un idbde

Enlève un alias, ou tous les alias d'un compte.

["unalias", "toto"] 

["unalias", 5] 

Boutons

get_boutons

Droit nécessaire : get_boutons (inclus dans "note")

Attend en paramètre une liste  [<term>, <categ>]  (deux strings).

Renvoie tous les boutons (sous forme d'une liste de dictionnaires) contenant term dans leur label et qui sont dans la catégorie categ. Si term est vide, il laisse tout passer, si categ est vide alors aucun tri n'est fait dans les catégories.

["get_boutons", ["", ""]] 

Récupère tous les boutons

create_bouton

Droit nécessaire : create_bouton (inclus dans "boutons")

Attend en paramètre un dico contenant les clés "label", "montant", "destinataire" et "categorie".

Ajoute un bouton à la table (sauf si categorie n'existe pas encore, si destinataire n'est pas un club, ou si un bouton identique existe déjà).

["create_bouton", {"label": "Pinte", "montant": 200, "destinataire": 0, "categorie": "Alcool"}] 

update_bouton

Droit nécessaire : update_bouton (inclus dans "boutons")

Attend en paramètre un dico contenant au moins la clé "id".

Update un bouton avec le dico (à condition qu'il existe).

["update_bouton", {"id": 3, "montant": 400, "destinataire": 5}] 

delete_bouton

Droit nécessaire : delete_bouton (inclus dans "boutons")

Attend en paramètre un entier. (id)

Supprime le bouton n°id.

["delete_bouton", 3] 

Transactions

consos

Droit nécessaire : consos (inclus dans "note") + forced ou overforced pour débiter des gens en négatif.

Attend en paramètre un liste de  [<idbouton>, <idcompte>, <quantité>] 

Fait consommer tous les boutons à tous les comptes. Renvoie une liste de [<retcode>, <idbde>, <errmsg>] correspondant au succès des différentes transactions demandées.

Si un <idcompte> ou une <quantité> est <0 alors un message d'insulte est envoyé et rien n'est fait.

Si un compte ou un bouton n'existe pas, un message d'insulte est envoyé (à chaque fois qu'on passe dessus) mais le reste est effectué.

Si des comptes sont en négatif (au sens de la config), des avertissements sont envoyés et les transactions correspondantes sont enregistrées en valide=false (le reste continue à s'exécuter). Les consos sont faites dans l'ordre de la liste, donc un adhérent peut devenir négatif au milieu.

["consos", [[1, 1, 3], [3, 6, 1]]] 

transferts

Droit nécessaire : transferts (inclus dans "note") + forced ou overforced pour débiter des gens en négatif.

Attend en paramètre :  [<liste_d'emetteurs>, <liste_de_destinataires>, <montant>, <motif>] 

Effectue le transfert de chacun des émetteurs vers chacun des destinataires.

Si un compte n'existe pas, un message d'insulte est envoyé (à chaque fois qu'on passe dessus) mais le reste est effectué.

Si des comptes sont en négatif (au sens de la config), des avertissements sont envoyés et les transactions correspondantes sont enregistrées en valide=false (le reste continue à s'exécuter). Les transferts sont faits dans l'ordre de la liste, donc un adhérent peut devenir négatif au milieu.

["transferts", [[1, 3], [2, 4], 1500, "Hanjo"]] 

crediter ou credit

Droit nécessaire : credits

Attend en paramètre :  [<iddestinataire>, <montant>, <typ_paiement>, <params_pay>] 

Fait un crédit (pas de multi-crédit).

<params_pay> peut rester vide pour un crédit espèces; dans tous les cas, "motif" est facultatif.

["crediter", [1, 10000, "cheque", {"nom" : "Passoire", "prenom" : "Toto", "banque" : "Sogé", "motif" : "Toto a eu raison d'adhérer au BDE"}]] 

retirer ou retrait

Droit nécessaire : retraits

Attend en paramètre :  [<idemetteur>, <montant>, <typ_paiement>, <params_pay>] 

Fait un retrait (pas de multi-retrait).

<params_pay> peut rester vide pour un retrait espèces; dans tous les cas, "motif" est facultatif.

["retirer", [1, 450, "especes", {"motif" : "Pour aller payer un prima"}]] 

dons

Droit nécessaire : dons

Attend en paramètre :  [<liste_de_destinataires>, <montant>, <motif>] 

Effectue des dons de l'utilisateur courant vers les destinataires (pas accessible aux special users). On ne peut pas faire un don si son solde après transaction est <0 (0 hardcodé, contrairement au solde "être en négatif").

["dons", [[2065], "2000", "Participation anniversaire Kfet"] 

invitations

Droit nécessaire : invitations (inclus dans note)

Attend en paramètre une liste  [<idresponsable>, <idinvité>, <idactivité>] 

Permet de payer les invitations à une activité.

["invitations", [5352, 10207, 2027] 

Activités

get_activite

Droit nécessaire : aucun par défaut (pas d'authentification nécessaire) + activites_admin pour voir les activités passées et celles des autres

Attend en paramètre :  <id> 

Transmet les informations sur l'activité demandée.

["get_activite", 2000] 

Pas encore documentées mais ça viendra

Si vous tenez absolument à savoir tout de suite comment ça marche, vous pouvez essayer en tâtonnant, utiliser man. Sinon, vous pouvez toujours aller voir la doc complète.

CransWiki: NoteKfet/NoteKfet2015/API (dernière édition le 2020-01-16 18:12:56 par WikiPollion)