Clojure practice task:
Managing User Permissions with Sets
You are developing a role-based access control system for a web application. Each user has a set of permissions (e.g., :read, :write, :delete). Your goal is to implement a permission management system using Clojure sets.
User {:user-name :email :permission}
The set of all available permissions in the system is :read :write :delete.
Tasks
Create a function to assign a set of permissions to a user.
(defn valid-user-permission? [permission]
(subset? permission #{:read :write :delete}))
(defn valid-user? [user]
(and (some? (:user-name user))
(some? (:email user))))
(defn assign-user-permissions [user permissions]
(when (and (valid-user? user) (valid-user-permission? permissions))
(assoc user :permissions permissions)))
Write a function to check if a user has a specific permission.
(defn has-user-permission? [user permission]
(when (and (valid-user? user) (valid-user-permission? #{permission}))
(contains? (:permissions user) permission)))
Write a function to revoke a specific permission from a user.
(defn revoke-user-permissions [user permission]
(when (and (valid-user? user) (valid-user-permission? #{permission}))
(let [current-p (:permissions user)
remove-p (disj current-p permission)]
(assoc user :permissions remove-p)
)))
Find users who have at least one common permission from a given permission set.
(defn find-users-common-permissions [users permissions]
(filter #(subset? permissions (:permissions %)) users))
Find users who have all required permissions from a given permission set.
(defn find-users-all-permissions [users permissions]
(filter #(= permissions (:permissions %)) users))
Compute the difference between two users permissions.
(defn diff-users-permissions [user-1 user-2]
(difference (:permissions user-1) (:permissions user-2)))
Generate a report of all users and their permissions.
Example Alice -> #{:read :write}
(defn users-permissions-report [users]
(map #(let [user (:user-name %)
permissions (:permissions %) ]
(cond
(some? permissions) (str user " -> " permissions)
:else (str user)
))
users))
Top comments (1)
Hi Ivan, how are you? I hope you're doing well! :)
I really liked your implementation and wanted to share a suggestion. What do you think about using clojure.spec for validations instead of creating separate validator functions? I feel it could be a more natural way to handle this in Clojure. It would let you cleanly separate attribute validations from business logic in a scalable way, plus you’d get better error handling and richer feedback beyond just "true or false." What do you think?