Skip to content

Commit 0f33b48

Browse files
implementing persona deletion and sharing updates
- deleting a persona removes and shares/invites to/from that persona (creating the correct sync records along the way) - moving a chunk of sync code that deals with expanding (un)share sync items into the sync model - bugfixes in general
1 parent 9fe8a84 commit 0f33b48

File tree

5 files changed

+119
-44
lines changed

5 files changed

+119
-44
lines changed

controllers/sync.lisp

+5-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"Given the current user and a sync-id, spits out all data that has changes in
55
the user's profile since that sync id. Used by various clients to stay in
66
sync with the canonical profile (hosted on the server).
7-
7+
88
Unlike the /sync/full call, this is stateful...we are syncing actual profile
99
changes here and thus depend on syncing the correct data. A mistake here can
1010
put bad data into the profile that will sit there until the app clears its
@@ -14,7 +14,7 @@
1414
tricky is for 'share' and 'unshare' sync records: we have to create a bunch
1515
of fake sync records that add the board(s) and their note(s) to the profile
1616
and make sure they are injected at the correct place in the sync result.
17-
17+
1818
So in the cases where we're fabricating sync items, we have to be cautious
1919
to add/remove the correct data or the app is going to have a bad time."
2020
(alet* ((user-id (user-id req))
@@ -40,17 +40,16 @@
4040
;; if we have a "share", convert it to a vector of "add" sync
4141
;; items
4242
(when (string= (gethash "action" rec) "share")
43-
;; convert the CURRENT sync item to an add
44-
(setf (gethash "action" rec) "add")
43+
;; convert the CURRENT sync item to a nop (remove later)
44+
(setf (gethash "action" rec) "nop")
4545
(case (intern (string-upcase (gethash "type" rec)) :keyword)
4646
;; can only share boards atm
4747
(:board
4848
(push (convert-board-share-to-sync (gethash "id" data)) shares))))
4949
;; if we have an "unshare", convert it to a vector of "delete"
5050
;; sync items
5151
(when (string= (gethash "action" rec) "unshare")
52-
;; convert the CURRENT sync item to a NOP (will be removed
53-
;; later down the line)
52+
;; convert the CURRENT sync item to a nop (remove later)
5453
(setf (gethash "action" rec) "nop")
5554
(case (intern (string-upcase (gethash "type" rec)) :keyword)
5655
;; can only unshare boards atm

models/boards.lisp

+17-13
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,13 @@
451451
;; this separate "share" action is sent only to the invitee, and
452452
;; signifies the sync controller to pull out all notes for this board
453453
;; and return them
454-
(share-sync-ids (add-sync-record user-id
455-
"board"
456-
board-id
457-
"share"
458-
:rel-ids (list (gethash "user_id" to-persona)))))
454+
(share-sync-ids (if (hash-table-p to-persona)
455+
(add-sync-record user-id
456+
"board"
457+
board-id
458+
"share"
459+
:rel-ids (list (gethash "user_id" to-persona)))
460+
#())))
459461
(r:disconnect sock)
460462
(setf (gethash "sync_ids" link-data) (concatenate 'vector
461463
sync-ids
@@ -488,13 +490,14 @@
488490
;; this separate "unshare" action is sent only to the departed, and
489491
;; signifies the sync controller to delete all notes
490492
(to-persona (get-persona-by-id to-persona-id))
491-
(persona-user-id (gethash "user_id" to-persona))
492-
(share-sync-ids (add-sync-record user-id
493-
"board"
494-
board-id
495-
"unshare"
496-
:rel-ids (list persona-user-id)
497-
:no-auto-add-user t)))
493+
(share-sync-ids (if (hash-table-p to-persona)
494+
(add-sync-record user-id
495+
"board"
496+
board-id
497+
"unshare"
498+
:rel-ids (list (gethash "user_id" to-persona))
499+
:no-auto-add-user t)
500+
#())))
498501
(r:disconnect sock)
499502
(concatenate 'vector sync-ids share-sync-ids)))
500503

@@ -507,7 +510,8 @@
507510
(to-persona (get-persona-by-id to-persona-id)))
508511
(flet ((do-delete ()
509512
(alet* ((sync-ids (do-delete-board-persona-link user-id board-id to-persona-id)))
510-
(if delete-keychain-entries
513+
(if (and (hash-table-p to-persona)
514+
delete-keychain-entries)
511515
(alet* ((to-user-id (gethash "user_id" to-persona))
512516
(keychain-sync (delete-keychain-tree user-id to-user-id board-id)))
513517
(concatenate 'vector sync-ids keychain-sync))

models/invites.lisp

+56
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747

4848
(adefun get-persona-invites (persona-ids &key return-tokens)
4949
"Get all invites to or from the given persona ids."
50+
(when (zerop (length persona-ids))
51+
(return-from get-persona-invites #()))
5052
(flet ((get-invites (persona-ids index)
5153
(alet* ((sock (db-sock))
5254
(query (r:r
@@ -144,6 +146,60 @@
144146
:rel-ids user-ids)))
145147
sync-ids))
146148

149+
(adefun delete-persona-invites (user-id persona-id)
150+
"Delete any invites from/to a persona. No permissions checks, so don't call
151+
this unless you know user-id owns persona-id (or some other check has been
152+
performed)."
153+
(alet* ((sock (db-sock))
154+
(query (r:r
155+
(:set-union
156+
(:coerce-to (:pluck
157+
(:get-all
158+
(:table "invites")
159+
persona-id
160+
:index (db-index "invites" "to"))
161+
(list "id" "from" "to"))
162+
"array")
163+
(:coerce-to (:pluck
164+
(:get-all
165+
(:table "invites")
166+
persona-id
167+
:index (db-index "invites" "from"))
168+
(list "id" "from" "to"))
169+
"array"))))
170+
(cursor (r:run sock query))
171+
(invites (r:to-array sock cursor))
172+
(nil (r:stop sock cursor))
173+
(query (r:r (:delete (:get-all (:table "invites") persona-id :index (db-index "invites" "to")))))
174+
(nil (r:run sock query))
175+
(query (r:r (:delete (:get-all (:table "invites") persona-id :index (db-index "invites" "from")))))
176+
(nil (r:run sock query))
177+
(persona-ids (loop for inv across invites
178+
for from = (gethash "from" inv)
179+
for to = (gethash "to" inv)
180+
append (list from to)))
181+
(personas (get-personas-by-ids persona-ids))
182+
(persona-idx (let ((idx (hash)))
183+
(loop for persona across personas
184+
for id = (gethash "id" persona) do
185+
(setf (gethash id idx) persona))
186+
idx))
187+
(sync-records (map 'vector
188+
(lambda (invite)
189+
(let* ((id (gethash "id" invite))
190+
(from (gethash "from" invite))
191+
(to (gethash "to" invite))
192+
(from-user (gethash "user_id" (gethash from persona-idx (hash))))
193+
(to-user (gethash "user_id" (gethash to persona-idx (hash)))))
194+
(make-sync-record user-id
195+
"invite"
196+
id
197+
"delete"
198+
:rel-ids (remove-if-not 'identity (list from-user to-user)))))
199+
invites))
200+
(nil (insert-sync-records sync-records)))
201+
(map 'vector (lambda (s) (gethash "id" s)) sync-records)))
202+
147203
(adefun create-board-invite (user-id board-id invite-data)
148204
"Create an invite record."
149205
(alet* ((perms (get-user-board-permissions user-id board-id)))

models/personas.lisp

+40-18
Original file line numberDiff line numberDiff line change
@@ -144,37 +144,59 @@
144144
(defafun delete-persona (future) (user-id persona-id)
145145
"Delete a persona."
146146
(with-valid-persona (persona-id user-id future)
147-
(alet* ((sock (db-sock))
147+
(format t "- dp: start~%")
148+
(alet* ((nil (delete-persona-links user-id persona-id))
149+
(nil (format t "dp: deleted links~%"))
150+
(nil (delete-persona-invites user-id persona-id))
151+
(nil (format t "dp: deleted invites~%"))
152+
(sock (db-sock))
148153
(query (r:r (:delete (:get (:table "personas") persona-id))))
149154
(nil (r:run sock query))
150-
(sync-ids (add-sync-record user-id "persona" persona-id "delete"))
151-
(nil (delete-persona-links user-id persona-id)))
155+
(sync-ids (add-sync-record user-id "persona" persona-id "delete")))
156+
(format t "dp: add sync~%")
152157
(r:disconnect sock)
153158
(finish future sync-ids))))
154159

155-
(defafun delete-persona-links (future) (user-id persona-id)
160+
;; TODO: either move this board model, or move delete-persona-invites to this
161+
;; model.
162+
(adefun delete-persona-links (user-id persona-id)
156163
"Delete all persona-related information. This generally means board-persona
157164
links."
158165
(alet* ((sock (db-sock))
159166
(query-boards (r:r (:set-union
160-
(:coerce-to (:attr (:get-all (:table "boards_personas_link") persona-id :index (db-index "boards_personas_link" "to")) "board_id") "array")
161-
(:coerce-to (:attr (:get-all (:table "boards_personas_link") persona-id :index (db-index "boards_personas_link" "from")) "board_id") "array"))))
167+
(:coerce-to (:pluck (:get-all (:table "boards_personas_link") persona-id :index (db-index "boards_personas_link" "to")) (list "board_id" "to")) "array")
168+
(:coerce-to (:pluck (:get-all (:table "boards_personas_link") persona-id :index (db-index "boards_personas_link" "from")) (list "board_id" "to")) "array"))))
169+
(cursor (r:run sock query-boards))
170+
(board-links (r:to-array sock cursor))
171+
(nil (r:stop sock cursor))
162172
(query-to (r:r (:delete (:get-all (:table "boards_personas_link") persona-id :index (db-index "boards_personas_link" "to")))))
163173
(query-from (r:r (:delete (:get-all (:table "boards_personas_link") persona-id :index (db-index "boards_personas_link" "from")))))
164-
(cursor (r:run sock query-boards))
165-
(board-ids (r:to-array sock cursor))
166-
(board-ids (coerce board-ids 'list))
167-
(nil (when cursor (r:stop sock cursor)))
168174
(nil (r:run sock query-to))
169175
(nil (r:run sock query-from))
170-
(sync-records nil))
171-
(wait (adolist (board-id board-ids)
172-
(alet ((user-ids (get-affected-users-from-board-ids (list board-id))))
173-
(push (make-sync-record user-id "board" board-id "edit" :rel-ids user-ids) sync-records)))
174-
(wait (when sync-records
175-
(insert-sync-records sync-records))
176-
(r:disconnect sock)
177-
(finish future t)))))
176+
(sync-records nil)
177+
;; loop over the board links, grab affected users, and push our sync
178+
;; records
179+
(nil (all (loop for link across board-links
180+
for board-id = (gethash "board_id" link)
181+
for to = (gethash "to" link) collect
182+
(alet* ((user-ids (get-affected-users-from-board-ids (list board-id)))
183+
(to-persona (get-persona-by-id to))
184+
(to-user-id (gethash "user_id" to-persona)))
185+
;; edit the board
186+
(push (make-sync-record user-id
187+
"board"
188+
board-id
189+
"edit"
190+
:rel-ids user-ids) sync-records)
191+
(push (make-sync-record user-id
192+
"board"
193+
board-id
194+
"unshare"
195+
:rel-ids (list to-user-id)
196+
:no-auto-add-user t) sync-records)))))
197+
(nil (insert-sync-records sync-records)))
198+
(r:disconnect sock)
199+
(map 'vector (lambda (sync) (gethash "id" sync)) sync-records)))
178200

179201
(defafun get-persona-by-email (future) (email &key ignore-persona require-key)
180202
"Grab a persona via its email. Must be an exact match (for now)."

models/sync.lisp

+1-7
Original file line numberDiff line numberDiff line change
@@ -373,13 +373,7 @@
373373
(get-board-tree board-id)
374374
(concatenate
375375
'vector
376-
(map 'vector
377-
(lambda (board) (convert-to-sync board "board"))
378-
;; don't need to sync the shared board since it's
379-
;; already in he sync list
380-
(remove-if (lambda (board)
381-
(string= (gethash "id" board) board-id))
382-
boards))
376+
(map 'vector (lambda (board) (convert-to-sync board "board")) boards)
383377
(map 'vector (lambda (note) (convert-to-sync note "note")) notes))))
384378

385379
(adefun convert-board-unshare-to-sync (user-id board-id)

0 commit comments

Comments
 (0)