Fonctionnement général d'un Billet
MCD
classDiagram
class Crypto {
+int id
+int signable_id
+string signable_type
+string crypto_klass
+string crypto_options
}
class Billet {
+int id
+string uuid
+text data
+string numero
+datetime cancelled_at
+string cancelled_reason
+int billet_scans_count
}
class BilletScan {
+int id
+int uuid
+int check_errors
+text data
+int before_verify_check_errors
+string mobile_billet_uuid
+int status
}
Crypto "0..*" <--> "1" Billet : signable
Billet "0..*" <--> "1" BilletScan : billet_scans
Class Crypto
La class crypto sert à stocker les données nécessaire pour chiffrer/signer les Billets pour une données signable (Match/ModeleArticle).
On retrouve un getter/setter crypto_handler, il permet de gérer plusieurs methodes d'encodage des billets plus facilement.
Chaque CryptoHandler ont les méthodes suivantes:
encode!(data): Permet d'encoder un payload (Dans notre cas, l'uuid du Billet)-
decode!(data, verify: false): Les données encodées ainsi que l'argument optionnelverifyqui permet de vérifier si la signature est valide.Renvoie une erreur si c'est pas le cas
Note On retrouve exactement les mêmes algos coté Mobile avec les tests associés car l'application devra également vérifier les données encodées stockées dans le QrCode.
On retrouve également la class CryptoHandlers::Base avec le méthode try_decode!(data) qui permet de tester tout les algos et renvoie à la fois les données stockées mais également la class utilisée pour décoder les données.
On peut donc facilement faire
On dispose des Handlers suivants:
-
JwtEddsa : Genère un token JWT signé avec une clef Eddsa et encodé en Base 45
Deprecated : Ce type de data est beaucoup trop lourd (Le QrCode était trop complexe à analyser) et n'est plus utilisé sur la v2.
-
ConcatEddsa : Comme le nom l'indique, on concatène les données avec la signature
[data].[signature encodé en base 45]
On encode les données binaires en Base 45 car c'est la base la plus performante dans les QrCode et surtout recommandé pour cette usage (QrCode).
Eddsa est un algorithme de signature (Ne pas confondre avec un algos de chiffrement comme RSA), il permet de signer un payload avec une clef privé et ensuite de verifier la signature avec la clef publique. Il est recommandé pour les connexions SSH aujourd'hui et il génère une signature beaucoup plus légère que RSA. RSA était également beaucoup trop complexe pour faire un QrCode avec.
Note Les champs suivants ne sont plus nécessaires car ils ont été migrés vers le champ crypto_options:
- algorithm: string
- private_key: string
- public_key: string
Class Billet
Le billet est utilisé par l'application de scan mais également pour généré le QrCode avec la méthode qrcode_png ou qrcode_io.
Un billet est associé une seule pair de clef de crypto utilisée pour encoder et signer son payland (Champ data).
C'est ce champ qui est utilisé pour générer le QrCode.
Il est associé à un seul contact mais peut-être associé à plusieurs matchs pour les cartes d'abonnements. Dans ce cas, le billet doit-être valide pour tout les matchs.
Class BilletScan
À chaque fois que l'application Scan un billet, elle envoie le scan à l'API ou le stocke en BD si l'API n'est pas disponible.
L'application envoie les data du QrCode sur le billet, check_errors avec l'ensemble des erreurs remontées coté Application et le point de contrôle.
Lorsque l'API commence le traitement du scan du billet, l'API stocke directement check_errors dans before_verify_check_errors pour garder une trace
des états coté App de scan. Pratique pour le débogage.
check_errors et before_verify_check_errors sont de type integer mais servent de bit flags.
Pour faire simple, si le flat a == 0b0001, flag b == 0b0010 et que
check_errors== 0b0011, alorscheck_errorscontient le flag a et b.
Sur la billetterie, on a les flags suivants pour le scan d'un billet:
signature_invalid: Le flag est set si la signature dedatan'a pas pu être vérifié par la clef publique deCryptodonc potentiellement un billet frauduleux.payload_invalid: Le flag est set sidatan'a pas pu être décodé par aucunCryptoHandleroù si l'uuid dans lepayloadne correspond pas à l'uuid du Billet.already_scanned: Le flag est set si on a déjà un scan valide pour ce billet. Ça peut-être soit une erreur de Scan soit une personne essaie de passer deux fois le même Billet sur le même point de contrôle.invalid_point_control: Le flag est set si le Billet est valide mais qu'il ne permet pas d'accéder à ce point de contrôle.cancelled: Le flag est set si la personne essaie de scanner un billet annulé.
Note : La 1ère version utilise le concern WithBitsField mais une Merge Request existe pour migrer vers la gem active_flag.
La gem est utilisée pour la partie permissions Gestionnaire, accès module Gestionnaire et pour d'autres modèles.
Le status possède les états suivants:
waiting: Indique que l'API n'a pas encore vérifiée la validité du billetvalid: Indique que le scan ne contient aucune erreur donccheck_errors== 0invalid: Indique que le scan contient des erreurs donccheck_errors> 0. On peut récupérer les erreurs via les bits flags définie danscheck_errors