#acl +All:read = 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}}} * 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]] <> * Ahem. :o . Alors je suis allé voir de plus près. Le certificat exposé par l'API est [[attachment:note-kfet-2015-serveur.crt|celui-ci]] (expiré depuis bien longtemps), signé par [[attachment:ca.crt|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 [[attachment:statement.asc|dans cette déclaration]]. Happy ? :D -- [[Wiki20-100]] <> * Merci ! :D Même s'il est expiré. -- [[Krokmou]] <> * 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]] <> * En python ? Tu peux regarder le [[http://git.pimeys.fr/?p=bots/basile.git;a=blob;f=nk.py;h=0aafbc16aff64606b07b40e5d5ccf0e6a6ea6e69;hb=HEAD|code]] de Basile qui se connecte à la note -- [[Krokmou]] <> * C'est exactement ce qu'il me fallait, merci ! -- [[Jean-Louis]] <> * On peut le trouver ce code ? Quelqu'un l'a gardé ? -- WikiChanus <> * [[http://gitweb.pimeys.fr/?p=bots/basile.git;a=blob;f=nk.py;h=0aafbc16aff64606b07b40e5d5ccf0e6a6ea6e69;hb=HEAD|Là]] — [[Benjamin]] <>. = 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 [[http://www.json.org/|JSON]] (grâce à la [[http://docs.python.org/2/library/json.html|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", ]}}} Une fois décodé, {{{}}} est un objet qui varie selon la commande. * serveur -> client * {{{ {"retcode": , "errmsg":"un message d'erreur", "msg":} }}} (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 <> * 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]] <> * 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]] <> * 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]] <> * 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, [[https://gitlab.crans.org/bde/note-kfet-2015-serveur/blob/master/serveur/Serveur.py#L419|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 :D (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]] <> ~-(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]] <> * 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]] <> * 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). [[Wiki20-100|20-100]] on peut virer ça ? -- WikiBoudy <> * Que je soit le premier, ça ne me choque pas beaucoup x) -- [[Krokmou]] <> * 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 [[https://gitlab.crans.org/bde/note-client-alpha|le client minimaliste python]], je ne sais trop quoi qui doit plus existe (une ancienne version du client minimaliste ? un truc de monitoring ?), [[https://gitlab.crans.org/bde/note-kfet-2015-django|le client web officiel de la note]], [[http://git.pimeys.fr/?p=bots/basile.git;a=summary|le bot IRC interfacé avec la note]] et le projet digicode ([[https://gitlab.crans.org/nounous/digicode|this]] or [[https://gitlab.crans.org/bde/digicode|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]] <> . 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]] <> * 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]] <> ==== 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. {{{ [, , , ] }}} * pouvant être "bdd" ou "secial" * est à transmettre en clair (d'où l'intérêt du SSL). * est une liste de la forme : * Si on est en "special" ["droit1", "droit2", …] * Si on est en "bdd" [["droit1", "droit2", …], ["surdroit1", "surdroit2", …], ] ( étant un booléen) Le masque est la liste des droits qu'on ne *veut pas* pour cette session. (Habituellement, on mettra donc [[], [], False].) * Il serait bien que login renvoie la liste des droits de l'utilisateur -- ValentinSamir <> * 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]] <> {{{ ["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 [, , ] Ajoute/met à jour un utilisateur spécial. * est en clair. Si on fourni "-", il ne sera pas modifié (ne marche que si on update un utilisateur existant) * 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": , "userid": , "username": , "client": }, 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 : {{{ [, ] }}} * {{{}}} est l'{{{idServer}}} du destinataire * {{{}}} est un message, quelconque du moment qu'il est dé-JSONizable Envoie le message (re-JSONizé) au server numéro {{{}}}, précédé de {{{"Message from () :\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 () :\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, ] * 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 = [, ] 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": , "negatif": , "nom": , "prenom": , "solde": , "terme": , "was": <"pseudo" ou "alias" ou "historique">} }}} où 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 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 [, ]. 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/.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 [, , ] où est l'identifiant de la préinscription qu'on cherche à valider, 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 [, , ] * = montant (en plus de l'adhésion) versé sur la note * = "cheque" ou "especes" ou "virement" ou "soge" * = {"nom": , "prenom": , "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 : {{{ [, ] }}} 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 {{{ [, ] }}} (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 {{{ [, , ] }}} Fait consommer tous les boutons à tous les comptes. Renvoie une liste de {{{[, , ]}}} correspondant au succès des différentes transactions demandées. Si un {{{}}} ou une {{{}}} 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 : {{{ [, , , ] }}} 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 : {{{ [, , , ] }}} Avec {{{ = {"nom":, "prenom":, "banque":, "motif":} }}} Fait un crédit (pas de multi-crédit). {{{}}} 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 : {{{ [, , , ] }}} Avec {{{ = {"nom":, "prenom":, "banque":, "motif":} }}} Fait un retrait (pas de multi-retrait). {{{}}} 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 : {{{ [, , ] }}} 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 {{{ [, , ] }}} 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 : {{{ }}} 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|man]]. Sinon, vous pouvez toujours aller voir la [[http://doc-bde.crans.org/backend/|doc complète]].