
Εισαγωγή
Σχεδόν οποιαδήποτε εφαρμογή σήμερα εμπεριέχει την “οντότητα” του χρήστη - user. Το Laravel για παράδειγμα παρέχει ‘προεγκατεστημένο’ το συγκεκριμένο entity. Φαντάζομαι και πολλά ακόμα frameworks άλλων γλωσσών προγραμματισμού.
Το σύστημα ρόλων και δικαιωμάτων χρηστών, είναι μια από τις περιπτώσεις που μπορεί να υλοποιηθεί με απλό αλλά στατικό τρόπο και μπορεί να φτάσει να γίνει αρκετά σύνθετο αλλά ταυτόχρονα ευέλικτο και δυναμικό.
Πριν προχωρήσουμε παρακάτω θα πρέπει να διευκρινίσουμε δύο βασικές έννοιες, αυτή του authentication και αυτή του authorization. Το authentication είναι η διαδικασία όπου πιστοποιούμε έναν χρήστη ότι υπάρχει στο σύστημα μας, δεν είναι δηλαδή ένας άγνωστος επισκέπτης, ενώ το authorization ειναι η διαδικασία όπου πιστοποιούμε ότι ο συγκεκριμένος συνδεδεμένος χρήστης έχει το δικαιώμα να πραγματοποιήσει μια ενέργεια.
Οι προσεγγίσεις πάνω στο συγκεκριμένο ζήτημα
Στο συγκεκριμένο ζήτημα θεωρώ πώς υπάρχουν 3 βασικές θεωρητικές - σχεδιαστικές προσεγγίσεις. Αυτή του ελέγχου σε επίπεδο ρόλου, αυτή του permission group και τέλος αυτή σε επίπεδο δικαιώματος/permission που φτάνει σε low level access. Θεωρητικά όλες μαζί μπορούν να συνδυαστούν μέσα από ξεχωριστά layers. Πάντοτε άλλωστε υλοποιούμε με βάση την ανάγκη και κάθε εφαρμογή έχει ξεχωριστές ανάγκες και στόχους.
Ο έλεγχος σε επίπεδο ρόλου είναι εύκολα υλοποιήσιμος αλλά στατικός.
Ο έλεγχος σε επίπεδο permission group ειναι πιο δύσκολα υλοποιήσιμος αλλά παρέχει καλύτερη ευελιξία
Ο έλεγχος σε επίπεδο permission που φτάνει σε low level ειναι πιο σύνθετος, παρέχει ευελιξία στο μέγιστο δυνατό σημείο αλλά ταυτόχρονα σε μεγάλες εφαρμογές μπορεί να προσφέρει κακό UX. Σκεφτείτε δηλαδή να έχετε 300 entities Χ 4 actions (read, update, create, delete) και ο χρήστης να πρέπει να διαχειριστεί - δει τόσες επιλογές.
Μια μιξη των παραπάνω λοιπόν φαντάζει ως την καλύτερη επιλογή.
Ας περιγράψουμε τώρα πώς θα σχεδιάζαμε ένα τέτοιο σύστημα.
Ρόλος χρήστη: Ο ρόλος χρήστη πρέπει να επιτελεί δύο λειτουργίες. Να μας δείχνει αφενός το αξίωμα - τίτλο του χρήστη, αφετέρου να μας περιγράφει τις μέγιστες επιλογές απο permissions ή permission groups που μπορεί να δεχθεί. Οι μέγιστες επιλογές απο permissions για κάθε ρόλο μπορούν να συνδεθούν με subscription plans ή με το οποιοδήποτε μοντέλο της εφαρμογής μας.
Permissions groups: Ουσιαστικά για λόγους καλύτερου UX έχουμε ομαδοποιήσει σε πακέτα τα δικαιώματα σε low level που θα περιγράψουμε παρακάτω. Για παράδειγμα το λεκτικό User management μπορεί να εμπεριέχει τα δικαιώματα για [προβολή, δημιουργία, επεξεργασία, διαγραφή] χρήστη. Ο χρήστης δηλαδή επιλέγει - βλέπει μια επιλογή αντί για 4, φυσικά αυτό έχει limitations.
Low level permissions: Είναι απαραίτητο να ορίσουμε κάπου όλα τα δικαιώματα της εφαρμογής μας σε low level. Για παράδειγμα με το dot notation pattern το οποίο χρησιμοποιεί κατα κόρον το Laravel και είναι κοντά στην λογική των access lists, μπορούμε να το κάνουμε αυτό όμορφα, απλά και καθαρά γράφοντας για παράδειγμα “users.settings.security.change-password” το οποίο σε φυσική γλώσσα είναι εύκολα κατανοητό ακόμα και από μη engineers και μεταφράζεται ως “απο τους χρήστες/ρυθμίσεις/ασφαλείας δικαιώματα αλλαγής κωδικού”.
Το να έχουμε τα permissions σε low level είναι απαραίτητο για πολλούς λόγους. Αν δεν έχουμε αυτό το low level layer και φτάσουμε μόνο μέχρι τα permission groups σύντομα θα συναντήσουμε σημαντικές δυσκολίες - προβλήματα που θα ξεκινούν από το να έχουμε conflicts μεταξύ των entities και των permission groups μέχρι δυσκολία επικοινωνίας της ομάδας, χαμηλότερη παραγωγικότητα, θέματα ασφαλείας κ.α. Για παράδειγμα αν έχουμε το permission group “Manage user settings” ON αλλά το “Manage user passwords" OFF δεν είναι εύκολα κατανοητό ποιο υπερισχύει σε περίπτωση αλλαγής κωδικού χρήστη, διότι το πρώτο φαίνεται πώς καλύπτει όλες τις ρυθμίσεις όπως και αυτές της αλλαγής κωδικού αλλά η δεύτερη φαίνεται πιο στοχευμένη. Αν όμως αύριο η διαχείριση κωδικού πρέπει να μεταφερθεί σε άλλο επίπεδο και να μην ανήκει στις ρυθμίσεις του χρήστη, τότε το χαός ξεκινά. Αυτό φυσικά ειναι ένα απλό παράδειγμα μπροστά στην πολυπλοκότητα που μπορεί να χτιστεί. Το να έχουμε επίσης σε low level τα permissions μας προσφέρει την δυνατότητα να χτίσουμε το UI μας πιο ευκολα και πιο σωστά, να δείξουμε στον χρήστη (αλλά και τον νεοεισερχόμενο προγραμματιστή) το κάθε permission group ποιά low level permissions διαθέτει σήμερα αλλά και να εμφανίσουμε advanced settings στον χρήστη με δυνατότητα αντί για permission groups να διαχειριστεί τα permissions μόνος του.
Εφόσον λοιπόν καταλήξουμε σε μια δομή σαν την παραπάνω, μετά μπορούμε να δημιουργήσουμε ένα generic app permissions service/class το οποίο θα είναι υπεύθυνο για το authorization της εφαρμογής και μέσα θα σηκώνει (Dependency injection προσοχή) τα ειδικά services π.χ userPermissionsService κ.α. Αυτό μπορούμε να το χρησιμοποιούμε σε οποιοδήποτε σημείο ή επίπεδο της εφαρμογής, σύμφωνα με την δομή, τις ανάγκες και τους στόχους μας.
Ελπίζω να βρήκατε ενδιαφέρον το άρθρο μου.
Προσίλης Αργύρης
Software engineer Go/PHP