diff --git a/pkg/arvo/app/contact-pull-hook.hoon b/pkg/arvo/app/contact-pull-hook.hoon index 9d66a20c1..4ca07a365 100644 --- a/pkg/arvo/app/contact-pull-hook.hoon +++ b/pkg/arvo/app/contact-pull-hook.hoon @@ -9,6 +9,7 @@ update:store %contact-update %contact-push-hook + %.y :: necessary to enable p2p == -- :: @@ -32,14 +33,11 @@ ++ on-agent on-agent:def ++ on-watch on-watch:def ++ on-leave on-leave:def +++ resource-for-update resource-for-update:con ++ on-pull-nack |= [=resource =tang] ^- (quip card _this) - :_ this - ?~ (get-contact:con entity.resource) ~ - =- [%pass /pl-nack %agent [our.bowl %contact-store] %poke %contact-update -]~ - !> ^- update:store - [%remove entity.resource] + [~ this] :: ++ on-pull-kick |=(=resource `/) -- diff --git a/pkg/arvo/app/contact-push-hook.hoon b/pkg/arvo/app/contact-push-hook.hoon index 716d33e8b..08fdb2881 100644 --- a/pkg/arvo/app/contact-push-hook.hoon +++ b/pkg/arvo/app/contact-push-hook.hoon @@ -1,4 +1,6 @@ -/+ store=contact-store, res=resource, contact, default-agent, dbug, push-hook +/- pull-hook +/+ store=contact-store, res=resource, contact, group, + default-agent, dbug, push-hook ~% %contact-push-hook-top ..part ~ |% +$ card card:agent:gall @@ -12,6 +14,8 @@ == :: +$ agent (push-hook:push-hook config) +:: ++$ share [%share =ship] -- :: %- agent:dbug @@ -22,11 +26,34 @@ +* this . def ~(. (default-agent this %|) bowl) con ~(. contact bowl) + grp ~(. group bowl) +:: +++ on-init + ^- (quip card _this) + :_ this :_ ~ + =- [%pass /us %agent [our.bowl %contact-push-hook] %poke %push-hook-action -] + !> ^- action:push-hook + [%add [our.bowl %'']] :: -++ on-init on-init:def ++ on-save !>(~) ++ on-load on-load:def -++ on-poke on-poke:def +++ on-poke + |= [=mark =vase] + ^- (quip card _this) + ?. =(mark %contact-share) (on-poke:def mark vase) + =/ =share !<(share vase) + ?> =(src.bowl ship.share) + :_ this :_ ~ + :* %pass + /(scot %p src.bowl)/share + %agent + [our.bowl %contact-pull-hook] + %poke + %pull-hook-action + !> ^- action:pull-hook + [%add ship.share [ship.share %'']] + == +:: ++ on-agent on-agent:def ++ on-watch on-watch:def ++ on-leave on-leave:def @@ -48,16 +75,31 @@ %set-public %.n == :: +++ resource-for-update resource-for-update:con +:: ++ initial-watch |= [=path =resource:res] ^- vase - ?> (is-allowed:con src.bowl) + |^ + ?> (is-allowed:con resource src.bowl) !> ^- update:store - =/ contact=(unit contact:store) (get-contact:con our.bowl) - :+ %add - our.bowl - ?^ contact u.contact - *contact:store + [%initial rolo %.n] + :: + ++ rolo + ^- rolodex:store + =/ ugroup (scry-group:grp resource) + %- ~(gas by *rolodex:store) + ?~ ugroup + =/ c=(unit contact:store) (get-contact:con our.bowl) + ?~ c + [our.bowl *contact:store]~ + [our.bowl u.c]~ + %+ murn ~(tap in (members:grp resource)) + |= s=ship + ^- (unit [ship contact:store]) + =/ c=(unit contact:store) (get-contact:con s) + ?~(c ~ `[s u.c]) + -- :: ++ take-update |= =vase diff --git a/pkg/arvo/app/contact-store.hoon b/pkg/arvo/app/contact-store.hoon index c58b73d02..3a125137a 100644 --- a/pkg/arvo/app/contact-store.hoon +++ b/pkg/arvo/app/contact-store.hoon @@ -3,7 +3,7 @@ :: data store that holds individual contact data :: /- store=contact-store, *resource -/+ default-agent, dbug, *migrate +/+ default-agent, dbug, *migrate, contact |% +$ card card:agent:gall +$ state-4 @@ -29,6 +29,7 @@ |_ =bowl:gall +* this . def ~(. (default-agent this %|) bowl) + con ~(. contact bowl) :: ++ on-init =. rolodex (~(put by rolodex) our.bowl *contact:store) @@ -101,8 +102,10 @@ ++ handle-initial |= [rolo=rolodex:store is-public=?] ^- (quip card _state) + =/ our-contact (~(got by rolodex) our.bowl) =. rolodex (~(uni by rolodex) rolo) - :_ state(rolodex rolodex, is-public is-public) + =. rolodex (~(put by rolodex) our.bowl our-contact) + :_ state(rolodex rolodex) (send-diff [%initial rolodex is-public] %.n) :: ++ handle-add @@ -208,9 +211,22 @@ [%x %allowed-ship @ ~] =/ =ship (slav %p i.t.t.path) ``noun+!>((~(has in allowed-ships) ship)) + :: + [%x %is-public ~] + ``noun+!>(is-public) :: [%x %allowed-groups ~] ``noun+!>(allowed-groups) + + :: + [%x %is-allowed @ @ @ @ ~] + =/ is-personal =(i.t.t.t.t.t.path 'true') + =/ =resource + ?: is-personal + [our.bowl %''] + [(slav %p i.t.t.path) i.t.t.t.path] + =/ =ship (slav %p i.t.t.t.t.path) + ``json+!>(`json`b+(is-allowed:con resource ship)) == :: ++ on-leave on-leave:def diff --git a/pkg/arvo/app/graph-pull-hook.hoon b/pkg/arvo/app/graph-pull-hook.hoon index ee7d73796..01ca5e8f1 100644 --- a/pkg/arvo/app/graph-pull-hook.hoon +++ b/pkg/arvo/app/graph-pull-hook.hoon @@ -9,6 +9,7 @@ update:store %graph-update %graph-push-hook + %.n == -- :: @@ -48,4 +49,6 @@ =/ maybe-time (peek-update-log:gra resource) ?~ maybe-time `/ `/(scot %da u.maybe-time) +:: +++ resource-for-update resource-for-update:gra -- diff --git a/pkg/arvo/app/graph-push-hook.hoon b/pkg/arvo/app/graph-push-hook.hoon index 6685a881e..4501aa03f 100644 --- a/pkg/arvo/app/graph-push-hook.hoon +++ b/pkg/arvo/app/graph-push-hook.hoon @@ -93,6 +93,7 @@ %tag-queries %.n %run-updates %.n == +++ resource-for-update resource-for-update:gra :: ++ initial-watch |= [=path =resource:res] diff --git a/pkg/arvo/app/group-pull-hook.hoon b/pkg/arvo/app/group-pull-hook.hoon index 9141c8e82..5bc8208d8 100644 --- a/pkg/arvo/app/group-pull-hook.hoon +++ b/pkg/arvo/app/group-pull-hook.hoon @@ -14,6 +14,7 @@ update:store %group-update %group-push-hook + %.n == :: -- @@ -28,6 +29,7 @@ +* this . def ~(. (default-agent this %|) bowl) dep ~(. (default:pull-hook this config) bowl) + grp ~(. grpl bowl) :: ++ on-init on-init:def ++ on-save !>(~) @@ -45,8 +47,11 @@ :_ this =- [%pass / %agent [our.bowl %group-store] %poke -]~ group-update+!>([%remove-group resource ~]) +:: ++ on-pull-kick |= =resource ^- (unit path) `/ +:: +++ resource-for-update resource-for-update:grp -- diff --git a/pkg/arvo/app/group-push-hook.hoon b/pkg/arvo/app/group-push-hook.hoon index b4d0d69ca..5924db566 100644 --- a/pkg/arvo/app/group-push-hook.hoon +++ b/pkg/arvo/app/group-push-hook.hoon @@ -141,6 +141,7 @@ =(~(tap in ships.update) ~[src.bowl]) == -- +++ resource-for-update resource-for-update:grp :: ++ take-update |= =vase diff --git a/pkg/arvo/app/group-view.hoon b/pkg/arvo/app/group-view.hoon index 2cebb3eb5..884b30236 100644 --- a/pkg/arvo/app/group-view.hoon +++ b/pkg/arvo/app/group-view.hoon @@ -1,5 +1,6 @@ /- view-sur=group-view, group-store, *group, metadata=metadata-store -/+ default-agent, agentio, mdl=metadata, resource, dbug, grpl=group, verb +/+ default-agent, agentio, mdl=metadata, + resource, dbug, grpl=group, con=contact, verb |% ++ card card:agent:gall +$ state-zero @@ -69,9 +70,7 @@ [cards this] :: ++ on-arvo on-arvo:def -:: ++ on-leave on-leave:def -:: ++ on-fail on-fail:def -- |_ =bowl:gall @@ -86,6 +85,7 @@ ++ emit-many |= crds=(list card) jn-core(cards (weld (flop crds) cards)) + :: ++ emit |= =card jn-core(cards [card cards]) @@ -152,43 +152,65 @@ %+ poke-our:(jn-pass-io /pull-groups) %group-pull-hook pull-hook-action+!>([%add ship rid]) (tx-progress %added) - :: + :: %pull-groups ?> ?=(%poke-ack -.sign) (ack +.sign) - :: + :: %groups ?+ -.sign !! %fact (groups-fact +.sign) %watch-ack (ack +.sign) %kick watch-groups == - :: + :: %pull-md ?> ?=(%poke-ack -.sign) (ack +.sign) - :: + :: + %pull-co + ?> ?=(%poke-ack -.sign) + (ack +.sign) + :: + %share-co + ?> ?=(%poke-ack -.sign) + (ack +.sign) + :: + %push-co + ?> ?=(%poke-ack -.sign) + (ack +.sign) + :: %md ?+ -.sign !! %fact (md-fact +.sign) %watch-ack (ack +.sign) %kick watch-md == - :: + :: %pull-graphs ?> ?=(%poke-ack -.sign) %- cleanup ?^(p.sign %strange %done) == + :: ++ groups-fact |= =cage ?. ?=(%group-update p.cage) jn-core =+ !<(=update:group-store q.cage) ?. ?=(%initial-group -.update) jn-core ?. =(rid resource.update) jn-core - %- emit - %+ poke-our:(jn-pass-io /pull-md) %metadata-pull-hook - pull-hook-action+!>([%add [entity .]:rid]) + %- emit-many + =/ cag=^cage pull-hook-action+!>([%add [entity .]:rid]) + %- zing + :~ [(poke-our:(jn-pass-io /pull-md) %metadata-pull-hook cag)]~ + [(poke-our:(jn-pass-io /pull-co) %contact-pull-hook cag)]~ + :: + ?. scry-is-public:con ~ + :_ ~ + %+ poke:(jn-pass-io /share-co) + [entity.rid %contact-push-hook] + [%contact-share !>([%share our.bowl])] + == :: ++ md-fact |= [=mark =vase] diff --git a/pkg/arvo/app/metadata-pull-hook.hoon b/pkg/arvo/app/metadata-pull-hook.hoon index a7f54893d..374a19ed6 100644 --- a/pkg/arvo/app/metadata-pull-hook.hoon +++ b/pkg/arvo/app/metadata-pull-hook.hoon @@ -15,6 +15,7 @@ update:metadata %metadata-update %metadata-push-hook + %.n == +$ state-zero [%0 previews=(map resource group-preview:metadata)] @@ -191,6 +192,7 @@ ++ on-arvo on-arvo:def :: ++ on-fail on-fail:def +++ resource-for-update resource-for-update:met ++ on-pull-nack |= [=resource =tang] ^- (quip card _this) diff --git a/pkg/arvo/app/metadata-push-hook.hoon b/pkg/arvo/app/metadata-push-hook.hoon index 294263df6..aa096a857 100644 --- a/pkg/arvo/app/metadata-push-hook.hoon +++ b/pkg/arvo/app/metadata-push-hook.hoon @@ -92,6 +92,7 @@ ?=(%member-metadata vip.metadatum) == :: +++ resource-for-update resource-for-update:met ++ take-update |= =vase ^- [(list card) agent] diff --git a/pkg/arvo/lib/contact-store.hoon b/pkg/arvo/lib/contact-store.hoon index 18efaa09f..af70ed022 100644 --- a/pkg/arvo/lib/contact-store.hoon +++ b/pkg/arvo/lib/contact-store.hoon @@ -173,4 +173,10 @@ == -- -- +:: +++ share-dejs + =, dejs:format + |% + ++ share (ot [%share (su ;~(pfix sig fed:ag))]~) + -- -- diff --git a/pkg/arvo/lib/contact.hoon b/pkg/arvo/lib/contact.hoon index 449478e12..2f3c6106a 100644 --- a/pkg/arvo/lib/contact.hoon +++ b/pkg/arvo/lib/contact.hoon @@ -1,6 +1,7 @@ /- store=contact-store, *resource -/+ group +/+ group, grpl=group |_ =bowl:gall ++* grp ~(. grpl bowl) ++ scry-for |* [=mold =path] .^ mold @@ -11,24 +12,88 @@ (snoc `^path`path %noun) == :: +++ resource-for-update + |= =vase + ^- (list resource) + |^ + =/ =update:store !<(update:store vase) + ?- -.update + %initial ~ + %add (rids-for-ship ship.update) + %remove (rids-for-ship ship.update) + %edit (rids-for-ship ship.update) + %allow ~ + %disallow ~ + %set-public ~ + == + :: + ++ rids-for-ship + |= s=ship + ^- (list resource) + :: if the ship is in any group that I am pushing updates for, push + :: it out to that resource. + :: + =/ rids + %+ skim ~(tap in scry-sharing) + |= r=resource + (is-member:grp s r) + ?. =(s our.bowl) + rids + (snoc rids [our.bowl %'']) + -- +++ scry-sharing + .^ (set resource) + %gx + (scot %p our.bowl) + %contact-push-hook + (scot %da now.bowl) + /sharing/noun + == +:: ++ get-contact |= =ship ^- (unit contact:store) - =/ upd (scry-for (unit update:store) /contact/(scot %p ship)) - ?~ upd ~ - ?> ?=(%add -.u.upd) - `contact.u.upd + =/ =rolodex:store + (scry-for rolodex:store /all) + (~(get by rolodex) ship) +:: +++ scry-is-public + .^ ? + %gx + (scot %p our.bowl) + %contact-store + (scot %da now.bowl) + /is-public/noun + == :: ++ is-allowed - |= =ship + |= [rid=resource =ship] ^- ? - =/ shp (scry-for ? /allowed-ship/(scot %p ship)) - ?: shp %.y - =/ allowed-groups ~(tap in (scry-for (set resource) /allowed-groups)) =/ grp ~(. group bowl) - |- - ?~ allowed-groups %.n - ?: (~(has in (members:grp i.allowed-groups)) ship) - %.y - $(allowed-groups t.allowed-groups) + =/ allowed-groups (scry-for (set resource) /allowed-groups) + ?| :: if they are requesting our personal profile, check if we are + :: either public, or if they are on the allowed-ships list. + :: this is used for direct messages and leap searches + :: + ?& =(rid [our.bowl %'']) + ?| :: if our profile is public, allow + :: + scry-is-public + :: if the requester is an allowed-ship, allow + :: + (scry-for ? /allowed-ship/(scot %p ship)) + :: if the requester of our profile is the host of one of + :: our allowed-groups, allow + :: + %+ lien ~(tap in allowed-groups) + |= res=resource + =(entity.res ship) + == == + :: if they are requesting our contact data within a group, + :: we make sure that we are sharing that group, + :: and that they are a member of the group + :: + ?& (~(has in scry-sharing) rid) + (~(has in (members:grp rid)) ship) + == == -- diff --git a/pkg/arvo/lib/graph.hoon b/pkg/arvo/lib/graph.hoon index 9285ef663..4f8ebe37b 100644 --- a/pkg/arvo/lib/graph.hoon +++ b/pkg/arvo/lib/graph.hoon @@ -11,6 +11,27 @@ (snoc `^path`path %noun) == :: +++ resource-for-update + |= =vase + ^- (list resource) + =/ =update:store !<(update:store vase) + ?- -.q.update + %add-graph ~[resource.q.update] + %remove-graph ~[resource.q.update] + %add-nodes ~[resource.q.update] + %remove-nodes ~[resource.q.update] + %add-signatures ~[resource.uid.q.update] + %remove-signatures ~[resource.uid.q.update] + %archive-graph ~[resource.q.update] + %unarchive-graph ~ + %add-tag ~ + %remove-tag ~ + %keys ~ + %tags ~ + %tag-queries ~ + %run-updates ~[resource.q.update] + == +:: ++ get-graph |= res=resource ^- update:store diff --git a/pkg/arvo/lib/group.hoon b/pkg/arvo/lib/group.hoon index c2736efca..d2ef6af01 100644 --- a/pkg/arvo/lib/group.hoon +++ b/pkg/arvo/lib/group.hoon @@ -3,6 +3,15 @@ :: |_ =bowl:gall +$ card card:agent:gall +:: +++ resource-for-update + |= =vase + ^- (list resource) + =/ =update:store !<(update:store vase) + ?: ?=(%initial -.update) + ~ + ~[resource.update] +:: ++ scry-for |* [=mold =path] =. path @@ -28,6 +37,15 @@ %+ scry-for ,(unit group) `path`groups+(en-path:resource rid) :: +++ scry-groups + .^ ,(set resource) + %gy + (scot %p our.bowl) + %group-store + (scot %da now.bowl) + /groups/noun + == +:: ++ members |= rid=resource =; =group diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 96c377b66..a7327cc22 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -90,10 +90,8 @@ %chat-cli %herm %contact-store - %contact-hook %contact-push-hook %contact-pull-hook - %contact-view %metadata-store %s3-store %file-server diff --git a/pkg/arvo/lib/metadata.hoon b/pkg/arvo/lib/metadata.hoon index b8eb1285c..8e5aa8f9f 100644 --- a/pkg/arvo/lib/metadata.hoon +++ b/pkg/arvo/lib/metadata.hoon @@ -4,6 +4,13 @@ /+ resource :: |_ =bowl:gall +++ resource-for-update + |= =vase + ^- (list resource) + =/ =update:store !<(update:store vase) + ?. ?=(?(%add %remove %initial-group) -.update) ~ + ~[group.update] +:: ++ app-paths-from-group |= [=app-name:store group=resource] ^- (list resource) diff --git a/pkg/arvo/lib/pull-hook.hoon b/pkg/arvo/lib/pull-hook.hoon index 55c48b233..5b7c8289d 100644 --- a/pkg/arvo/lib/pull-hook.hoon +++ b/pkg/arvo/lib/pull-hook.hoon @@ -30,12 +30,15 @@ :: .store-name: name of the store to send subscription updates to. :: .update-mark: mark that updates will be tagged with :: .push-hook-name: name of the corresponding push-hook +:: .no-validate: If true, don't validate that resource/wire/src match +:: up :: +$ config $: store-name=term update=mold update-mark=term push-hook-name=term + no-validate=_| == :: :: $base-state-0: state for the pull hook @@ -106,6 +109,14 @@ ++ on-pull-kick |~ resource *(unit path) + :: +resource-for-update: get resources from vase + :: + :: This should be identical to the +resource-for-update arm in the + :: corresponding push-hook + :: + ++ resource-for-update + |~ vase + *(list resource) :: :: from agent:gall ++ on-init @@ -470,24 +481,30 @@ /helper/pull-hook wire :: - ++ get-conversion - .^ tube:clay - %cc (scot %p our.bowl) %home (scot %da now.bowl) - /[update-mark.config]/resource - == - :: ++ give-update ^- card [%give %fact ~[/tracking] %pull-hook-update !>(tracking)] :: + ++ check-src + |= resources=(set resource) + ^- ? + %+ roll ~(tap in resources) + |= [rid=resource out=_|] + ?: out %.y + ?~ ship=(~(get by tracking) rid) + %.n + =(src.bowl u.ship) + :: ++ update-store |= [wire-rid=resource =vase] ^- card =/ =wire (make-wire /store) - =+ !<(rid=resource (get-conversion vase)) - ?> =(src.bowl (~(got by tracking) rid)) - ?> =(wire-rid rid) + =+ resources=(~(gas in *(set resource)) (resource-for-update:og vase)) + ?> ?| no-validate.config + ?& (check-src resources) + (~(has in resources) wire-rid) + == == [%pass wire %agent [our.bowl store-name.config] %poke update-mark.config vase] -- -- diff --git a/pkg/arvo/lib/push-hook.hoon b/pkg/arvo/lib/push-hook.hoon index b36fc5284..2cb7bd705 100644 --- a/pkg/arvo/lib/push-hook.hoon +++ b/pkg/arvo/lib/push-hook.hoon @@ -67,6 +67,16 @@ |* =config $_ ^| |_ bowl:gall + :: + :: +resource-for-update: get affected resources from an update + :: + :: Given a vase of the update, the mark of which is + :: update-mark.config, produce the affected resources, if any. + :: + ++ resource-for-update + |~ vase + *(list resource) + :: :: +take-update: handle update from store :: :: Given an update from the store, do other things after proxying @@ -145,12 +155,12 @@ =* state - ^- agent:gall =< - |_ =bowl:gall +* this . og ~(. push-hook bowl) hc ~(. +> bowl) def ~(. (default-agent this %|) bowl) + :: ++ on-init =^ cards push-hook on-init:og @@ -165,11 +175,9 @@ |^ ?- -.old %1 - =. cards - :_(cards (build-mark:hc %sing)) =^ og-cards push-hook (on-load:og inner-state.old) - [(weld (flop cards) og-cards) this(state old)] + [(weld cards og-cards) this(state old)] :: %0 %_ $ @@ -261,6 +269,7 @@ (push-updates:hc q.cage.sign) cards == + :: ++ on-leave |= =path =^ cards push-hook @@ -269,20 +278,16 @@ :: ++ on-arvo |= [=wire =sign-arvo] - ?. ?=([%helper %push-hook @ *] wire) - =^ cards push-hook - (on-arvo:og wire sign-arvo) - [cards this] - ?. ?=(%resource-conversion i.t.t.wire) - (on-arvo:def wire sign-arvo) - :_ this - ~[(build-mark:hc %next)] + =^ cards push-hook + (on-arvo:og wire sign-arvo) + [cards this] :: ++ on-fail |= [=term =tang] =^ cards push-hook (on-fail:og term tang) [cards this] + :: ++ on-peek |= =path ^- (unit (unit cage)) @@ -311,6 +316,7 @@ %remove (remove +.action) %revoke (revoke +.action) == + :: ++ add |= rid=resource =. sharing @@ -322,7 +328,7 @@ =/ pax=path [%resource (en-path:resource rid)] =/ paths=(set path) - %- sy + %- silt %+ turn (incoming-subscriptions pax) |=([ship pox=path] pox) @@ -344,6 +350,7 @@ ~ `[%give %kick ~[path] `her] -- + :: ++ incoming-subscriptions |= prefix=path ^- (list (pair ship path)) @@ -371,58 +378,50 @@ ++ push-updates |= =vase ^- (list card:agent:gall) - =/ rid=(unit resource) - (resource-for-update vase) - ?~ rid ~ + =/ rids=(list resource) (resource-for-update vase) + =| cards=(list card:agent:gall) + |- + ?~ rids cards =/ prefix=path - resource+(en-path:resource u.rid) + resource+(en-path:resource i.rids) =/ paths=(list path) %~ tap in %- silt %+ turn (incoming-subscriptions prefix) |=([ship pax=path] pax) - ?~ paths ~ - [%give %fact paths update-mark.config vase]~ + ?~ paths $(rids t.rids) + %_ $ + rids t.rids + cards (snoc cards [%give %fact paths update-mark.config vase]) + == :: ++ forward-update - |= update=vase + |= =vase ^- (list card:agent:gall) - =/ rid=resource - (need (resource-for-update update)) + =/ rids=(list resource) (resource-for-update vase) + =| cards=(list card:agent:gall) + |- + ?~ rids cards =/ =path - resource+(en-path:resource rid) + resource+(en-path:resource i.rids) =/ =wire - (make-wire resource+(en-path:resource rid)) + (make-wire resource+(en-path:resource i.rids)) =/ dap=term - ?:(=(our.bowl entity.rid) store-name.config dap.bowl) - [%pass wire %agent [entity.rid dap] %poke update-mark.config update]~ - :: - ++ get-conversion - .^ tube:clay - %cc (scot %p our.bowl) %home (scot %da now.bowl) - /[update-mark.config]/resource + ?:(=(our.bowl entity.i.rids) store-name.config dap.bowl) + %_ $ + rids t.rids + :: + cards + %+ snoc cards + [%pass wire %agent [entity.i.rids dap] %poke update-mark.config vase] == :: ++ resource-for-update - |= update=vase - ^- (unit resource) - =/ converted=(each vase (list tank)) - (mule |.((get-conversion update))) - ?: ?=(%| -.converted) - %- (slog p.converted) - ~ - [~ !<(resource p.converted)] - :: - ++ build-mark - |= rav=?(%sing %next) - ^- card - =/ =wire - (make-wire /resource-conversion) - =/ =mood:clay - [%c da+now.bowl /[update-mark.config]/resource] - =/ =rave:clay - ?:(?=(%next rav) [rav mood] [rav mood]) - [%pass wire %arvo %c %warp our.bowl [%home `rave]] + |= =vase + ^- (list resource) + %~ tap in + %- silt + (resource-for-update:og vase) -- -- diff --git a/pkg/arvo/mar/contact/share.hoon b/pkg/arvo/mar/contact/share.hoon new file mode 100644 index 000000000..abca9f637 --- /dev/null +++ b/pkg/arvo/mar/contact/share.hoon @@ -0,0 +1,15 @@ +/+ *contact-store +:: +|_ share=[%share =ship] +++ grad %noun +++ grow + |% + ++ noun share + -- +:: +++ grab + |% + ++ noun _share + ++ json share:share-dejs + -- +-- diff --git a/pkg/arvo/mar/contact/update.hoon b/pkg/arvo/mar/contact/update.hoon index 87d3f18a5..733d30f48 100644 --- a/pkg/arvo/mar/contact/update.hoon +++ b/pkg/arvo/mar/contact/update.hoon @@ -6,22 +6,6 @@ |% ++ noun upd ++ json (update:enjs upd) - ++ resource - |^ - ?- -.upd - %initial [nobody %contacts] - %add [nobody %contacts] - %remove [nobody %contacts] - %edit [nobody %contacts] - %allow !! - %disallow !! - %set-public !! - == - :: - ++ nobody - ^- @p - (bex 128) - -- -- :: ++ grab diff --git a/pkg/arvo/mar/graph/update.hoon b/pkg/arvo/mar/graph/update.hoon index 405ae76c8..e6766edb5 100644 --- a/pkg/arvo/mar/graph/update.hoon +++ b/pkg/arvo/mar/graph/update.hoon @@ -7,13 +7,6 @@ |% ++ noun upd ++ json (update:enjs upd) - ++ resource - ?+ -.q.upd !! - ?(%run-updates %add-nodes %remove-nodes %add-graph) resource.q.upd - ?(%remove-graph %archive-graph %unarchive-graph) resource.q.upd - ?(%add-tag %remove-tag) resource.q.upd - ?(%add-signatures %remove-signatures) resource.uid.q.upd - == ++ mime [/application/x-urb-graph-update (as-octs (jam upd))] -- :: diff --git a/pkg/arvo/mar/group/update.hoon b/pkg/arvo/mar/group/update.hoon index 62fdc5af2..d4ea2abd9 100644 --- a/pkg/arvo/mar/group/update.hoon +++ b/pkg/arvo/mar/group/update.hoon @@ -4,10 +4,6 @@ ++ grow |% ++ noun upd - ++ resource - ?< ?=(%initial -.upd) - resource.upd - :: ++ json %+ frond:enjs:format 'groupUpdate' (update:enjs upd) diff --git a/pkg/arvo/mar/metadata/update.hoon b/pkg/arvo/mar/metadata/update.hoon index 1982521bf..9f894cf84 100644 --- a/pkg/arvo/mar/metadata/update.hoon +++ b/pkg/arvo/mar/metadata/update.hoon @@ -4,9 +4,6 @@ ++ grow |% ++ noun update - ++ resource - ?> ?=(?(%add %remove %initial-group) -.update) - group.update ++ json (update:enjs:store update) -- :: diff --git a/pkg/arvo/ted/group/create.hoon b/pkg/arvo/ted/group/create.hoon index 4185eeb38..1b7da9b83 100644 --- a/pkg/arvo/ted/group/create.hoon +++ b/pkg/arvo/ted/group/create.hoon @@ -45,6 +45,7 @@ [%add rid groups+rid metadatum] ;< ~ bind:m (poke-our %metadata-store %metadata-action !>(met-action)) ;< ~ bind:m (poke-our %metadata-push-hook push-hook-act) +;< ~ bind:m (poke-our %contact-push-hook push-hook-act) (pure:m !>(~)) diff --git a/pkg/arvo/ted/group/delete.hoon b/pkg/arvo/ted/group/delete.hoon index 3c9d1e924..08525780d 100644 --- a/pkg/arvo/ted/group/delete.hoon +++ b/pkg/arvo/ted/group/delete.hoon @@ -26,5 +26,6 @@ ;< ~ bind:m (cleanup-md:view rid) ;< ~ bind:m (poke-our %group-store %group-update !>([%remove-group rid ~])) ;< ~ bind:m (poke-our %metadata-push-hook push-hook-act) +;< ~ bind:m (poke-our %contact-push-hook push-hook-act) ;< ~ bind:m (poke-our %group-push-hook push-hook-act) (pure:m !>(~)) diff --git a/pkg/arvo/ted/group/leave.hoon b/pkg/arvo/ted/group/leave.hoon index ec4da0555..65ea051cb 100644 --- a/pkg/arvo/ted/group/leave.hoon +++ b/pkg/arvo/ted/group/leave.hoon @@ -22,6 +22,7 @@ :- %pull-hook-action !> ^- action:pull-hook [%remove rid] +;< ~ bind:m (poke-our %contact-pull-hook pull-hook-act) ;< ~ bind:m (poke-our %metadata-pull-hook pull-hook-act) ;< ~ bind:m (poke-our %group-pull-hook pull-hook-act) ;< ~ bind:m (poke-our %group-store %group-update !>([%remove-group rid ~])) diff --git a/pkg/interface/src/logic/api/base.ts b/pkg/interface/src/logic/api/base.ts index 323c13ce7..085c4cc32 100644 --- a/pkg/interface/src/logic/api/base.ts +++ b/pkg/interface/src/logic/api/base.ts @@ -57,6 +57,7 @@ export default class BaseApi { } scry(app: string, path: Path): Promise { + console.log(path); return fetch(`/~/scry/${app}${path}.json`).then(r => r.json() as Promise); } diff --git a/pkg/interface/src/logic/api/contacts.ts b/pkg/interface/src/logic/api/contacts.ts index fab1ed90a..628532700 100644 --- a/pkg/interface/src/logic/api/contacts.ts +++ b/pkg/interface/src/logic/api/contacts.ts @@ -34,12 +34,35 @@ export default class ContactsApi extends BaseApi { }); } + allow(ship) { + return this.storeAction({ + allow: ship + }); + } + setPublic(setPublic: any) { return this.storeAction({ 'set-public': setPublic }); } + share(recipient, us) { + return this.action( + 'contact-push-hook', + 'contact-share', + { share: us }, + recipient + ); + } + + fetchIsAllowed(entity, name, ship, personal) { + const isPersonal = personal ? 'true' : 'false'; + return this.scry( + 'contact-store', + `/is-allowed/${entity}/${name}/${ship}/${isPersonal}` + ); + } + private storeAction(action: any): Promise { return this.action('contact-store', 'contact-update', action) } diff --git a/pkg/interface/src/views/apps/chat/ChatResource.tsx b/pkg/interface/src/views/apps/chat/ChatResource.tsx index 73b9df995..e4d094da6 100644 --- a/pkg/interface/src/views/apps/chat/ChatResource.tsx +++ b/pkg/interface/src/views/apps/chat/ChatResource.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useCallback, useEffect } from 'react'; +import React, { useRef, useCallback, useEffect, useState } from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { Col } from '@tlon/indigo-react'; import _ from 'lodash'; @@ -36,6 +36,7 @@ export function ChatResource(props: ChatResourceProps) { const [,, owner, name] = station.split('/'); const ourContact = contacts?.[`~${window.ship}`]; + console.log(contacts); const chatInput = useRef(); @@ -89,7 +90,15 @@ export function ChatResource(props: ChatResourceProps) { return ( - + { + setProfileAllowed(true); + }} /> {dragging && } { - const image = (props?.our?.avatar) - ? - : - - ; +const pathAsResource = (path) => { + if (!path) { + return false; + } + const pathArr = path.split('/'); + if (pathArr.length !== 4) { + return false; + } - return ( + return { + entity: pathArr[2], + name: pathArr[3] + }; +}; + +export const ShareProfile = (props) => { + const { api, recipient, hideBanner, group, groupPath } = props; + console.log(groupPath); + // TODO: use isContactPublic somewhere + + const [showBanner, setShowBanner] = useState(false); + const res = pathAsResource(groupPath); + + useEffect(() => { + if (!res) { return; } + if (!group) { return; } + console.log(group); + if (group.hidden) { + // TODO: + // take the union of the pending set and the members set, + // subtract ourselves, then if *anyone* has not already been shared with, + // show the banner + // Promise.all all the members of the set + let check = + Promise.all() + props.api.contacts.fetchIsAllowed( + `~${window.ship}`, + 'personal', // not used + recipient, + true + ).then((retVal) => { + console.log(retVal); + setShowBanner(!retVal); + }); + } else { + // TODO: + // if the group is not in the allowed-groups set, then show the banner + props.api.contacts.fetchIsAllowed( + res.entity, + res.name, + recipient, + false + ).then((retVal) => { + console.log(retVal); + setShowBanner(!retVal); + }); + } + }, [recipient, res, group]); + + const image = (props?.our?.avatar) + ? ( + + ) : ( + + + + ); + + const onClick = () => { + api.contacts.allow(recipient).then(() => { + api.contacts.share(recipient, window.ship); + }); + hideBanner(); + }; + + return showBanner ? ( { {image} Share private profile? - + Share - ); + ) : null; }; diff --git a/pkg/interface/src/views/apps/profile/components/ContactCard.tsx b/pkg/interface/src/views/apps/profile/components/ContactCard.tsx deleted file mode 100644 index b7fe89e29..000000000 --- a/pkg/interface/src/views/apps/profile/components/ContactCard.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import React from "react"; -import { Sigil } from "~/logic/lib/sigil"; -import * as Yup from "yup"; - -import { uxToHex } from "~/logic/lib/util"; -import { - ManagedForm as Form, - Col, - ManagedTextInputField as Input, - Box, - Text, - Row, - BaseImage -} from "@tlon/indigo-react"; -import { Formik, FormikHelpers } from "formik"; -import { Contact } from "~/types/contact-update"; -import { AsyncButton } from "~/views/components/AsyncButton"; -import { ColorInput } from "~/views/components/ColorInput"; -import GlobalApi from "~/logic/api/global"; -import { ImageInput } from "~/views/components/ImageInput"; -import { S3State } from "~/types"; -import useLocalState from "~/logic/state/local"; - -interface ContactCardProps { - contact: Contact; - path: string; - api: GlobalApi; - s3: S3State; - rootIdentity: Contact; -} - -const formSchema = Yup.object({ - color: Yup.string(), - nickname: Yup.string(), - email: Yup.string().matches( - new RegExp( - String( - /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*/.source - ) + - /@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/ - .source - ), - "Not a valid email" - ), - phone: Yup.string().matches( - new RegExp( - String(/^\s*(?:\+?(\d{1,3}))?/.source) + - /([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)\s*$/ - .source - ), - "Not a valid phone" - ), - - website: Yup.string().matches( - new RegExp( - String(/[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}/.source) + - /\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.source - ), - "Not a valid website" - ), -}); - -const emptyContact = { - avatar: null, - color: '0', - nickname: '', - email: '', - phone: '', - website: '', - notes: '' -}; - -export function ContactCard(props: ContactCardProps) { - const { hideAvatars, hideNicknames } = useLocalState(({ hideAvatars, hideNicknames }) => ({ - hideAvatars, hideNicknames - })); - const us = `~${window.ship}`; - const { contact, rootIdentity } = props; - const onSubmit = async (values: any, actions: FormikHelpers) => { - try { - if(!contact) { - const [,,ship] = props.path.split('/'); - values.color = uxToHex(values.color); - const sharedValues = Object.assign({}, values); - sharedValues.avatar = !values.avatar ? null : { url: values.avatar }; - console.log(values); - await props.api.contacts.share(ship, props.path, us, sharedValues); - actions.setStatus({ success: null }); - return; - } - - await Object.keys(values).reduce((acc, key) => { - const newValue = key !== "color" ? values[key] : uxToHex(values[key]); - if (newValue !== contact[key]) { - if (key === "avatar") { - return acc.then(() => - props.api.contacts.edit(props.path, us, { - avatar: { url: newValue }, - } as any) - ); - } - - return acc.then(() => - props.api.contacts.edit(props.path, us, { - [key]: newValue, - } as any) - ); - } - return acc; - }, Promise.resolve()); - actions.setStatus({ success: null }); - } catch (e) { - console.error(e); - actions.setStatus({ error: e.message }); - } - }; - - const hexColor = contact?.color ? `#${uxToHex(contact.color)}` : "#000000"; - const image = (!hideAvatars && contact?.avatar) - ? - : ; - - const nickname = (!hideNicknames && contact?.nickname) ? contact.nickname : ""; - - return ( - - -
- - - {image} - - - {nickname} - - - - - - - - - - - {(contact) ? "Save" : "Share Contact"} - - -
-
- ); -} diff --git a/pkg/interface/src/views/apps/profile/components/SetStatus.tsx b/pkg/interface/src/views/apps/profile/components/SetStatus.tsx index 4674f315c..0d2240077 100644 --- a/pkg/interface/src/views/apps/profile/components/SetStatus.tsx +++ b/pkg/interface/src/views/apps/profile/components/SetStatus.tsx @@ -59,3 +59,4 @@ export function SetStatus(props: any) { ); } +