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.
Sommaire
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
Je veux bien me connecter en SSL, mais on perds un peu l'intérêt si j'ai pas le certificat (qui n'est plus sur le dépot) -- Krokmou 2018-02-22 20:53:48
Ahem.
Alors je suis allé voir de plus près. Le certificat exposé par l'API est celui-ci (expiré depuis bien longtemps), signé par cette autorité de certification. Et afin de prouver tout ceci (même si les pièces jointes ont bien été uploadées par Wiki20-100), je GPG-signe le tout dans cette déclaration. Happy ? -- Wiki20-100 2018-02-23 13:12:08
Merci ! Même s'il est expiré. -- Krokmou 2018-02-23 15:08:06
J'ai pas vraiment compris, quelqu'un peut me donner un exemple (avec du SSL et du JSON, pour que je comprenne un peu) ? -- Jean-Louis 2018-03-07 15:37:53
En python ? Tu peux regarder le code de Basile qui se connecte à la note -- Krokmou 2018-03-07 21:14:07
C'est exactement ce qu'il me fallait, merci ! -- Jean-Louis 2018-03-08 17:26:31
On peut le trouver ce code ? Quelqu'un l'a gardé ? -- WikiChanus 2019-05-12 10:50:32
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.
- Les droits spécifiques des utilisateurs spéciaux (ils peuvent en plus avoir tous ceux de bdd) :
- die
- who
- adduser
- deluser
- users
- surdroits (= comme si il avait tous les surdroits = il peut modifier les droits bdd)
- speak
- broadcast
- Les droits des utilisateurs bdd : (NB : pour les surdroits c'est exactement la même chose)
- (une catégorie = un alias)
- basic
- myself (c'est un droit particulier qui signifie "je veux pouvoir accéder à mon propre compte". Quand on se connecte "pour laisser" on peut demander à ne pas l'avoir)
- login
- preinscriptions
- dons
- activites
- invites
- note
- get_boutons
- inscriptions
- consos
- get_photo
- transferts
- credits
- retraits
- quick_search
- historique_transactions
- transactions
- comptes
- search
- adherents_weak (permet de modifier un compte mais pas nom/prénom)
- aliases
- historique_pseudo
- update_photo
- boutons
- create_bouton
- update_bouton
- delete_bouton
- admin
- activites_admin
- invites_admin
- adherents_strong
- full_search
- overforced
forced (c'est juste un trick pour que overforced => forced)
- Les droits qui n'ont pas d'alias :
- wei
- overforced
- transactions_admin
- chgpass
- supprimer_compte
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 :
client -> serveur
["commande"]
["commande", <data>]
Une fois décodé, <data> est un objet qui varie selon la commande.
serveur -> client
<taille> {"retcode": <n>, "errmsg":"un message d'erreur", "msg":<objet>}
(oui, il y a un \n après la taille)
où objet est ce qu'on cherche à envoyer et n un code de retour, taille est la taille en octet de la chaîne de caractère représentant le dictionnaire en JSON
Les différents codes de retour possibles
- succès
- 0
- 101 = ce message est broadcasté
- 102 = ce message provient d'un autre client
- 103 = tentative de création d'un bouton déjà existant (donc il n'a pas été dupliqué)
110 = l'invité a été ajouté parce que tu as les droits invites_admin, mais en temps normal il aurait été refusé (précisions dans l'errmsg)
130 = activité validée, mais il y a conflit avec d'autres activités (spécifiées dans l'errmsg)
- 140 = transaction effectuée, mais c'est parce que tu as utilisé forced
- échec
- 1 = hello attendu avant
- 2 = paquet mal formé (non dé-JSON-isable, n'est pas une liste ou une liste de mauvaise taille)
- 3 = la commande attend un paramètre
- 4 = le paramètre est incorrect pour la commande (erreur de type, de nombre de champs, champs interdits ou mal remplis...)
- 5 = login failed
- 6 = tentative de suppression d'un user inexistant
- 7 = tentative de self-suppression
- 8 = tentative d'envoi de message à un client inexistant ou non-joignable
- 9 = challenge RSA non décodable
- 10 = challenge RSA refusé (cooldown non terminé)
- 11 = client incompatible
- 12 = pseudo déjà pris
- 14 = adhésion pour cette année déjà faite
15 = tentative d'adhésion d'un compte d'idbde <= 0
- 16 = pas de manpage correspondante
- 255 = nom de commande hors ascii
- 300 = transaction échouée pour cause de solde trop négatif (et pas assez de droits forcé)
301 = tentative de transaction sur un idbde<0
302 = tentative de transaction avec quantite<0
- 303 = transaction échouée (bouton ou compte inexistant)
- 304 = transaction échouée, compte pas à jour d'adhésion
305 = tentative de transfert avec un montant<0
- 306 = transaction échouée, compte bloqué
- 307 = tentative de transfert concernant un club sans motif
- 310 = ne peut pas valider une transaction valide
- 311 = ne peut pas dévalider une transaction invalide
- 312 = ne peut pas valider/dévalider une transaction cantinvalidate=true
- 313 = ne peut pas valider/dévalider une transaction trop ancienne
- 314 = ne peut pas valider/dévalider une transaction qu'on n'aurait pas pu réaliser
- 402 = la modification de ce mot de passe est impossible (supreme)
- 403 = droits insuffisants
- 404 = Not found (ça peut être la commande, un idbde…)
- 405 = impossible de réinitialiser le mot de passe, trop de comptes correspondants
- 406 = tentative de confirmation de régénération de mot de passe avec un token inexistant
- 407 = tentative de confirmation de régénération de mot de passe avec un token expiré
- 408 = impossible de réinitialiser le mot de passe d'un suprème
- 410 = ne peut pas supprimer le compte, solde non nul
- 411 = ne peut pas supprimer le compte, il a trop de droits
et le "length required" -- ZeldAurore 2013-07-26 14:38:26
J'y ai pensé en rajoutant le 412. Trop tard. Je vais pas changer les codes d'erreur du protocole D'autant que la length est jamais required :p -- Wiki20-100 2013-07-26 18:15:05
- 412 = ne peut pas supprimer le compte, il est déjà supprimé
- 414 = requête trop longue
- 500 = recherche mal formulée, tu demandes à rechercher dans les alias mais tu ne donnes pas d'alias à rechercher
- 501 = recherche mal formulée, tu demandes à rechercher dans l'historique mais tu ne donnes pas d'historique à rechercher
- 503 = ce compte n'a pas le droit de se connecter depuis cette IP
- 555 = Erreur interne (c'est-à-dire, dans la BDD)
- 666 = j'ai crashé sans trop savoir pourquoi, je t'envoie l'erreur (ne devrait pas se produire en prod :D)
Il suffit d'envoyer une liste vide json (ou même un nombre tout seul) pour obtenir cette erreur, pour un truc qui ne devrait pas se produire en prod, c'est un peu triste :p -- Krokmou 2018-01-27 13:49:38
En effet. Le fix devrait être plutôt simple. Par contre pour une liste vide, j'ai personnellement en retour les informations de mon compte. Ce qui est… inattendu. -- Wiki20-100 2018-02-20 17:28:12
Oh nice, je viens de comprendre pourquoi ça me renvoie les data de mon compte : j'utilise des shortcuts pour intéragir avec l'API, et le premier truc que je fais c'est demander les infos de mon compte. Or, sur une liste vide, ce if ne matche pas… et il n'a pas de clause else ! Donc il continue avec l'ancienne valeur de cmd chez moi, donc réexecute la même chose, et chez toi, ça doit probablement hurler que cmd n'existe pas. Bug très sympathique (et complètement harmless, pour ceux que ça aurait inquiété) Quant à l'erreur pour l'entier, c'est que je cherche à prendre la longueur d'un truc dont je n'ai pas vérifié qu'il s'agissait d'une liste. En même temps, tu envoies un message invalide d'un point de vue du protocole, donc il faut pas s'attendre à des miracles ^^ -- Wiki20-100 2018-02-21 08:54:20 (Fix en cours…)
J'envoie des messages invalides par erreur (oui je fais des requêtes API à la main), et je m'attendais pas à un miracle mais à un code d'erreur qui n'a pas comme description ne devrait pas se produire en prod -- Krokmou 2018-02-22 00:22:01
- 701 = activité à durée négative
- 710 = impossible d'inviter à cette activité (non validée, ou pas de liste ou liste imprimée)
- 711 = un special user ne peut pas inviter sans préciser le responsable
- 712 = liste non ouverte à l'heure actuelle
- 713 = responsable en négatif, il ne peut pas inviter
- 714 = vous n'êtes pas le responsable de cet invité, vous ne pouvez pas le supprimer
- 715 = cette personne a déjà été invitée à cette activité
- 716 = cet invité est déjà entré à cette activité, on ne peut pas le supprimer.
- 720 = ne peut pas supprimer l'activité parce qu'il y a des invités
- 721 = ne peut pas supprimer l'activité parce que vous n'êtes pas le responsable
- 722 = ne peut pas supprimer l'activité parce qu'elle est validée
- 731 = ne peut pas modifier l'activité parce que vous n'êtes pas le responsable
- 732 = ne peut pas modifier l'activité parce qu'elle est validée
- 740 = erreur à la génération du pdf de la liste d'invités
- 750 = ne peut pas ouvrir une activité qui ne possède pas de liste d'invités
- 801 = photo trop grosse
- 802 = format de photo non autorisé
- 803 = échec de b64-décodage de la photo
- 804 = erreur pendant le redimensionnement de la photo
- 805 = erreur pendant la conversion en .png
- 806 = erreur pendant la suppression du fichier non-.png
#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"]
C'est bien sympa la version v0.0, mais moi on me dit Clients acceptés : manual, Python Client alpha, test_client, HTTP Django, Basile, digicode, j'en conclut que j'ai pas le droit de me connecter ? -- Krokmou 2018-02-22 20:48:43
C'est bien ce que dit le code, et comme toi je comprends pas trop (et j'en conclue que tu es le premier à essayer d'utiliser l'API). 20-100 on peut virer ça ? -- WikiBoudy 2018-02-23 00:22:17
Que je soit le premier, ça ne me choque pas beaucoup x) -- Krokmou 2018-02-23 02:29:01
Bah tu obéis bien gentiment en disant que tu es "manual" et pas "v0.0" (l'exemple est effectivement outdated, voire n'a jamais été vrai). Les autres sont réellements utilisées, respectivement par le client minimaliste python, je ne sais trop quoi qui doit plus existe (une ancienne version du client minimaliste ? un truc de monitoring ?), le client web officiel de la note, le bot IRC interfacé avec la note et le projet digicode (this or that, dunno).
Je suggère d'ailleurs de parcourir le code dudit client minimaliste, il donne au moins un bon aperçu d'exemples de session d'échange avec le serveur qui marchent correctement. -- Wiki20-100 2018-02-23 12:51:57
On pourrait effectivement faire sauter ce test, parce qu'on ne s'en sert pas après pour discriminer les clients et faire des choses différentes, mais bon, ça coûte pas bien cher de dire qu'on se connecte en manuel pour qu'on nous emmerde pas, et ça serait relou à enlever un peu partout dans le code pour un gain ~nul. -- Wiki20-100 2018-02-23 12:51:57
C'est ce bien ce que je faisait, me connecter en manual, pour des tests ça va, si je fais un vrai client ça sera un peu triste mais au final ça change rien donc bon... Et pour l'example de code, je me servait déjà du code du bot IRC comme example -- Krokmou 2018-02-23 13:49:54
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>]
<auth_type> pouvant être "bdd" ou "secial"
<passwd> est à transmettre en clair (d'où l'intérêt du SSL).
<masque> est une liste de la forme :
- Si on est en "special" ["droit1", "droit2", …]
Si on est en "bdd" [["droit1", "droit2", …], ["surdroit1", "surdroit2", …], <supreme>] (<supreme> étant un booléen)
Il serait bien que login renvoie la liste des droits de l'utilisateur -- ValentinSamir 2012-02-20 13:53:56
Je veux bien, ça demande à peine une ligne de plus dans le code, mais je suis pas sûr que ce soit utile. Jette un œil à la commande mayi. Si tu veux vraiment, je peux le rajouter -- Wiki20-100 2012-07-25 20:53:59
["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.
<password> est en clair. Si on fourni "-", il ne sera pas modifié (ne marche que si on update un utilisateur existant)
<newacl> est une liste de strings qui sont les nouveaux droits de l'user.
["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>]
<id> est l'idServer du destinataire
<message> est un message, quelconque du moment qu'il est dé-JSONizable
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
search
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}>]
- les flags possibles sont :
- o cherche aussi dans les comptes qui ne sont pas à jour d'adhésion
- a affiche les alias
- A cherche aussi dans les alias
- h affiche l'historique des pseudos
- H cherche aussi dans l'historique des pseudos
- b ne cherche que les match sur le début du mot (LIKE 'terme%')
- i insensible à la casse (ILIKE)
- x exact match (LIKE 'terme') (le comportement par défaut est LIKE '%terme%') (x écrase b)
- les fields : idbde, pseudo, nom, prenom, mail, fonction, idcrans, commentaire
- fields nécessitant full_search : tel, adresse, pbsante, numsecu
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).
quick_search
Droit nécessaire : search
data = [<terme>, <flag "o" (facultatif)>]
Effectue une recherche simple :
- sur les pseudos, les alias et l'historique
- avec un filtre begin
- case insensitive
- on a juste le choix de préciser old ou pas (par défaut, on ne va pas chercher les comptes non à jour)
- cas particulier : si term est le forme #qqc, on ne fait rien de tout ça mais on cherche sur les idbde
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" :
- 0 : en positif
1 : solde_negatif > solde > solde_tres_negatif
2 : solde_tres_negatif > solde > solde_pas_plus_negatif (forced sera nécessaire)
3 : solde_pas_plus_negatif > solde (overforced sera nécessaire)
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).
paiement est lui-même une liste [<sur_note>, <type_paiement>, <params>]
<sur_note> = montant (en plus de l'adhésion) versé sur la note
<type_paiement> = "cheque" ou "especes" ou "virement" ou "soge"
<params> = {"nom": <nom>, "prenom": <prenom>, "banque": <banque>}
["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>]
Avec <params_pay> = {"nom":<nom>, "prenom":<prénom>, "banque":<banque>, "motif":<motif>}
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>]
Avec <params_pay> = {"nom":<nom>, "prenom":<prénom>, "banque":<banque>, "motif":<motif>}
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
- historique_pseudo
- search_historique_pseudo
- chgpass
- update_compte
- get_last_modified_photo
- get_photo
- get_preinscription
- get_preinscriptions
- del_preinscription
- get_default_pseudo
- readherer
- get_boutons_categories
- get_un_bouton
- get_clubs
- historique_transactions
- valider_transaction
- devalider_transaction
- get_activites
- add_activite
- update_activite
- del_activite
- valider_activite
- devalider_activite
- add_invite
- del_invite
- get_invites
- django_get_accessible_pages
- mayi
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.