Compare commits
8 Commits
feature/se
...
jwt
Author | SHA1 | Date | |
---|---|---|---|
424273360d | |||
ae6dfb2644 | |||
d78d581c65 | |||
52c878b0ab | |||
5666c01bdc | |||
3a9243bfb8 | |||
bcd17e1038 | |||
47d5ed77d5 |
@ -20,13 +20,14 @@ docker run -d --add-host reload.example.com:127.0.0.1 -p 80:80 coudot/lemonldap-
|
|||||||
|
|
||||||
Démarrer un serveur postgresql de test
|
Démarrer un serveur postgresql de test
|
||||||
```
|
```
|
||||||
podman pull docker.io/library/postgres:11-alpine
|
docker run -dt -p 5432:5432 --name postgres postgres:11-alpine
|
||||||
podman run -dt -p 5432:5432 postgres:11-alpine
|
docker exec -ti postgres bash
|
||||||
|
|
||||||
psql -U postgres -h localhost -c "CREATE ROLE risotto WITH LOGIN PASSWORD 'risotto';"
|
psql -U postgres -h localhost -c "CREATE ROLE risotto WITH LOGIN PASSWORD 'risotto';"
|
||||||
psql -U postgres -h localhost -c "CREATE DATABASE risotto;"
|
psql -U postgres -h localhost -c "CREATE DATABASE risotto;"
|
||||||
psql -U postgres -h localhost -c "GRANT ALL ON DATABASE risotto TO risotto;"
|
psql -U postgres -h localhost -c "GRANT ALL ON DATABASE risotto TO risotto;"
|
||||||
psql -U postgres -h localhost -c "CREATE EXTENSION hstore;" risotto
|
psql -U postgres -h localhost -c "CREATE EXTENSION hstore;"
|
||||||
|
psql -U postgres -h localhost -c "CREATE EXTENSION pgcrypto;"
|
||||||
```
|
```
|
||||||
|
|
||||||
Gestion de la base de données avec Sqitch
|
Gestion de la base de données avec Sqitch
|
||||||
|
29
docker/Dockerfile
Normal file
29
docker/Dockerfile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
FROM python:3.7
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
ARG TIRAMISU_REPO_URL=https://framagit.org/tiramisu/tiramisu.git
|
||||||
|
ARG RISOTTO_REPO_URL=https://forge.cadoles.com/Infra/risotto.git
|
||||||
|
ARG ROUGAIL_REPO_URL=https://forge.cadoles.com/Infra/rougail.git
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
vim \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
jq \
|
||||||
|
&& apt-get clean
|
||||||
|
|
||||||
|
RUN git clone --branch develop ${TIRAMISU_REPO_URL} /srv/src/tiramisu
|
||||||
|
RUN git clone --branch docker ${RISOTTO_REPO_URL} /srv/src/risotto
|
||||||
|
RUN git clone --branch master ${ROUGAIL_REPO_URL} /srv/src/rougail
|
||||||
|
|
||||||
|
RUN ln -s /srv/src/tiramisu/tiramisu /usr/local/lib/python3.7
|
||||||
|
RUN ln -s /srv/src/rougail/src/rougail /usr/local/lib/python3.7
|
||||||
|
RUN ln -s /srv/src/risotto/src/risotto /usr/local/lib/python3.7
|
||||||
|
|
||||||
|
RUN pip install Cheetah3 PyJWT
|
||||||
|
RUN cd /srv/src/risotto && pip install -r requirements.txt
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
RUN cp -r /srv/src/risotto/messages/ /usr/local/lib/
|
||||||
|
RUN mkdir -p /var/cache/risotto/servermodel
|
||||||
|
RUN mkdir -p /var/cache/risotto/database
|
14
docker/README.md
Normal file
14
docker/README.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
Docker
|
||||||
|
```
|
||||||
|
cd docker
|
||||||
|
docker build -t cadoles/risotto .
|
||||||
|
docker run -t -d --name risotto cadoles/risotto
|
||||||
|
docker exec -ti risotto bash
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Docker-Compose
|
||||||
|
```
|
||||||
|
cd docker
|
||||||
|
docker-compose up
|
||||||
|
```
|
29
docker/docker-compose.yaml
Normal file
29
docker/docker-compose.yaml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
version: '2.2'
|
||||||
|
services:
|
||||||
|
risotto:
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: docker/Dockerfile
|
||||||
|
volumes:
|
||||||
|
- ../.:/srv/src/risotto
|
||||||
|
- ../messages:/usr/local/lib/messages
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
links:
|
||||||
|
- postgres
|
||||||
|
#command: tail -F /var/log
|
||||||
|
command: python -u /srv/src/risotto/script/server.py
|
||||||
|
restart: on-failure
|
||||||
|
postgres:
|
||||||
|
image: postgres:11-alpine
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
|
||||||
|
PGDATA: /data/postgres
|
||||||
|
volumes:
|
||||||
|
- ./postgres-init/:/docker-entrypoint-initdb.d/
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
restart: unless-stopped
|
105
docker/postgres-init/10-postgres.init.sh
Executable file
105
docker/postgres-init/10-postgres.init.sh
Executable file
@ -0,0 +1,105 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
psql --username "$POSTGRES_USER" <<-EOSQL
|
||||||
|
CREATE ROLE risotto WITH LOGIN PASSWORD 'risotto';
|
||||||
|
CREATE DATABASE risotto;
|
||||||
|
GRANT ALL ON DATABASE risotto TO risotto;
|
||||||
|
\c risotto
|
||||||
|
CREATE EXTENSION hstore;
|
||||||
|
CREATE EXTENSION pgcrypto;
|
||||||
|
EOSQL
|
||||||
|
|
||||||
|
psql --username "risotto" --password "risotto" <<-EOSQL
|
||||||
|
-- Création de la table Source
|
||||||
|
CREATE TABLE Source (
|
||||||
|
SourceId SERIAL PRIMARY KEY,
|
||||||
|
SourceName VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
SourceURL TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Création de la table Release
|
||||||
|
CREATE TABLE Release (
|
||||||
|
ReleaseId SERIAL PRIMARY KEY,
|
||||||
|
ReleaseName VARCHAR(255) NOT NULL,
|
||||||
|
ReleaseSourceId INTEGER NOT NULL,
|
||||||
|
ReleaseDistribution VARCHAR(20) CONSTRAINT releasedistribution_choice CHECK (ReleaseDistribution IN ('last', 'n-1', 'n-2')),
|
||||||
|
UNIQUE (ReleaseName, ReleaseSourceId),
|
||||||
|
UNIQUE (ReleaseDistribution, ReleaseSourceId),
|
||||||
|
FOREIGN KEY (ReleaseSourceId) REFERENCES Source(SourceId)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
-- Création de la table Servermodel
|
||||||
|
CREATE TABLE Servermodel (
|
||||||
|
ServermodelId SERIAL PRIMARY KEY,
|
||||||
|
ServermodelName VARCHAR(255) NOT NULL,
|
||||||
|
ServermodelDescription VARCHAR(255) NOT NULL,
|
||||||
|
ServermodelParentsId INTEGER [] DEFAULT '{}',
|
||||||
|
ServermodelReleaseId INTEGER NOT NULL,
|
||||||
|
ServermodelApplicationServiceId INTEGER NOT NULL,
|
||||||
|
ServermodelUsers hstore,
|
||||||
|
UNIQUE (ServermodelName, ServermodelReleaseId)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Création de la table ApplicationService
|
||||||
|
CREATE TABLE ApplicationService (
|
||||||
|
ApplicationServiceId SERIAL PRIMARY KEY,
|
||||||
|
ApplicationServiceName VARCHAR(255) NOT NULL,
|
||||||
|
ApplicationServiceDescription VARCHAR(255) NOT NULL,
|
||||||
|
ApplicationServiceReleaseId INTEGER NOT NULL,
|
||||||
|
ApplicationServiceDependencies JSON,
|
||||||
|
UNIQUE (ApplicationServiceName, ApplicationServiceReleaseId)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Server table creation
|
||||||
|
CREATE TABLE Server (
|
||||||
|
ServerId SERIAL PRIMARY KEY,
|
||||||
|
ServerName VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
ServerDescription VARCHAR(255) NOT NULL,
|
||||||
|
ServerServermodelId INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- User, Role and ACL table creation
|
||||||
|
|
||||||
|
CREATE TABLE RisottoUser (
|
||||||
|
UserId SERIAL PRIMARY KEY,
|
||||||
|
UserLogin VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
UserPassword TEXT NOT NULL,
|
||||||
|
UserName VARCHAR(100) NOT NULL,
|
||||||
|
UserSurname VARCHAR(100) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE UserRole (
|
||||||
|
RoleId SERIAL PRIMARY KEY,
|
||||||
|
RoleUserId INTEGER NOT NULL,
|
||||||
|
RoleName VARCHAR(255) NOT NULL,
|
||||||
|
RoleAttribute VARCHAR(255),
|
||||||
|
RoleAttributeValue VARCHAR(255),
|
||||||
|
FOREIGN KEY (RoleUserId) REFERENCES RisottoUser(UserId)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE URI (
|
||||||
|
URIId SERIAL PRIMARY KEY,
|
||||||
|
URIName VARCHAR(255) NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE RoleURI (
|
||||||
|
RoleName VARCHAR(255) NOT NULL,
|
||||||
|
URIId INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (URIId) REFERENCES URI(URIId),
|
||||||
|
PRIMARY KEY (RoleName, URIId)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Log table creation
|
||||||
|
|
||||||
|
CREATE TABLE log(
|
||||||
|
Msg VARCHAR(255) NOT NULL,
|
||||||
|
Level VARCHAR(10) NOT NULL,
|
||||||
|
Path VARCHAR(255),
|
||||||
|
Username VARCHAR(100) NOT NULL,
|
||||||
|
Data JSON,
|
||||||
|
Date timestamp DEFAULT current_timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
EOSQL
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne des informations sur la session HTTP courante de l'utilisateur.
|
Retourne des informations sur la session HTTP courante de l'utilisateur.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client identity.session-user.get
|
cucchiaiata identity.session-user.get
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne les préférences de l'utilisateur spécifié.
|
Retourne les préférences de l'utilisateur spécifié.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client identity.settings.get -u yo
|
cucchiaiata identity.settings.get -u yo
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Enregistre des préférences pour l'utilisateur spécifié.
|
Enregistre des préférences pour l'utilisateur spécifié.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client identity.settings.set -u yo
|
cucchiaiata identity.settings.set -u yo
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ pattern: rpc
|
|||||||
domain: server-domain
|
domain: server-domain
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client server.delete -s 1
|
cucchiaiata server.delete -s 1
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
serverid:
|
serverid:
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Transmet une commande à exécuter sur un serveur donné.
|
Transmet une commande à exécuter sur un serveur donné.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client server.exec.command -s 1 -c reconfigure
|
cucchiaiata server.exec.command -s 1 -c reconfigure
|
||||||
|
|
||||||
domain: server-domain
|
domain: server-domain
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Déploie la configuration sur un serveur donné.
|
Déploie la configuration sur un serveur donné.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client server.exec.deploy -s 1
|
cucchiaiata server.exec.deploy -s 1
|
||||||
|
|
||||||
domain: server-domain
|
domain: server-domain
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Liste les commandes exécuté pour un identifiant de tâche.
|
Liste les commandes exécuté pour un identifiant de tâche.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client server.exec.list -j 1
|
cucchiaiata server.exec.list -j 1
|
||||||
|
|
||||||
domain: execution-domain
|
domain: execution-domain
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Liste les commandes exécutées sur un serveur donné.
|
Liste les commandes exécutées sur un serveur donné.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client server.exec.list -s 1
|
cucchiaiata server.exec.list -s 1
|
||||||
|
|
||||||
domain: execution-domain
|
domain: execution-domain
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne la liste des sélections de serveurs d'un serveur
|
Retourne la liste des sélections de serveurs d'un serveur
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client server.serverselection.list
|
cucchiaiata server.serverselection.list
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ description: |
|
|||||||
public: true
|
public: true
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client server.update -s 1 -n toto -d "server description"
|
cucchiaiata server.update -s 1 -n toto -d "server description"
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Associe un service applicatif à un modèle de serveur.
|
Associe un service applicatif à un modèle de serveur.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client servermodel.applicationservice.join -m 1 -s 1
|
cucchiaiata servermodel.applicationservice.join -m 1 -s 1
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne la liste des applications service.
|
Retourne la liste des applications service.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client servermodel.applicationservice.list -s 6
|
cucchiaiata servermodel.applicationservice.list -s 6
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Crée un modèle de serveur.
|
Crée un modèle de serveur.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client servermodel.create -p 1 -n "MonServeurModele" -d "Ma description" -s 1
|
cucchiaiata servermodel.create -p 1 -n "MonServeurModele" -d "Ma description" -s 1
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne la liste des subreleases.
|
Retourne la liste des subreleases.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client servermodel.subrelease.list
|
cucchiaiata servermodel.subrelease.list
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Crée un sélection de serveurs.
|
Crée un sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.create -n Select1 -d "Ma description"
|
cucchiaiata serverselection.create -n Select1 -d "Ma description"
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Supprime une sélection de serveurs.
|
Supprime une sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.delete -s 1
|
cucchiaiata serverselection.delete -s 1
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ description: |
|
|||||||
|
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.describe -s 1
|
cucchiaiata serverselection.describe -s 1
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Transmet une commande à exécuter sur une sélection de serveurs.
|
Transmet une commande à exécuter sur une sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.exec.command -s 1 -c reconfigure
|
cucchiaiata serverselection.exec.command -s 1 -c reconfigure
|
||||||
|
|
||||||
domain: server-domain
|
domain: server-domain
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Déploie la configuration sur les serveurs d'une sélection de serveurs.
|
Déploie la configuration sur les serveurs d'une sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.exec.deploy -s 1
|
cucchiaiata serverselection.exec.deploy -s 1
|
||||||
|
|
||||||
domain: server-domain
|
domain: server-domain
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne la liste des sélections de serveurs.
|
Retourne la liste des sélections de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.list
|
cucchiaiata serverselection.list
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Ajoute un serveur à une sélection de serveurs.
|
Ajoute un serveur à une sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.add.server -s 1 -i 1
|
cucchiaiata serverselection.add.server -s 1 -i 1
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Supprime un serveur d'une sélection de serveurs.
|
Supprime un serveur d'une sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.remove.server -s 1 -i 1
|
cucchiaiata serverselection.remove.server -s 1 -i 1
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Renseigne une liste de serveur dans une sélection de serveurs.
|
Renseigne une liste de serveur dans une sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.server.set -s 1 -i 1
|
cucchiaiata serverselection.server.set -s 1 -i 1
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Modifie une sélection de serveur.
|
Modifie une sélection de serveur.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.update -s 1 -n Select1 -d "Ma description"
|
cucchiaiata serverselection.update -s 1 -n Select1 -d "Ma description"
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Associe un utilisateur à une sélection de serveurs.
|
Associe un utilisateur à une sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.add.user -s 1 -u yo -r admin
|
cucchiaiata serverselection.add.user -s 1 -u yo -r admin
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne la sélection de serveurs par défaut de l'utilisateur.
|
Retourne la sélection de serveurs par défaut de l'utilisateur.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.user.default
|
cucchiaiata serverselection.user.default
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne les sélections de serveurs dont l'utilisateur fait parti.
|
Retourne les sélections de serveurs dont l'utilisateur fait parti.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.user.list
|
cucchiaiata serverselection.user.list
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Dissocie un utilisateur d'une sélection de serveurs.
|
Dissocie un utilisateur d'une sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.remove.user -s 1 -u yo
|
cucchiaiata serverselection.remove.user -s 1 -u yo
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne le rôle d'utilisateur sur une selection de serveurs.
|
Retourne le rôle d'utilisateur sur une selection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.user.role.get -d '{}'
|
cucchiaiata serverselection.user.role.get -d '{}'
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Retourne le rôle d'un utlisateur sur un serveur.
|
Retourne le rôle d'un utlisateur sur un serveur.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.user.role.server.get -d '{}'
|
cucchiaiata serverselection.user.role.server.get -d '{}'
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ description: |
|
|||||||
Modifie le rôle d'un utilisateur pour une sélection de serveurs.
|
Modifie le rôle d'un utilisateur pour une sélection de serveurs.
|
||||||
|
|
||||||
sampleuse: |
|
sampleuse: |
|
||||||
zephir-client serverselection.update.user -s 1 -u yo -r admin
|
cucchiaiata serverselection.update.user -s 1 -u yo -r admin
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
|
@ -11,6 +11,10 @@ parameters:
|
|||||||
shortarg: l
|
shortarg: l
|
||||||
description: Login de l'utilisateur.
|
description: Login de l'utilisateur.
|
||||||
ref: User.Login
|
ref: User.Login
|
||||||
|
user_password:
|
||||||
|
type: String
|
||||||
|
shortarg: p
|
||||||
|
description: Password de l'utilisateur.
|
||||||
user_name:
|
user_name:
|
||||||
type: String
|
type: String
|
||||||
shortarg: n
|
shortarg: n
|
||||||
|
7
requirements.txt
Normal file
7
requirements.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
asyncpg==0.20.1
|
||||||
|
lxml==4.4.2
|
||||||
|
requests==2.22.0
|
||||||
|
aiohttp==3.6.2
|
||||||
|
pytest==5.3.3
|
||||||
|
PyYAML==5.3
|
||||||
|
tiramisu==3.0rc15
|
@ -57,6 +57,7 @@ CREATE TABLE Server (
|
|||||||
CREATE TABLE RisottoUser (
|
CREATE TABLE RisottoUser (
|
||||||
UserId SERIAL PRIMARY KEY,
|
UserId SERIAL PRIMARY KEY,
|
||||||
UserLogin VARCHAR(100) NOT NULL UNIQUE,
|
UserLogin VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
UserPassword TEXT NOT NULL,
|
||||||
UserName VARCHAR(100) NOT NULL,
|
UserName VARCHAR(100) NOT NULL,
|
||||||
UserSurname VARCHAR(100) NOT NULL
|
UserSurname VARCHAR(100) NOT NULL
|
||||||
);
|
);
|
||||||
@ -97,7 +98,15 @@ CREATE TABLE log(
|
|||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
db_conf = get_config().get('database')
|
db_conf = get_config().get('database')
|
||||||
pool = await asyncpg.create_pool(database=db_conf.get('dbname'), user=db_conf.get('user'))
|
#asyncpg.connect('postgresql://postgres@localhost/test')
|
||||||
|
engine = db_conf.get('engine')
|
||||||
|
host = db_conf.get('host')
|
||||||
|
dbname = db_conf.get('dbname')
|
||||||
|
dbuser = db_conf.get('user')
|
||||||
|
dbpassword = db_conf.get('password')
|
||||||
|
dbport = db_conf.get('port')
|
||||||
|
cfg = "{}://{}:{}@{}:{}/{}".format(engine, dbuser, dbpassword, host, dbport, dbname)
|
||||||
|
pool = await asyncpg.create_pool(cfg)
|
||||||
async with pool.acquire() as connection:
|
async with pool.acquire() as connection:
|
||||||
async with connection.transaction():
|
async with connection.transaction():
|
||||||
returns = await connection.execute(VERSION_INIT)
|
returns = await connection.execute(VERSION_INIT)
|
||||||
@ -106,3 +115,4 @@ if __name__ == '__main__':
|
|||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
loop.run_until_complete(main())
|
loop.run_until_complete(main())
|
||||||
# asyncio.run(main())
|
# asyncio.run(main())
|
||||||
|
|
||||||
|
@ -1,32 +1,45 @@
|
|||||||
MESSAGE_ROOT_PATH = 'messages'
|
MESSAGE_ROOT_PATH = 'messages'
|
||||||
DATABASE_DIR = 'database'
|
DATABASE_DIR = '/var/cache/risotto/database'
|
||||||
INTERNAL_USER = 'internal'
|
INTERNAL_USER = 'internal'
|
||||||
CONFIGURATION_DIR = 'configurations'
|
CONFIGURATION_DIR = 'configurations'
|
||||||
TEMPLATE_DIR = 'templates'
|
TEMPLATE_DIR = 'templates'
|
||||||
TMP_DIR = 'tmp'
|
TMP_DIR = 'tmp'
|
||||||
ROUGAIL_DTD_PATH = '../rougail/data/creole.dtd'
|
ROUGAIL_DTD_PATH = '../rougail/data/creole.dtd'
|
||||||
DEFAULT_USER = 'Anonymous'
|
DEFAULT_USER = 'gnunux'
|
||||||
|
DEFAULT_USER_PASSWORD = 'gnunux'
|
||||||
|
URI = 'http://localhost'
|
||||||
|
PORT = 8080
|
||||||
|
JWT_SECRET = 'MY_SUPER_SECRET'
|
||||||
|
JWT_TOKEN_EXPIRE = 3600
|
||||||
|
JWT_TOKEN_AUDIENCE = "Risotto"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from pathlib import PurePosixPath
|
from pathlib import PurePosixPath
|
||||||
CURRENT_PATH = PurePosixPath(__file__)
|
CURRENT_PATH = PurePosixPath(__file__)
|
||||||
|
|
||||||
def get_config():
|
def get_config():
|
||||||
return {'database': {'host': 'localhost',
|
return {'database': {'engine': 'postgres',
|
||||||
|
'host': 'postgres',
|
||||||
'port': 5432,
|
'port': 5432,
|
||||||
'dbname': 'risotto',
|
'dbname': 'risotto',
|
||||||
'user': 'risotto',
|
'user': 'risotto',
|
||||||
'password': 'risotto',
|
'password': 'risotto',
|
||||||
},
|
},
|
||||||
'http_server': {'port': 8080,
|
'http_server': {'port': PORT,
|
||||||
#'default_user': "gnunux"},
|
|
||||||
'default_user': DEFAULT_USER},
|
'default_user': DEFAULT_USER},
|
||||||
'global': {'message_root_path': CURRENT_PATH.parents[2] / 'messages',
|
'global': {'message_root_path': CURRENT_PATH.parents[2] / 'messages',
|
||||||
'debug': True,
|
'debug': True,
|
||||||
'internal_user': 'internal',
|
'internal_user': 'internal',
|
||||||
'check_role': True,
|
'check_role': True,
|
||||||
'rougail_dtd_path': '../rougail/data/creole.dtd',
|
'rougail_dtd_path': '../rougail/data/creole.dtd',
|
||||||
'admin_user': DEFAULT_USER},
|
'admin_user': DEFAULT_USER,
|
||||||
|
'admin_user_password': DEFAULT_USER_PASSWORD},
|
||||||
'source': {'root_path': '/srv/seed'},
|
'source': {'root_path': '/srv/seed'},
|
||||||
'cache': {'root_path': '/var/cache/risotto'}
|
'cache': {'root_path': '/var/cache/risotto'},
|
||||||
|
'jwt': {
|
||||||
|
'secret': JWT_SECRET,
|
||||||
|
'token_expire': JWT_TOKEN_EXPIRE,
|
||||||
|
'issuer': URI,
|
||||||
|
'audience': JWT_TOKEN_AUDIENCE}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
from aiohttp.web import Application, Response, get, post, HTTPBadRequest, HTTPInternalServerError, HTTPNotFound
|
from aiohttp.web import Application, Response, get, post, HTTPBadRequest, HTTPInternalServerError, HTTPNotFound, HTTPUnauthorized
|
||||||
|
from aiohttp import BasicAuth, RequestInfo
|
||||||
from json import dumps
|
from json import dumps
|
||||||
from traceback import print_exc
|
from traceback import print_exc
|
||||||
from tiramisu import Config
|
from tiramisu import Config
|
||||||
|
import datetime
|
||||||
|
import jwt
|
||||||
|
|
||||||
from .dispatcher import dispatcher
|
from .dispatcher import dispatcher
|
||||||
from .utils import _
|
from .utils import _
|
||||||
@ -16,7 +18,17 @@ from .services import load_services
|
|||||||
|
|
||||||
def create_context(request):
|
def create_context(request):
|
||||||
risotto_context = Context()
|
risotto_context = Context()
|
||||||
risotto_context.username = request.match_info.get('username',
|
if 'Authorization' in request.headers:
|
||||||
|
token = request.headers['Authorization']
|
||||||
|
if not token.startswith("Bearer "):
|
||||||
|
raise HTTPBadRequest(reason='Unexpected bearer format')
|
||||||
|
token = token[7:]
|
||||||
|
decoded = verify_token(token)
|
||||||
|
if 'user' in decoded:
|
||||||
|
risotto_context.username = decoded['user']
|
||||||
|
return risotto_context
|
||||||
|
else:
|
||||||
|
risotto_context.username = request.match_info.get('username',
|
||||||
get_config()['http_server']['default_user'])
|
get_config()['http_server']['default_user'])
|
||||||
return risotto_context
|
return risotto_context
|
||||||
|
|
||||||
@ -49,7 +61,7 @@ class extra_route_handler:
|
|||||||
try:
|
try:
|
||||||
returns = await cls.function(**kwargs)
|
returns = await cls.function(**kwargs)
|
||||||
except NotAllowedError as err:
|
except NotAllowedError as err:
|
||||||
raise HTTPNotFound(reason=str(err))
|
raise HTTPUnauthorized(reason=str(err))
|
||||||
except CallError as err:
|
except CallError as err:
|
||||||
raise HTTPBadRequest(reason=str(err))
|
raise HTTPBadRequest(reason=str(err))
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
@ -77,7 +89,7 @@ async def handle(request):
|
|||||||
check_role=True,
|
check_role=True,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
except NotAllowedError as err:
|
except NotAllowedError as err:
|
||||||
raise HTTPNotFound(reason=str(err))
|
raise HTTPUnauthorized(reason=str(err))
|
||||||
except CallError as err:
|
except CallError as err:
|
||||||
raise HTTPBadRequest(reason=str(err).replace('\n', ' '))
|
raise HTTPBadRequest(reason=str(err).replace('\n', ' '))
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
@ -141,8 +153,76 @@ async def get_app(loop):
|
|||||||
print()
|
print()
|
||||||
del extra_routes
|
del extra_routes
|
||||||
app.add_routes(routes)
|
app.add_routes(routes)
|
||||||
|
app.router.add_post('/auth', auth)
|
||||||
|
app.router.add_post('/access_token', access_token)
|
||||||
await dispatcher.on_join()
|
await dispatcher.on_join()
|
||||||
return await loop.create_server(app.make_handler(), '*', get_config()['http_server']['port'])
|
return await loop.create_server(app.make_handler(), '*', get_config()['http_server']['port'])
|
||||||
|
|
||||||
|
async def auth(request):
|
||||||
|
auth_code = request.headers['Authorization']
|
||||||
|
if not auth_code.startswith("Basic "):
|
||||||
|
raise HTTPBadRequest(reason='Unexpected bearer format')
|
||||||
|
auth = BasicAuth.decode(auth_code)
|
||||||
|
async with dispatcher.pool.acquire() as connection:
|
||||||
|
async with connection.transaction():
|
||||||
|
# Check role with ACL
|
||||||
|
sql = '''
|
||||||
|
SELECT UserName
|
||||||
|
FROM RisottoUser
|
||||||
|
WHERE UserLogin = $1
|
||||||
|
AND UserPassword = crypt($2, UserPassword);
|
||||||
|
'''
|
||||||
|
res = await connection.fetch(sql, auth.login, auth.password)
|
||||||
|
if res:
|
||||||
|
res = gen_token(auth)
|
||||||
|
if verify_token(res):
|
||||||
|
return Response(text=str(res.decode('utf-8')))
|
||||||
|
else:
|
||||||
|
return HTTPInternalServerError(reason='Token could not be verified just after creation')
|
||||||
|
else:
|
||||||
|
raise HTTPUnauthorized(reason='Unauthorized')
|
||||||
|
|
||||||
|
def gen_token(auth):
|
||||||
|
secret = get_config()['jwt']['secret']
|
||||||
|
expire = get_config()['jwt']['token_expire']
|
||||||
|
issuer = get_config()['jwt']['issuer']
|
||||||
|
audience = get_config()['jwt']['audience']
|
||||||
|
payload = {
|
||||||
|
'user': auth.login,
|
||||||
|
'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=expire),
|
||||||
|
'iss': issuer,
|
||||||
|
'aud': audience
|
||||||
|
}
|
||||||
|
token = jwt.encode(payload, secret, algorithm='HS256')
|
||||||
|
return token
|
||||||
|
|
||||||
|
def access_token(request):
|
||||||
|
expire = get_config()['jwt']['token_expire']
|
||||||
|
secret = get_config()['jwt']['secret']
|
||||||
|
token = request.headers['Authorization']
|
||||||
|
if not token.startswith("Bearer "):
|
||||||
|
raise HTTPBadRequest(reason='Unexpected bearer format')
|
||||||
|
token = token[7:]
|
||||||
|
decoded = verify_token(token)
|
||||||
|
if decoded:
|
||||||
|
decoded['exp'] = datetime.datetime.utcnow() + datetime.timedelta(seconds=expire)
|
||||||
|
token = jwt.encode(decoded, secret, algorithm='HS256')
|
||||||
|
return Response(text=str(token.decode('utf-8')))
|
||||||
|
else:
|
||||||
|
return HTTPUnauthorized(reason='Token could not be verified')
|
||||||
|
|
||||||
|
def verify_token(token):
|
||||||
|
secret = get_config()['jwt']['secret']
|
||||||
|
issuer = get_config()['jwt']['issuer']
|
||||||
|
audience = get_config()['jwt']['audience']
|
||||||
|
try:
|
||||||
|
decoded = jwt.decode(token, secret, issuer=issuer, audience=audience, algorithms=['HS256'])
|
||||||
|
except jwt.ExpiredSignatureError:
|
||||||
|
raise HTTPUnauthorized(reason='Token Expired')
|
||||||
|
except jwt.InvalidIssuerError:
|
||||||
|
raise HTTPUnauthorized(reason='Token could not be verified')
|
||||||
|
except jwt.InvalidAudienceError:
|
||||||
|
raise HTTPUnauthorized(reason='Token audience not match')
|
||||||
|
return decoded
|
||||||
|
|
||||||
tiramisu = None
|
tiramisu = None
|
||||||
|
@ -38,7 +38,7 @@ class AnyOption(Option):
|
|||||||
|
|
||||||
class MessageDefinition:
|
class MessageDefinition:
|
||||||
"""
|
"""
|
||||||
A MessageDefinition is a representation of a message in the Zephir application messaging context
|
A MessageDefinition is a representation of a message in the Risotto application messaging context
|
||||||
"""
|
"""
|
||||||
__slots__ = ('version',
|
__slots__ = ('version',
|
||||||
'uri',
|
'uri',
|
||||||
@ -135,7 +135,7 @@ class ParameterDefinition:
|
|||||||
|
|
||||||
class ResponseDefinition:
|
class ResponseDefinition:
|
||||||
"""
|
"""
|
||||||
An ResponseDefinition is a representation of a response in the Zephir application messaging context
|
An ResponseDefinition is a representation of a response in the Risotto application messaging context
|
||||||
"""
|
"""
|
||||||
__slots__ = ('description',
|
__slots__ = ('description',
|
||||||
'type',
|
'type',
|
||||||
@ -184,7 +184,7 @@ class ResponseDefinition:
|
|||||||
|
|
||||||
class ErrorDefinition:
|
class ErrorDefinition:
|
||||||
"""
|
"""
|
||||||
An ErrorDefinition is a representation of an error in the Zephir application messaging context
|
An ErrorDefinition is a representation of an error in the Risotto application messaging context
|
||||||
"""
|
"""
|
||||||
__slots__ = ('uri',)
|
__slots__ = ('uri',)
|
||||||
|
|
||||||
|
@ -248,7 +248,15 @@ class RegisterDispatcher:
|
|||||||
async def load(self):
|
async def load(self):
|
||||||
# valid function's arguments
|
# valid function's arguments
|
||||||
db_conf = get_config().get('database')
|
db_conf = get_config().get('database')
|
||||||
self.pool = await asyncpg.create_pool(database=db_conf.get('dbname'), user=db_conf.get('user'))
|
|
||||||
|
engine = db_conf.get('engine')
|
||||||
|
host = db_conf.get('host')
|
||||||
|
dbname = db_conf.get('dbname')
|
||||||
|
dbuser = db_conf.get('user')
|
||||||
|
dbpassword = db_conf.get('password')
|
||||||
|
dbport = db_conf.get('port')
|
||||||
|
cfg = "{}://{}:{}@{}:{}/{}".format(engine, dbuser, dbpassword, host, dbport, dbname)
|
||||||
|
self.pool = await asyncpg.create_pool(cfg)
|
||||||
async with self.pool.acquire() as connection:
|
async with self.pool.acquire() as connection:
|
||||||
async with connection.transaction():
|
async with connection.transaction():
|
||||||
for version, messages in self.messages.items():
|
for version, messages in self.messages.items():
|
||||||
@ -271,3 +279,4 @@ class RegisterDispatcher:
|
|||||||
module_name)
|
module_name)
|
||||||
await self.insert_message(connection,
|
await self.insert_message(connection,
|
||||||
f'{version}.{message}')
|
f'{version}.{message}')
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ class Risotto(Controller):
|
|||||||
""" pre-load servermodel and server
|
""" pre-load servermodel and server
|
||||||
"""
|
"""
|
||||||
user_login = get_config()['global']['admin_user']
|
user_login = get_config()['global']['admin_user']
|
||||||
|
user_password = get_config()['global']['admin_user_password']
|
||||||
sql = '''
|
sql = '''
|
||||||
SELECT UserId
|
SELECT UserId
|
||||||
FROM RisottoUser
|
FROM RisottoUser
|
||||||
@ -22,7 +23,8 @@ class Risotto(Controller):
|
|||||||
user_login) is None:
|
user_login) is None:
|
||||||
await self._user_create(risotto_context,
|
await self._user_create(risotto_context,
|
||||||
user_login,
|
user_login,
|
||||||
user_login,
|
user_password,
|
||||||
|
user_login,
|
||||||
user_login)
|
user_login)
|
||||||
await self._user_role_create(risotto_context,
|
await self._user_role_create(risotto_context,
|
||||||
user_login,
|
user_login,
|
||||||
@ -33,14 +35,16 @@ class Risotto(Controller):
|
|||||||
async def _user_create(self,
|
async def _user_create(self,
|
||||||
risotto_context: Context,
|
risotto_context: Context,
|
||||||
user_login: str,
|
user_login: str,
|
||||||
|
user_password: str,
|
||||||
user_name: str,
|
user_name: str,
|
||||||
user_surname: str) -> Dict:
|
user_surname: str) -> Dict:
|
||||||
user_insert = """INSERT INTO RisottoUser(UserLogin, UserName, UserSurname)
|
user_insert = """INSERT INTO RisottoUser(UserLogin, UserPassword, UserName, UserSurname)
|
||||||
VALUES ($1,$2,$3)
|
VALUES ($1,crypt($2, gen_salt('bf')),$3,$4)
|
||||||
RETURNING UserId
|
RETURNING UserId
|
||||||
"""
|
"""
|
||||||
user_id = await risotto_context.connection.fetchval(user_insert,
|
user_id = await risotto_context.connection.fetchval(user_insert,
|
||||||
user_login,
|
user_login,
|
||||||
|
user_password,
|
||||||
user_name,
|
user_name,
|
||||||
user_surname)
|
user_surname)
|
||||||
await self.call('v1.user.role.create',
|
await self.call('v1.user.role.create',
|
||||||
@ -56,10 +60,12 @@ class Risotto(Controller):
|
|||||||
async def user_create(self,
|
async def user_create(self,
|
||||||
risotto_context: Context,
|
risotto_context: Context,
|
||||||
user_login: str,
|
user_login: str,
|
||||||
|
user_password: str,
|
||||||
user_name: str,
|
user_name: str,
|
||||||
user_surname: str) -> Dict:
|
user_surname: str) -> Dict:
|
||||||
return await self._user_create(risotto_context,
|
return await self._user_create(risotto_context,
|
||||||
user_login,
|
user_login,
|
||||||
|
user_password,
|
||||||
user_name,
|
user_name,
|
||||||
user_surname)
|
user_surname)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user