Échange de données 1

Laboratoire 3

Laboratoire 4

Vous devez développer un service de transformation de données utilisant une application terminal tierce. Le serveur doit recevoir un fichier et générer un fichier transformé via l'outil choisi. Analysez les requêtes-réponses pour élaborer les fonctionnalités du serveur.

Démontrez ensuite le fonctionnement du serveur en implémentant des requêtes brutes et affichage pertinent des réponse dans un client Ruby: 1 requête positive, 1 requête alternative significative et différente.

BONUS

Pour compléter votre exploration des concepts du cours, vous pouvez étoffer votre projet d'un élément qui n'a pas été vu en classe, par exemple :

  • Client (connexion, liste, ajout, modification, suppression)
  • Tests unitaires exhaustifs
  • Approche orientée-objet/modules en Ruby, Ruby OOP
  • Utilisation d'une base de donnée relationnelle, SQLite
  • Autre fonctionnalité supplémentaire pertinente... ?

Vous devez faire approuver votre choix d'outil(et de bonus)!

Persistence des données

Vous devez implémenter un mécanisme d'authentification HTTP Basic multi-usagers persistente. Vous pouvez créer manuellement les utilisateurs sur le serveur.

Le résultat de chaque transformation effectuée par les utilisateurs doit être enregistré dans un fichier et une base de données permet d'associer chaque fichier à son propriétaire, en plus des informations suivantes

  • name, nom du fichier original téléversé
  • timestamp, date et heure(format "%F %T") de la transformation
  • password, mot de passe optionnel pour protéger le fichier
  • uuid, identifiant unique alphanumérique généré lors de la transformation

Vous devez également effectuer les validations nécessaires pour assurer l'intégrité des données.


Les routes suivantes sont accessibles sans authentification obligatoire.

Gallerie

Affiche ce fichier HTML

http
GET / HTTP/1.1

===

... Fichier gallery.html ...

Liste

Retourne les informations des fichiers

http
GET /files HTTP/1.1

===

200
Content-Type: application/json
[
{ uuid: _string_, name: _string_, timestamp: _string_, private: _boolean_, mine: _boolean_ },
...
]
  • Trier les items en affichant ceux de l'utilisateur en premier si authentifié, puis du plus récent au plus ancien et nom de fichier croissant.
    • On peut retourner un tableau de la fonction sort_by pour préciser plusieurs conditions de tri
      rb
      [
      {nom: "charlie", age: 10},
      {nom: "alice", age: 10},
      {nom: "bob", age: 20}
      ].sort_by {|p| [ p[:age], p[:nom] ]}
    • Pour ajuster le tri ascendant ou descendant, on peut inverser la valeur via un calcul dans le sort_by.
    • Si le résultat du calcul est un booléen, on doit le convertir pour la comparaison dans le tri.
  • Attention la représentation des données dans la réponse est DIFFÉRENTE des données de la base de données. Le serveur doit traiter les données AVANT de les retourner

    • Par exemple, la base de données contient
      Prenom | Nom | Naissance
      -----------------------------
      James | Hoffman | 1990
      Mathieu | St-Yves | 1980
      Lyne | Amyot | 1970
    • Le serveur peut transformer les données pour produire la réponse suivante
      Nom complet | Age
      ----------------------
      James Hoffman | 30
      Mathieu St-Yves | 40
      Lyne Amyot | 50
    • Donc on CALCULE les valeurs pertinentes à partir des données brutes

Récupérer un fichier

  • Si le fichier est protégé, le pass doit correspondre
  • Sinon, si l'utilisateur est authentifié ET qu'il est le propriétaire, le pass est ignoré
http
GET /files/...uuid...?pass=... HTTP/1.1

===

... Fichier correspondant au uuid ...

~~~ Si uuid invalide

404
File not found

~~~ Si pass incorrecte OU pas propriétaire

403
Access denied

Authentification

  • Il n'y a pas de log out avec l'authentification basique dans le navigateur, utilisez une fenêtre privée pour tester. Vous serez déconnecté à la fermeture de la fenêtre.
http
GET /login HTTP/1.1

===

303
Location: /

~~~ Si authentification invalide

401
WWW-Authenticate: Basic
Invalid credentials


Les routes qui suivent requiert l'authentification de l'usager, et n'affectent que les données qui lui appartiennent

Transformation

Pour créer un nouveau fichier et ses informations.

  • On envoit la requête au format multipart pour permettre de joindre des fichiers
  • On peut préciser un mot de passe pour protéger l'accès au fichier
  • On peut préciser les arguments de l'outils de transformation au format JSON
  • Lors d'une réponse positive, on retourne le résultat de la transformation en body et l'URL via un header
http
POST /files HTTP/1.1
Authorization: Basic ...
Content-Type: multipart/form-data

-----------------------------
Content-Disposition: form-data; name="password"

shawi123
-----------------------------
Content-Disposition: form-data; name="original_file"; filename="demo.txt"
Content-Type: text/plain

Content of demo.txt
-----------------------------
Content-Disposition: form-data; name="options"

{ some: ..., option: ... }
-----------------------------

===

201
Content-Location: /files/...uuid...

... Fichier traité ...

~~~ Si erreur

400
...Message...

~~~ Si pas authentifié

401
WWW-Authenticate: Basic
Authentication required

Modification

Permet d'ajouter/retirer le mot de passe d'un fichier

  • Le mot de passe, ou vide, est envoyé directement dans le body
http
PATCH /files/...uuid... HTTP/1.1

... password ...

===

204

~~~ Si uuid invalide, ou pas propriétaire

404
File not found

~~~ Si erreur

400
...Message...

~~~ Si pas authentifié

401
WWW-Authenticate: Basic
Authentication required

Suppression

Efface le fichier et ses informations de la base de données

http
DELETE /files/...uuid... HTTP/1.1
===

204

~~~ Si uuid invalide, ou pas propriétaire

404
File not found

~~~ Si erreur

400
...Message...

~~~ Si pas authentifié

401
WWW-Authenticate: Basic
Authentication required

Outils

Suggestions tokei
bash
wget https://github.com/XAMPPRocky/tokei/releases/download/v12.1.2/tokei-x86_64-unknown-linux-gnu.tar.gz
su root -c "tar -xf tokei-x86_64-unknown-linux-gnu.tar.gz --directory=/usr/bin"
bash
Usage
tokei
tesseract ocr
bash
su root -c "apt install tesseract-ocr -y"
bash
Usage
tesseract
boxes
bash
su root -c "apt install boxes -y"
bash
Usage
boxes
figlet
bash
su root -c "apt install figlet -y"
bash
Usage
figlet
toilet
bash
su root -c "apt install toilet -y"
bash
Usage
toilet
markmap
bash
su root -c "apt install nodejs npm -y"
su root -c "npm install -g markmap-cli"
bash
Usage
markmap
triangle
bash
wget https://github.com/esimov/triangle/releases/download/v2.0.0/triangle-2.0.0-linux-amd64.tar.gz
su root -c "tar -xvf triangle-2.0.0-linux-amd64.tar.gz triangle-2.0.0-linux-amd64/triangle -O > /usr/bin/triangle; chmod 755 /usr/bin/triangle"
bash
Usage
triangle
wkhtmltopdf / wkhtmltoimage
bash
su root -c "apt install wkhtmltopdf -y"
bash
Usage
wkhtmltopdf
bash
Usage
wkhtmltoimage
cowsay
bash
su root -c "apt install cowsay -y"
bash
Usage
cowsay
diff2html
bash
su root -c "apt install nodejs npm -y"
su root -c "npm install -g diff2html-cli"
bash
Usage
diff -u file1.txt file2.txt | diff2html -i stdin
jq
bash
su root -c "apt install jq -y"
bash
Usage
jq
hget
bash
su root -c "apt install nodejs npm -y"
su root -c "npm install -g hget"
bash
Usage
hget
qrencode
bash
su root -c "apt install qrencode -y"
bash
Usage
qrencode
ffmpeg
bash
su root -c "apt install ffmpeg -y"
bash
Usage
ffmpeg
markdown
bash
su root -c "apt install markdown -y"
bash
Usage
markdown
graphicsmagick
bash
su root -c "apt install graphicsmagick -y"
bash
Usage
magick
ASCII Image Converter
bash
su root -c "echo 'deb [trusted=yes] https://apt.fury.io/ascii-image-converter/ /' | sudo tee /etc/apt/sources.list.d/ascii-image-converter.list"
su root -c "apt update && apt install ascii-image-converter -y"
bash
Usage
ascii-image-converter
odiff
bash
su root -c "apt install nodejs npm -y"
su root -c "npm install -g odiff-bin"
bash
Usage
odiff
markmap cli
bash
su root -c "apt install nodejs npm -y"
su root -c "npm install -g markmap-cli"
bash
Usage
markmap-cli
mermaid cli
bash
su root -c "apt install ca-certificates fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils"
su root -c "apt install nodejs npm -y"
su root -c "npm install -g @mermaid-js/mermaid-cli"
bash
Usage
mmdc

Compléments techniques

Téléversement de fichiers
rb
server.txt
require "bundler/inline"

gemfile do
source "http://rubygems.org"

gem "sinatra"

gem "rackup"
gem "webrick"
end

require "sinatra/base"

class SinatraFileUpload < Sinatra::Base

post "/" do
return [
params.to_s,
"title = " + params["title"],
params["demo_file"]["filename"] + " = " + params["demo_file"]["tempfile"].read
].join("\n\n")
end

run! if app_file == $0
end
txt
file.txt
Hello world!!!
rb
client.rb
require "bundler/inline"

gemfile do
source "http://rubygems.org"
gem "faraday"

# https://github.com/lostisland/faraday-multipart
gem "faraday-multipart"
end

require "faraday"
require "faraday/multipart"

server = Faraday.new("http://localhost:4567") do |f|
f.request :multipart
end

data = {
title: "demo file upload",
demo_file: Faraday::Multipart::FilePart.new("file.txt", "text/plain")
}

response = server.post("/", data)

puts(response.body)
Réponse
{
"title"=>"demo file upload",
"demo_file"=>{
"filename"=>"file.txt",
"type"=>"text/plain",
"name"=>"demo_file",
"tempfile"=> Tempfile:/tmp/RackMultipart20221119-13201-151pi1f.txt,
"head"=>"
Content-Disposition: form-data;
name="demo_file";
Content-Length: 16\r\n
Content-Type: text/plain\r\n
Content-Transfer-Encoding: binary\r\n
"
}
}

title = demo file upload

file.txt = Hello world!!!

Exécution d'un programme externe
txt
original.txt
3
4
2
6
7
3
4
5
7
3
6
rb
code.rb
# Demonstration de l'utilisation d'un programme externe via Ruby

# https://docs.ruby-lang.org/en/3.1/Kernel.html#method-i-system

# avec les utilitaires standards uniq et sort

filename = "original.txt"
output = "result.txt"

# sort original.txt | uniq > result.txt
system("sort #{filename} | uniq > #{output}")
txt
result.txt
2
3
4
5
6
7

Remise

18 décembre, 8h via LÉA

  • Une pénalité de 10% sera appliquée à la note finale pour chaque jour de retard à la remise.
  • Remettre tous les fichiers pertinents de votre projet dans une archive ZIP via la remise de travail LÉA.
    • Votre application Sinatra doit se trouver dans le fichier server.rb
    • Vos requêtes client brutes doivent se trouver dans le fichier client.rb

Échange de données 1

Nom:


Outil __________________________

Suivis formatifs
#1
GET /login (     1     0.5     0     )
GET /files, public vs auth, données brutes (     2     1.5     1     0     )
GET /, affichage de la liste, différents cas (     1     0.5     0     )
#2
POST /files, transformation et persistence (     2     1.5     1     0     )
GET /files, données réelles (     1     0.5     0     )

Livraison
Zip, Fichiers requis 0     -0.5     -1     -2
Qualité de rédaction, Nomenclature, Formatage 0     -0.5     -1     -2
Qualité de l'implémentation, syntaxe, mécanismes, réutilisation 0     -0.5     -1     -2
Gallerie
GET / = Fichier gallery.html 1     0.5     0
Liste
GET /files = 200, tableau JSON 2     1.5     1     0
Tri propriétaire en premier, si authentifié 1     0.5     0
Tri date descendant ET nom ascendant 1     0.5     0
Représentation des données uuid, name, timestamp, private, mine 2     1.5     1     0
Récupération
GET /files/...uuid... = 200, fichier correspondant 2     1.5     1     0
Sinon 404, not found 1     0.5     0
?pass=... doit correspondre sauf si propriétaire authentifié 1     0.5     0
Sinon 403, access denied 1     0.5     0
Authentification
GET /login = 303, redirection / 2     1.5     1     0
Sinon 401, invalid 1     0.5     0
Plusieurs utilisateurs, Gestion sécuritaire du mot de passe 0     -1     -2
Transformation
POST /files 1     0.5     0
password, original file, options JSON 2     1.5     1     0
= 201, content-location, fichier résultat 2     1.5     1     0
Sinon 401, auth required 1     0.5     0
Validations pertinentes = 400, erreur... 2     1.5     1     0
Persistence des informations de la transformation 1     0.5     0
Génération du fichier résultat de la transformation via l'outil, avec les options supplémentaires 2     1.5     1     0
Modification
PATCH /files/...uuid... , password = 204, persistence 2     1.5     1     0
404, not found OU pas propriétaire 1     0.5     0
401, auth required 1     0.5     0
400, message... 1     0.5     0
Suppression
DELETE /files/...uuid... = 204, persistence, suppression du fichier 2     1.5     1     0
404, not found OU pas propriétaire 1     0.5     0
401, auth required 1     0.5     0
400, message... 1     0.5     0
Client
GET /files positive, alternative, affichage 2     1.5     1     0
GET /files/...uuid..?pass positive, alternative, affichage 2     1.5     1     0
POST /files positive, alternative, affichage 2     1.5     1     0
PATCH /files/...uuid... positive, alternative, affichage 2     1.5     1     0
DELETE /files/...uuid... positive, alternative, affichage 2     1.5     1     0
BONUS

__________________________
+5     0