You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

94 lines
2.8 KiB

  1. #lang racket
  2. (require db
  3. redis
  4. json
  5. racket/set
  6. threading
  7. "db.rkt")
  8. (provide get-user
  9. get-group
  10. get-groups-by-member
  11. add-user
  12. add-group
  13. (struct-out user)
  14. (struct-out group))
  15. ; A simple (placeholder) user type, to be replaced by one isomorphic
  16. ; to the GeneNetwork user type.
  17. (struct user (id name)
  18. #:transparent)
  19. ;; Retrieve the given user by ID from Redis; deserializes from JSON
  20. ;; TODO update this when we update the user struct
  21. (define (get-user dbc id)
  22. (let ((user-hash (bytes->jsexpr
  23. (redis-hash-ref dbc "users" id))))
  24. (user id
  25. (dict-ref user-hash 'email_address))))
  26. ;; Add a user with the given ID and name to the "users" hash in Redis.
  27. ;; NB: This is mainly for testing locally; the proxy shouldn't create
  28. ;; users in production.
  29. (define (add-user dbc id name)
  30. (redis-hash-set! dbc
  31. "users"
  32. id
  33. (jsexpr->bytes (hash 'email_address name))))
  34. ; A group is a product of two sets of users, admins and members. A
  35. ; user can be either an admin or a member, not both. Logically, for
  36. ; access control purposes, being an admin implies being a member.
  37. (struct group (id admins members)
  38. #:transparent)
  39. ;; Deserialize a group struct from bytestringified JSON
  40. (define (deserialize-group id grp-bytes)
  41. (let ((group-hash (bytes->jsexpr grp-bytes)))
  42. (define (parse k)
  43. (~> (dict-ref group-hash k)
  44. (list->set)))
  45. (group id
  46. (parse 'admins)
  47. (parse 'members))))
  48. ;; Retrieve the given group by ID from Redis
  49. (define (get-group dbc id)
  50. (deserialize-group id
  51. (redis-hash-ref dbc
  52. "groups"
  53. id)))
  54. ;; NB: like add-user, for testing in the REPL
  55. (define (add-group dbc id admins members)
  56. (redis-hash-set! dbc
  57. "groups"
  58. id
  59. (jsexpr->bytes
  60. (hash 'admins (set->list admins)
  61. 'members (set->list members)))))
  62. ;; Search Redis and return all the groups that have the given user ID
  63. ;; as either an admin or a regular member.
  64. ;; TODO Redis almost certainly has tools to make this faster & better
  65. (define (get-groups-by-member dbc user-id)
  66. (define (parse e)
  67. (deserialize-group (car e) (cdr e)))
  68. (for/list ([group (sequence-map parse
  69. (in-redis-hash dbc "groups"))]
  70. #:when (has-user? group user-id))
  71. group))
  72. ;; Helper functions for querying groups
  73. (define (has-admin? g uid)
  74. (set-member? (group-admins g) uid))
  75. (define (has-member? g uid)
  76. (set-member? (group-members g) uid))
  77. (define (has-user? g uid)
  78. (or (has-admin? g uid) (has-member? g uid)))