Créez votre propre SaaS sur Linux avec Vely


  • Français


  • Vely combine les hautes performances et la faible empreinte du C avec la facilité d’utilisation et la sécurité améliorée des langages comme PHP. C’est un logiciel gratuit et open source, sous licence GPLv3 et LGPL 3 pour les bibliothèques, vous pouvez donc même créer des logiciels commerciaux avec.

    Utilisation de Vely pour le SaaS

    Vous pouvez utiliser Vely pour créer une application Web mutualisée que vous pouvez exécuter sur Internet en tant que logiciel en tant que service (SaaS). Chaque utilisateur dispose d’un espace de données complètement séparé de tout autre.

    Dans cet exemple d’application Web, un utilisateur peut s’inscrire à un service de bloc-notes pour créer des notes, puis les afficher et les supprimer. Il démontre plusieurs intégrations technologiques en seulement 310 lignes de code dans sept fichiers source. Les technologies incluent :

    • MariaDB
    • Navigateur Web
    • apache
    • Prises Unix

    Comment ça fonctionne

    Voici comment l’application fonctionne du point de vue de l’utilisateur. Un code pas à pas suit les images.

    L’application permet à un utilisateur de créer une nouvelle connexion en spécifiant une adresse e-mail et un mot de passe. Vous pouvez les styliser comme bon vous semble, comme avec CSS :

    (Sergio Mijatovic, CC BY-SA 4.0)

    Vérifiez l’adresse e-mail de l’utilisateur :

    (Sergio Mijatovic, CC BY-SA 4.0)

    Chaque utilisateur se connecte avec son nom d’utilisateur et son mot de passe uniques :

    (Sergio Mijatovic, CC BY-SA 4.0)

    Une fois connecté, un utilisateur peut ajouter une note :

    (Sergio Mijatovic, CC BY-SA 4.0)

    Un utilisateur peut obtenir une liste de notes :

    (Sergio Mijatovic, CC BY-SA 4.0)

    L’application demande confirmation avant de supprimer une note :

    (Sergio Mijatovic, CC BY-SA 4.0)

    Après confirmation de l’utilisateur, la note est supprimée :

    (Sergio Mijatovic, CC BY-SA 4.0)

    Conditions préalables à l’installation

    Suivez les instructions d’installation sur Vely.dev. Il s’agit d’un processus rapide qui utilise des outils d’empaquetage standard, tels que DNF, APT, Pacman ou Zypper.

    Comme ils font partie de cet exemple, vous devez installer Apache en tant que serveur Web et MariaDB en tant que base de données.

    Après avoir installé Vely, activez la coloration syntaxique dans Vim si vous l’utilisez :

    vv -m

    Obtenir le code source

    Le code source de cette application SaaS de démonstration fait partie de l’installation de Vely. C’est une bonne idée de créer un répertoire de code source séparé pour chaque application (et vous pouvez le nommer comme vous le souhaitez). Dans ce cas, décompresser le code source le fait pour vous :

    $ tar xvf $(vv -o)/examples/multitenant_SaaS.tar.gz
    $ cd multitenant_SaaS

    Par défaut, l’application s’appelle multitenant_SaaSmais vous pouvez l’appeler n’importe quoi (si vous faites cela, changez-le partout).

    Configurer l’application

    La toute première étape consiste à créer une application. C’est simple à faire avec Vely’s vf utilitaire:

    $ sudo vf -i -u $(whoami) multitenant_SaaS

    Cette commande crée un nouvel accueil d’application (/var/lib/vv/multitenant_SaaS) et effectue la configuration de l’application pour vous. Cela signifie principalement créer divers sous-répertoires dans le dossier de départ et attribuer des privilèges. Dans ce cas, seul l’utilisateur actuel (le résultat de whoami) possède les répertoires, avec les privilèges 0700, ce qui garantit que personne d’autre n’a accès aux fichiers.

    Configurer la base de données

    Avant de procéder à tout codage, vous avez besoin d’un emplacement pour stocker les informations utilisées par l’application. Tout d’abord, créez une base de données MariaDB appelée db_multitenant_SaaSpropriété de l’utilisateur vely avec mot de passe your_password. Vous pouvez modifier n’importe laquelle de ces valeurs, mais n’oubliez pas de les modifier partout dans cet exemple.

    Connecté en tant que root dans l’utilitaire MySQL :

    CREATE DATABASE IF NOT EXISTS db_multitenant_SaaS;
    CREATE USER IF NOT EXISTS vely IDENTIFIED BY 'your_password';
    GRANT CREATE,ALTER,DROP,SELECT,INSERT,DELETE,UPDATE ON db_multitenant_SaaS.* TO vely;

    Créez ensuite des objets de base de données (tables et enregistrements, etc.) dans la base de données :

    USE db_multitenant_SaaS;
    SOURCE setup.sql;
    exit

    Connecter Vely à une base de données

    Pour que Vely sache où se trouve votre base de données et comment s’y connecter, créez un fichier de configuration de base de données nommé db_multitenant_SaaS. (C’est le nom utilisé par les instructions de base de données dans le code source, donc si vous le modifiez, assurez-vous de le changer partout.)

    Vely utilise la connectivité native de la base de données MariaDB, vous pouvez donc spécifier toutes les options qu’une base de données donnée vous permet :

    $ echo '[client]
    user=vely
    password=your_password
    database=db_multitenant_SaaS
    protocol=TCP
    host=127.0.0.1
    port=3306'
    > db_multitenant_SaaS

    Construire l’application

    Utilisez le vv utilitaire pour faire l’application, en utilisant le --db option pour spécifier la base de données MariaDB et le fichier de configuration de la base :

    $ vv -q --db=mariadb:db_multitenant_SaaS

    Programmation et développement

    Démarrer le serveur d’applications

    Pour démarrer le serveur d’applications de votre application Web, utilisez le vf Gestionnaire de processus FastCGI. Le serveur d’application utilise un socket Unix pour communiquer avec le serveur web (création d’un reverse proxy) :

    $ vf -w 3 multitenant_SaaS

    Cela démarre trois processus démons pour traiter les demandes entrantes. Vous pouvez également démarrer un serveur adaptatif qui augmente le nombre de processus pour traiter plus de requêtes et réduire progressivement le nombre de processus lorsqu’ils ne sont pas nécessaires :

    $ vf multitenant_SaaS

    Voir vf pour plus d’options pour vous aider à obtenir les meilleures performances.

    Lorsque vous devez arrêter votre serveur d’applications, utilisez le -m quit option:

    $ vf -m quit multitenant_SaaS

    Configurer le serveur Web

    Il s’agit d’une application Web, donc l’application a besoin d’un serveur Web. Cet exemple utilise Apache au moyen d’un écouteur de socket Unix.

    1. Configurer Apache

    Pour configurer Apache en tant que proxy inverse et y connecter votre application, vous devez activer le support du proxy FastCGI, ce qui signifie généralement utiliser le proxy et proxy_fcgi modules.

    Pour les systèmes Fedora (ou autres, comme Arch), activez le proxy et proxy_fcgi modules en ajoutant (ou décommentant) les ChargerModule directives dans le /etc/httpd/conf/httpd.conf Fichier de configuration apache.

    Pour Debian, Ubuntu et des systèmes similaires, activez le proxy et proxy_fcgi modules:

    $ sudo a2enmod proxy
    $ sudo a2enmod proxy_fcgi

    Pour OpenSUSE, ajoutez ces lignes à la fin de /etc/apache2/httpd.conf:

    LoadModule proxy_module modules/mod_proxy.so
    LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

    2. Configurez Apache

    Vous devez maintenant ajouter les informations de proxy au fichier de configuration Apache :

    ProxyPass "/multitenant_SaaS" unix:///var/lib/vv/multitenant_SaaS/sock/sock|fcgi://localhost/multitenant_SaaS

    L’emplacement de votre configuration peut varier en fonction de votre distribution Linux :

    • Fedora, CentOS, Mageia et Arch : /etc/httpd/conf/httpd.conf
    • Debian, Ubuntu, Menthe : /etc/apache2/apache2.conf
    • OuvrirSUSE : /etc/apache2/httpd.conf

    3. Redémarrez

    Enfin, redémarrez Apache. Sur Fedora et systèmes similaires, ainsi que Arch Linux :

    $ sudo systemctl restart httpd

    Sur les systèmes Debian et basés sur Debian, ainsi que sur OpenSUSE :

    $ sudo systemctl restart apache2

    Configurer la messagerie locale

    Cet exemple utilise le courrier électronique dans le cadre de sa fonction. Si votre serveur peut déjà envoyer des e-mails, vous pouvez ignorer cette étape. Sinon, vous pouvez utiliser le courrier local (myuser@localhost) juste pour tester. Pour ce faire, installez Sendmail.

    Sur Fedora et similaire :

    $ sudo dnf install sendmail
    $ sudo systemctl start sendmail

    Sur les systèmes Debian (comme Ubuntu) :

    $ sudo apt install sendmail
    $ sudo systemctl start sendmail

    Lorsque l’application envoie un e-mail à un utilisateur local, tel que OS_user@localhostvous pouvez alors vérifier que l’e-mail a bien été envoyé en consultant /var/mail/ (le « spool de courrier »).

    Accéder au serveur d’application depuis le navigateur

    En supposant que vous exécutez l’application localement, utilisez http://127.0.0.1/multitenant_SaaS?req=notes&action=begin pour accéder à votre serveur d’application à partir de votre navigateur Web. Si vous l’exécutez sur un serveur en direct sur Internet, vous devrez peut-être ajuster les paramètres de votre pare-feu pour autoriser le trafic HTTP.

    Code source

    Cet exemple d’application contient sept fichiers sources. Vous pouvez revoir le code vous-même (rappelez-vous, il ne s’agit que de 310 lignes dans ces fichiers), mais voici un aperçu de chacun.

    Configuration SQL (setup.sql)

    Les deux tables créées sont :

    • utilisateurs: Informations sur chaque utilisateur. Chaque utilisateur du utilisateurs table a son propre ID unique (identifiant d’utilisateur colonne) ainsi que d’autres informations telles que l’adresse e-mail et si elle est vérifiée. Il y a aussi un mot de passe haché. Un mot de passe réel n’est jamais stocké en texte brut (ou autrement); un hachage unidirectionnel est utilisé pour vérifier le mot de passe.
    • Remarques: Notes saisies par l’utilisateur. La Remarques table contient les notes, chacune avec identifiant d’utilisateur colonne qui indique quel utilisateur les possède. La identifiant d’utilisateur la valeur de la colonne correspond à la colonne homonyme de utilisateurs table. De cette façon, chaque note appartient clairement à un seul utilisateur.

    Le contenu du fichier :

    CREATE TABLE IF NOT EXISTS notes (dateOf datetime, noteId BIGINT AUTO_INCREMENT PRIMARY KEY, userId BIGINT, note VARCHAR(1000));
    CREATE TABLE IF NOT EXISTS users (userId BIGINT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(100), hashed_pwd VARCHAR(100), verified SMALLINT, verify_token VARCHAR(30), SESSION VARCHAR(100));
    CREATE UNIQUE INDEX IF NOT EXISTS users1 ON users (email);

    Données d’exécution (login.h)

    Pour afficher correctement les liens de connexion, d’inscription et de déconnexion, vous avez besoin de certains indicateurs disponibles n’importe où dans l’application. De plus, l’application utilise des cookies pour maintenir une session, donc cela doit être disponible n’importe où, par exemple, pour vérifier que la session est valide. Chaque demande envoyée à l’application est ainsi confirmée. Seules les demandes accompagnées de cookies vérifiables sont autorisées.

    Donc, à cet effet, vous avez un global_request_data taper reqdata (demande de données) et dedans il y a sess_userId (ID de l’utilisateur) et sess_id (ID de session en cours de l’utilisateur). Vous avez également des drapeaux plutôt explicites qui aident à rendre les pages :

    #ifndef _VV_LOGIN
    #define _VV_LOGIN

    typedef struct s_reqdata {
        bool displayed_logout; // true if Logout link displayed
        bool is_logged_in; // true if session verified logged-in
        char *sess_userId; // user ID of current session
        char *sess_id; // session ID
    } reqdata;

    void login_or_signup ();

    #endif

    Vérification de session et données de session (_before.vely)

    Vely a la notion d’un avant_request_handler. Le code que vous écrivez s’exécute avant tout autre code qui gère une requête. Pour cela, il suffit d’écrire ce code dans un fichier nommé _before.velyet le reste est automatiquement géré.

    Tout ce que fait une application SaaS, comme la gestion des demandes envoyées à une application, doit être validé pour des raisons de sécurité. De cette façon, l’application sait si l’appelant dispose des autorisations nécessaires pour effectuer une action.

    La vérification de l’autorisation est effectuée ici dans un gestionnaire de requête avant. De cette façon, quel que soit l’autre code dont vous disposez pour gérer une requête, vous disposez déjà des informations de session.

    Pour garder les données de session (comme l’ID de session et l’ID utilisateur) disponibles n’importe où dans votre code, vous utilisez global_request_data. C’est juste un pointeur générique (annuler*) à la mémoire à laquelle tout code qui gère les requêtes peut accéder. C’est parfait pour les sessions de manipulation, comme indiqué ci-dessous :

    #include "vely.h"
    #include "login.h"

    // _before() is a before-request-handler. It always executes before
    // any other code that handles a request. It's a good place for any
    // kind of request-wide setting or data initialization
    void _before() {
        // Output HTTP header
        out-header default
        reqdata *rd; // this is global request data, see login.h
        // allocate memory for global request data, will be automatically deallocated
        // at the end of request
        new-mem rd size sizeof(reqdata)
        // initialize flags
        rd->displayed_logout = false;
        rd->is_logged_in = false;
        // set the data we created to be global request data, accessible
        // from any code that handles a request
        set-req data rd
        // check if session exists (based on cookies from the client)
        // this executes before any other request-handling code, making it
        // easier to just have session information ready
        _check_session ();
    }

    Vérifier si la session est valide (_check_session.vely)

    L’une des tâches les plus importantes dans une application SaaS mutualisée consiste à vérifier (dès que possible) si la session est valide en vérifiant si un utilisateur est connecté. Cela se fait en obtenant les cookies d’ID de session et d’ID utilisateur du client (tels que en tant que navigateur Web) et en les comparant à la base de données dans laquelle les sessions sont stockées :

    #include "vely.h"
    #include "login.h"

    // Check if session is valid
    void _check_session () {
        // Get global request data
        reqdata *rd;
        get-req data to rd
        // Get cookies from user browser
        get-cookie rd->sess_userId="sess_userId"
        get-cookie rd->sess_id="sess_id"
        if (rd->sess_id[0] != 0) {
            // Check if session ID is correct for given user ID
            char *email;
            run-query @db_multitenant_SaaS = "select email from users where userId='%s' and session='%s'" output email : rd->sess_userId, rd->sess_id row-count define rcount
                query-result email to email
            end-query
            if (rcount == 1) {
                // if correct, set logged-in flag
                rd->is_logged_in = true;
                // if Logout link not display, then display it
                if (rd->displayed_logout == false) {
                    @Hi <<p-out email>>! <a href="https://opensource.com/?req=login&action=logout">Logout</a><br/>
                    rd->displayed_logout = true;
                }
            } else rd->is_logged_in = false;
        }
    }

    Inscription, connexion, déconnexion (login.vely)

    La base de tout système mutualisé est la possibilité pour un utilisateur de s’inscrire, de se connecter et de se déconnecter. En règle générale, l’inscription implique la vérification de l’adresse e-mail ; le plus souvent, la même adresse e-mail est utilisée comme nom d’utilisateur. C’est le cas ici.

    Plusieurs sous-requêtes implémentées ici sont nécessaires pour exécuter la fonctionnalité :

    • Lors de l’inscription d’un nouvel utilisateur, affichez le formulaire HTML pour collecter les informations. La signature de la demande d’URL pour cela est req=login&action=newuser.
    • En réponse au formulaire d’inscription, créez un nouvel utilisateur. La signature de la demande d’URL est req=login&action=createuser. La paramètre d’entrée le signal obtient un e-mail et pwd Champs de formulaire POST. La valeur du mot de passe est un hachage unidirectionnel et un jeton de vérification d’e-mail est créé sous la forme d’un nombre aléatoire à cinq chiffres. Ceux-ci sont insérés dans le utilisateurs table, créant un nouvel utilisateur. Un e-mail de vérification est envoyé et l’utilisateur est invité à lire l’e-mail et à saisir le code.
    • Vérifiez l’e-mail en entrant le code de vérification envoyé à cet e-mail. La signature de la demande d’URL est req=login&action=verify.
    • Affichez un formulaire de connexion permettant à l’utilisateur de se connecter. La signature de la demande d’URL est req=login (par exemple, action est vide.)
    • Connectez-vous en vérifiant l’adresse e-mail (nom d’utilisateur) et le mot de passe. La signature de la demande d’URL est req=login&action=login.
    • Déconnexion à la demande de l’utilisateur. La signature de la demande d’URL est req=login&action=logout.
    • Page de destination de l’application. La signature de la demande d’URL est req=login&action=begin.
    • Si l’utilisateur est actuellement connecté, accédez à la page d’accueil de l’application.

    Voir des exemples ci-dessous :

    #include "vely.h"
    #include "login.h"

    // Handle session maintenance, login, logout, session verification
    // for any multitenant Cloud application
    void login () {
        // Get URL input parameter "action"
        input-param action

        // Get global request data, we record session information in it, so it's handy
        reqdata *rd;
        get-req data to rd

        // If session is already established, the only reason why we won't proceed to
        // application home is if we're logging out
        if (rd->is_logged_in) {
            if (strcmp(action, "logout")) {
                _show_home();
                exit-request
            }
        }

        // Application screen to get started. Show links to login or signup and show
        // home screen appropriate for this
        if (!strcmp (action, "begin")) {
            _show_home();
            exit-request

        // Start creating new user. Ask for email and password, then proceed to create user
        // when this form is submitted.
        } else if (!strcmp (action, "newuser")) {
            @Create New User<hr/>
            @<form action="https://opensource.com/?req=login" method="POST">
            @<input name="action" type="hidden" value="createuser">
            @<input name="email" type="text" value="" size="50" maxlength="50" required autofocus placeholder="Email">
            @<input name="pwd" type="password" value="" size="50" maxlength="50" required placeholder="Password">
            @<input type="submit" value="Sign Up">
            @</form>

        // Verify code sent to email by user. The code must match, thus verifying email address    
        } else if (!strcmp (action, "verify")) {
            input-param code
            input-param email
            // Get verify token based on email
            run-query @db_multitenant_SaaS = "select verify_token from users where email="%s"" output db_verify : email
                query-result db_verify to define db_verify
                // Compare token recorded in database with what user provided
                if (!strcmp (code, db_verify)) {
                    @Your email has been verifed. Please <a href="https://opensource.com/?req=login">Login</a>.
                    // If matches, update user info to indicate it's verified
                    run-query @db_multitenant_SaaS no-loop = "update users set verified=1 where email="%s"" : email
                    exit-request
                }
            end-query
            @Could not verify the code. Please try <a href="https://opensource.com/?req=login">again</a>.
            exit-request

        // Create user - this runs when user submits form with email and password to create a user    
        } else if (!strcmp (action, "createuser")) {
            input-param email
            input-param pwd
            // create hashed (one-way) password
            hash-string pwd to define hashed_pwd
            // generate random 5 digit string for verify code
            random-string to define verify length 5 number
            // create user: insert email, hashed password, verification token. Current verify status is 0, or not verified
            begin-transaction @db_multitenant_SaaS
            run-query @db_multitenant_SaaS no-loop = "insert into users (email, hashed_pwd, verified, verify_token, session) values ('%s', '%s', '0', '%s', '')" : email, hashed_pwd, verify affected-rows define arows error define err on-error-continue
            if (strcmp (err, "0") || arows != 1) {
                // if cannot add user, it probably doesn't exist. Either way, we can't proceed.
                login_or_signup();
                @User with this email already exists.
                rollback-transaction @db_multitenant_SaaS
            } else {
                // Create email with verification code and email it to user
                write-string define msg
                    @From: vely@vely.dev
                    @To: <<p-out email>>
                    @Subject: verify your account
                    @
                    @Your verification code is: <<p-out verify>>
                end-write-string
                exec-program "/usr/sbin/sendmail" args "-i", "-t" input msg status define st
                if (st != 0) {
                    @Could not send email to <<p-out email>>, code is <<p-out verify>>
                    rollback-transaction @db_multitenant_SaaS
                    exit-request
                }
                commit-transaction @db_multitenant_SaaS
                // Inform the user to go check email and enter verification code
                @Please check your email and enter verification code here:
                @<form action="https://opensource.com/?req=login" method="POST">
                @<input name="action" type="hidden" value="verify" size="50" maxlength="50">
                @<input name="email" type="hidden" value="<<p-out email>>">
                @<input name="code" type="text" value="" size="50" maxlength="50" required autofocus placeholder="Verification code">
                @<button type="submit">Verify</button>
                @</form>
            }

        // This runs when logged-in user logs out.    
        } else if (!strcmp (action, "logout")) {
            // Update user table to wipe out session, meaning no such user is logged in
            if (rd->is_logged_in) {
                run-query @db_multitenant_SaaS = "update users set session='' where userId='%s'" : rd->sess_userId no-loop affected-rows define arows
                if (arows == 1) {
                    rd->is_logged_in = false; // indicate user not logged in
                    @You have been logged out.<hr/>
                }
            }
            _show_home();

        // Login: this runs when user enters user name and password
        } else if (!strcmp (action, "login")) {
            input-param pwd
            input-param email
            // create one-way hash with the intention of comparing with user table - password is NEVER recorded
            hash-string pwd to define hashed_pwd
            // create random 30-long string for session ID
            random-string to rd->sess_id length 30
            // Check if user name and hashed password match
            run-query @db_multitenant_SaaS = "select userId from users where email="%s" and hashed_pwd='%s'" output sess_userId : email, hashed_pwd
                query-result sess_userId to rd->sess_userId
                // If match, update user table with session ID
                run-query @db_multitenant_SaaS no-loop = "update users set session='%s' where userId='%s'" : rd->sess_id, rd->sess_userId affected-rows define arows
                if (arows != 1) {
                    @Could not create a session. Please try again. <<.login_or_signup();>> <hr/>
                    exit-request
                }
                // Set user ID and session ID as cookies. User's browser will return those to us with every request
                set-cookie "sess_userId" = rd->sess_userId
                set-cookie "sess_id" = rd->sess_id
                // Display home, make sure session is correct first and set flags
                _check_session();
                _show_home();
                exit-request
            end-query
            @Email or password are not correct. <<.login_or_signup();>><hr/>

        // Login screen, asks user to enter user name and password    
        } else if (!strcmp (action, "")) {
            login_or_signup();
            @Please Login:<hr/>
            @<form action="https://opensource.com/?req=login" method="POST">
            @<input name="action" type="hidden" value="login" size="50" maxlength="50">
            @<input name="email" type="text" value="" size="50" maxlength="50" required autofocus placeholder="Email">
            @<input name="pwd" type="password" value="" size="50" maxlength="50" required placeholder="Password">
            @<button type="submit">Go</button>
            @</form>
        }
    }

    // Display Login or Sign Up links
    void login_or_signup() {
            @<a href="https://opensource.com/?req=login">Login</a> & & <a href="https://opensource.com/?req=login&action=newuser">Sign Up</a><hr/>
    }

    Application à usage général (_show_home.vely)

    Avec ce didacticiel, vous pouvez créer n’importe quelle application SaaS mutualisée de votre choix. Le module de traitement mutualisé ci-dessus (login.vely) appelle le _show_home() fonction, qui peut héberger n’importe quel code de la vôtre. Cet exemple de code montre l’application Notes, mais cela pourrait être n’importe quoi. La _show_home() La fonction appelle le code que vous souhaitez et est un plug-in d’application multi-locataire à usage général :

    #include "vely.h"

    void _show_home() {
        notes();
        exit-request
    }

    Application Notes (notes.vely)

    L’application est capable d’ajouter, de lister et de supprimer n’importe quelle note :

    #include "vely.h"
    #include "login.h"

    // Notes application in a multitenant Cloud
    void notes () {
        // get global request data
        reqdata *rd;
        get-req data to rd
        // If session invalid, display Login or Signup
        if (!rd->is_logged_in) {
            login_or_signup();
        }
        // Greet the user
        @<h1>Welcome to Notes!</h1><hr/>
        // If not logged in, exit - this ensures security verification of user's identity
        if (!rd->is_logged_in) {
            exit-request
        }
        // Get URL parameter that tells Notes what to do
        input-param subreq
        // Display actions that Notes can do (add or list notes)
        @<a href="https://opensource.com/?req=notes&subreq=add">Add Note</a> <a href="https://opensource.com/?req=notes&subreq=list">List Notes</a><hr/>

        // List all notes for this user
        if (!strcmp (subreq, "list")) {
            // select notes for this user ONLY
            run-query @db_multitenant_SaaS = "select dateOf, note, noteId from notes where userId='%s' order by dateOf desc" : rd->sess_userId output dateOf, note, noteId
                query-result dateOf to define dateOf
                query-result note to define note
                query-result noteId to define noteId
                // change new lines to <br/> with fast cached Regex
                match-regex "\n" in note replace-with "<br/>\n" result define with_breaks status define st cache
                if (st == 0) with_breaks = note; // nothing was found/replaced, just use original
                // Display a note
                @Date: <<p-out dateOf>> (<a href="https://opensource.com/?req=notes&subreq=delete_note_ask&note_id=%3C%3Cp-out%20noteId%3E%3E">delete note</a>)<br/>
                @Note: <<p-out with_breaks>><br/>
                @<hr/>
            end-query
        }

        // Ask to delete a note
        else if (!strcmp (subreq, "delete_note_ask")) {
            input-param note_id
            @Are you sure you want to delete a note? Use Back button to go back, or <a href="https://opensource.com/?req=notes&subreq=delete_note&note_id=%3C%3Cp-out%20note_id%3E%3E">delete note now</a>.
        }

        // Delete a note
        else if (!strcmp (subreq, "delete_note")) {
            input-param note_id
            // Delete note
            run-query @db_multitenant_SaaS = "delete from notes where noteId='%s' and userId='%s'" : note_id, rd->sess_userId affected-rows define arows no-loop error define errnote
            // Inform user of status
            if (arows == 1) {
                @Note deleted
            } else {
                @Could not delete note (<<p-out errnote>>)
            }
        }

        // Add a note
        else if (!strcmp (subreq, "add_note")) {
            // Get URL POST data from note form
            input-param note
            // Insert note under this user's ID
            run-query @db_multitenant_SaaS = "insert into notes (dateOf, userId, note) values (now(), '%s', '%s')" : rd->sess_userId, note affected-rows define arows no-loop error define errnote
            // Inform user of status
            if (arows == 1) {
                @Note added
            } else {
                @Could not add note (<<p-out errnote>>)
            }
        }

        // Display an HTML form to collect a note, and send it back here (with subreq="add_note" URL param)
        else if (!strcmp (subreq, "add")) {
            @Add New Note
            @<form action="https://opensource.com/?req=notes" method="POST">
            @<input name="subreq" type="hidden" value="add_note">
            @<textarea name="note" rows="5" cols="50" required autofocus placeholder="Enter Note"></textarea>
            @<button type="submit">Create</button>
            @</form>
        }
    }

    SaaS avec performances C

    Vely permet d’exploiter la puissance du C dans vos applications Web. Une application SaaS mutualisée est un excellent exemple de cas d’utilisation qui en bénéficie. Jetez un œil aux exemples de code, écrivez du code et essayez Vely.

    Source

    Houssen Moshinaly

    Pour contacter personnellement le taulier :

    Laisser un commentaire

    Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

    Copy code