group admin, leave-group action
This commit is contained in:
parent
cf52d8ddf4
commit
4e9c22c9fc
|
@ -12,13 +12,17 @@
|
|||
get-keypair
|
||||
get-peer-identities
|
||||
get-identities
|
||||
save-identities]]
|
||||
save-identities
|
||||
save-group-admin
|
||||
group-admin?
|
||||
remove-group-data]]
|
||||
[syng-im.protocol.delivery :refer [start-delivery-loop]]
|
||||
[syng-im.protocol.web3 :refer [listen
|
||||
make-msg
|
||||
post-msg
|
||||
make-web3
|
||||
new-identity]]
|
||||
new-identity
|
||||
stop-listener]]
|
||||
[syng-im.protocol.handler :refer [handle-incoming-whisper-msg]]
|
||||
[syng-im.protocol.user-handler :refer [invoke-user-handler]]
|
||||
[syng-im.utils.encryption :refer [new-keypair]]
|
||||
|
@ -27,7 +31,8 @@
|
|||
group-add-participant-msg
|
||||
group-remove-participant-msg
|
||||
removed-from-group-msg]]
|
||||
[syng-im.protocol.defaults :refer [default-content-type]])
|
||||
[syng-im.protocol.defaults :refer [default-content-type]]
|
||||
[syng-im.utils.logging :as log])
|
||||
(:require-macros [cljs.core.async.macros :refer [go]]))
|
||||
|
||||
(defn create-connection [ethereum-rpc-url]
|
||||
|
@ -49,7 +54,7 @@
|
|||
:event-type can be:
|
||||
|
||||
:new-msg - [from payload]
|
||||
:new-group-msg [from payload]
|
||||
:new-group-msg [from group-id payload]
|
||||
:error - [error-msg details]
|
||||
:msg-acked [msg-id from]
|
||||
:delivery-failed [msg-id]
|
||||
|
@ -58,6 +63,7 @@
|
|||
:group-new-participant [identity group-id]
|
||||
:group-removed-participant [from identity group-id]
|
||||
:removed-from-group [from group-id]
|
||||
:participant-left-group [from group-id]
|
||||
:initialized [identity]
|
||||
|
||||
:new-msg, new-group-msg, msg-acked should be handled idempotently (may be called multiple times for the same msg-id)
|
||||
|
@ -93,7 +99,8 @@
|
|||
:payload {:content content
|
||||
:content-type default-content-type}}))
|
||||
|
||||
(defn start-group-chat [identities]
|
||||
(defn start-group-chat
|
||||
[identities]
|
||||
(let [group-topic (random/id)
|
||||
keypair (new-keypair)
|
||||
store (storage)
|
||||
|
@ -103,6 +110,7 @@
|
|||
(conj my-identity))]
|
||||
(save-keypair store group-topic keypair)
|
||||
(save-identities store group-topic identities)
|
||||
(save-group-admin store group-topic my-identity)
|
||||
(listen connection handle-incoming-whisper-msg {:topics [group-topic]})
|
||||
(doseq [ident identities :when (not (= ident my-identity))]
|
||||
(let [{:keys [msg-id msg]} (init-group-chat-msg ident group-topic identities keypair)]
|
||||
|
@ -110,37 +118,56 @@
|
|||
(post-msg connection msg)))
|
||||
group-topic))
|
||||
|
||||
(defn group-add-participant [group-id new-peer-identity]
|
||||
(let [store (storage)
|
||||
connection (connection)
|
||||
identities (-> (get-identities store group-id)
|
||||
(conj new-peer-identity))
|
||||
keypair (get-keypair store group-id)]
|
||||
(save-identities store group-id identities)
|
||||
(let [{:keys [msg-id msg]} (group-add-participant-msg new-peer-identity group-id identities keypair)]
|
||||
(add-pending-message msg-id msg {:internal? true})
|
||||
(post-msg connection msg))
|
||||
(send-group-msg {:group-id group-id
|
||||
:type :group-new-participant
|
||||
:payload {:identity new-peer-identity}
|
||||
:internal? true})))
|
||||
|
||||
(defn group-remove-participant [group-id identity-to-remove]
|
||||
(defn group-add-participant
|
||||
"Only call if you are the group-admin"
|
||||
[group-id new-peer-identity]
|
||||
(let [store (storage)
|
||||
connection (connection)
|
||||
identities (-> (get-identities store group-id)
|
||||
(disj identity-to-remove))
|
||||
keypair (new-keypair)
|
||||
my-identity (my-identity)]
|
||||
(save-identities store group-id identities)
|
||||
(save-keypair store group-id keypair)
|
||||
(doseq [ident identities :when (not (= ident my-identity))]
|
||||
(let [{:keys [msg-id msg]} (group-remove-participant-msg ident group-id keypair identity-to-remove)]
|
||||
(add-pending-message msg-id msg {:internal? true})
|
||||
(post-msg connection msg)))
|
||||
(let [{:keys [msg-id msg]} (removed-from-group-msg group-id identity-to-remove)]
|
||||
(add-pending-message msg-id msg {:internal? true})
|
||||
(post-msg connection msg))))
|
||||
(if-not (group-admin? store group-id my-identity)
|
||||
(log/error "Called group-add-participant but not group admin, group-id:" group-id "my-identity:" my-identity)
|
||||
(let [connection (connection)
|
||||
identities (-> (get-identities store group-id)
|
||||
(conj new-peer-identity))
|
||||
keypair (get-keypair store group-id)]
|
||||
(save-identities store group-id identities)
|
||||
(let [{:keys [msg-id msg]} (group-add-participant-msg new-peer-identity group-id identities keypair)]
|
||||
(add-pending-message msg-id msg {:internal? true})
|
||||
(post-msg connection msg))
|
||||
(send-group-msg {:group-id group-id
|
||||
:type :group-new-participant
|
||||
:payload {:identity new-peer-identity}
|
||||
:internal? true})))))
|
||||
|
||||
(defn group-remove-participant
|
||||
"Only call if you are the group-admin"
|
||||
[group-id identity-to-remove]
|
||||
(let [store (storage)
|
||||
my-identity (my-identity)]
|
||||
(if-not (group-admin? store group-id my-identity)
|
||||
(log/error "Called group-remove-participant but not group admin, group-id:" group-id "my-identity:" my-identity)
|
||||
(let [connection (connection)
|
||||
identities (-> (get-identities store group-id)
|
||||
(disj identity-to-remove))
|
||||
keypair (new-keypair)]
|
||||
(save-identities store group-id identities)
|
||||
(save-keypair store group-id keypair)
|
||||
(doseq [ident identities :when (not (= ident my-identity))]
|
||||
(let [{:keys [msg-id msg]} (group-remove-participant-msg ident group-id keypair identity-to-remove)]
|
||||
(add-pending-message msg-id msg {:internal? true})
|
||||
(post-msg connection msg)))
|
||||
(let [{:keys [msg-id msg]} (removed-from-group-msg group-id identity-to-remove)]
|
||||
(add-pending-message msg-id msg {:internal? true})
|
||||
(post-msg connection msg))))))
|
||||
|
||||
(defn leave-group-chat [group-id]
|
||||
(let [store (storage)
|
||||
my-identity (my-identity)]
|
||||
(send-group-msg {:group-id group-id
|
||||
:type :left-group
|
||||
:payload {:identity my-identity}
|
||||
:internal? true})
|
||||
(remove-group-data store group-id)
|
||||
(stop-listener group-id)))
|
||||
|
||||
(defn current-connection []
|
||||
(connection))
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
:encrypt? true
|
||||
:public-key public-key
|
||||
:payload payload
|
||||
:clear-info {:group-id group-id
|
||||
:type type}}))
|
||||
:clear-info {:group-topic group-id
|
||||
:type type}}))
|
||||
|
||||
(defn send-group-msg [{:keys [group-id payload type internal?] :or {internal? false}}]
|
||||
(let [store (storage)
|
||||
|
|
|
@ -11,7 +11,11 @@
|
|||
chat-exists?
|
||||
get-keypair
|
||||
add-identity
|
||||
remove-group-data]]
|
||||
remove-group-data
|
||||
save-group-admin
|
||||
group-admin?
|
||||
remove-identity
|
||||
group-member?]]
|
||||
[syng-im.protocol.web3 :refer [to-ascii
|
||||
make-msg
|
||||
post-msg
|
||||
|
@ -57,65 +61,82 @@
|
|||
(listen web3 handle-incoming-whisper-msg {:topics [group-topic]})
|
||||
(save-keypair store group-topic keypair)
|
||||
(save-identities store group-topic identities)
|
||||
(save-group-admin store group-topic from)
|
||||
(invoke-user-handler :new-group-chat {:from from
|
||||
:identities identities
|
||||
:group-id group-topic}))))
|
||||
|
||||
(defn decrypt-group-msg [group-id encrypted-payload]
|
||||
(defn decrypt-group-msg [group-topic encrypted-payload]
|
||||
(let [store (storage)
|
||||
{private-key :private} (get-keypair store group-id)]
|
||||
{private-key :private} (get-keypair store group-topic)]
|
||||
(-> (decrypt private-key encrypted-payload)
|
||||
(read-string)
|
||||
(assoc :group-id group-id))))
|
||||
(assoc :group-topic group-topic))))
|
||||
|
||||
(defn handle-group-user-msg [web3 from {:keys [enc-payload group-id]}]
|
||||
(let [{:keys [msg-id] :as payload} (decrypt-group-msg group-id enc-payload)]
|
||||
(send-ack web3 from msg-id)
|
||||
(invoke-user-handler :new-group-msg {:from from
|
||||
:payload payload})))
|
||||
(defn handle-group-user-msg [web3 from {:keys [msg-id group-topic] :as payload}]
|
||||
(send-ack web3 from msg-id)
|
||||
(invoke-user-handler :new-group-msg {:from from
|
||||
:group-id group-topic
|
||||
:payload payload}))
|
||||
|
||||
(defn handle-group-new-participant [web3 from {:keys [enc-payload group-id]}]
|
||||
(let [store (storage)
|
||||
{:keys [msg-id identity]} (decrypt-group-msg group-id enc-payload)]
|
||||
(send-ack web3 from msg-id)
|
||||
(add-identity store group-id identity)
|
||||
(invoke-user-handler :group-new-participant {:identity identity
|
||||
:group-id group-id
|
||||
:from from})))
|
||||
(defn handle-group-new-participant [web3 from {:keys [msg-id identity group-topic]}]
|
||||
(let [store (storage)]
|
||||
(if (group-admin? store group-topic from)
|
||||
(do
|
||||
(send-ack web3 from msg-id)
|
||||
(when-not (group-member? store group-topic identity)
|
||||
(add-identity store group-topic identity)
|
||||
(invoke-user-handler :group-new-participant {:identity identity
|
||||
:group-id group-topic
|
||||
:from from})))
|
||||
(log/warn "Ignoring group-new-participant for group" group-topic "from a non group-admin user" from))))
|
||||
|
||||
(defn handle-group-removed-participant [web3 from {:keys [keypair group-topic msg-id removed-identity]}]
|
||||
(let [store (storage)
|
||||
identities (get-identities store group-topic)]
|
||||
(if (get identities from)
|
||||
(let [store (storage)]
|
||||
(if (group-admin? store group-topic from)
|
||||
(do
|
||||
(send-ack web3 from msg-id)
|
||||
(save-keypair store group-topic keypair)
|
||||
(->> (disj identities removed-identity)
|
||||
(save-identities store group-topic))
|
||||
(invoke-user-handler :group-removed-participant {:identity removed-identity
|
||||
:group-id group-topic
|
||||
:from from}))
|
||||
(log/warn "Got group-removed-participant message from" from "who is not part the group" group-topic))))
|
||||
(when (group-member? store group-topic removed-identity)
|
||||
(save-keypair store group-topic keypair)
|
||||
(remove-identity store group-topic removed-identity)
|
||||
(invoke-user-handler :group-removed-participant {:identity removed-identity
|
||||
:group-id group-topic
|
||||
:from from})))
|
||||
(log/warn "Ignoring group-removed-participant for group" group-topic "from a non group-admin user" from))))
|
||||
|
||||
(defn handle-removed-from-group [web3 from {:keys [group-topic msg-id]}]
|
||||
(let [store (storage)
|
||||
identities (get-identities store group-topic)]
|
||||
(if (get identities from)
|
||||
(let [store (storage)]
|
||||
(if (group-admin? store group-topic from)
|
||||
(do
|
||||
(send-ack web3 from msg-id)
|
||||
(remove-group-data store group-topic)
|
||||
(stop-listener group-topic)
|
||||
(invoke-user-handler :removed-from-group {:group-id group-topic
|
||||
:from from}))
|
||||
(log/warn "Got removed-from-group message from" from "who is not part the group" group-topic))))
|
||||
(when (group-member? store group-topic (state/my-identity))
|
||||
(remove-group-data store group-topic)
|
||||
(stop-listener group-topic)
|
||||
(invoke-user-handler :removed-from-group {:group-id group-topic
|
||||
:from from})))
|
||||
(log/warn "Ignoring removed-from-group for group" group-topic "from a non group-admin user" from))))
|
||||
|
||||
(defn handle-participant-left-group [web3 from {:keys [group-topic msg-id]}]
|
||||
(let [store (storage)]
|
||||
(send-ack web3 from msg-id)
|
||||
(when (group-member? store group-topic from)
|
||||
(remove-identity store group-topic from)
|
||||
(invoke-user-handler :participant-left-group {:group-id group-topic
|
||||
:from from}))))
|
||||
|
||||
(defn handle-group-msg [web3 msg-type from {:keys [enc-payload group-topic]}]
|
||||
(let [payload (decrypt-group-msg group-topic enc-payload)]
|
||||
(case msg-type
|
||||
:group-user-msg (handle-group-user-msg web3 from payload)
|
||||
:group-new-participant (handle-group-new-participant web3 from payload)
|
||||
:left-group (handle-participant-left-group web3 from payload))))
|
||||
|
||||
(defn handle-incoming-whisper-msg [web3 msg]
|
||||
(log/info "Got whisper message:" msg)
|
||||
(let [{from :from
|
||||
to :to
|
||||
topics :topics ;; always empty (bug in go-ethereum?)
|
||||
payload :payload
|
||||
:as msg} (js->clj msg :keywordize-keys true)]
|
||||
payload :payload} (js->clj msg :keywordize-keys true)]
|
||||
(if (or (= to "0x0")
|
||||
(= to (state/my-identity)))
|
||||
(let [{msg-type :type :as payload} (->> (to-ascii payload)
|
||||
|
@ -124,8 +145,9 @@
|
|||
:ack (handle-ack from payload)
|
||||
:user-msg (handle-user-msg web3 from payload)
|
||||
:init-group-chat (handle-new-group-chat web3 from payload)
|
||||
:group-user-msg (handle-group-user-msg web3 from payload)
|
||||
:group-new-participant (handle-group-new-participant web3 from payload)
|
||||
:group-removed-participant (handle-group-removed-participant web3 from payload)
|
||||
:removed-from-group (handle-removed-from-group web3 from payload)))
|
||||
:removed-from-group (handle-removed-from-group web3 from payload)
|
||||
:group-user-msg (handle-group-msg web3 msg-type from payload)
|
||||
:group-new-participant (handle-group-msg web3 msg-type from payload)
|
||||
:left-group (handle-group-msg web3 msg-type from payload)))
|
||||
(log/warn "My identity:" (state/my-identity) "Message To:" to "Message is encrypted for someone else, ignoring"))))
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
(defn topic-identities-key [topic]
|
||||
(str "group-chat.topic-identities." topic))
|
||||
|
||||
(defn topic-admin-ident-key [topic]
|
||||
(str "group-chat.topic-admin-ident." topic))
|
||||
|
||||
(defn save-keypair [storage topic keypair]
|
||||
(let [key (topic-keypair-key topic)]
|
||||
(s/put storage key keypair)))
|
||||
|
@ -26,6 +29,16 @@
|
|||
(->> (conj identities identity)
|
||||
(save-identities storage topic)))))
|
||||
|
||||
(defn remove-identity [storage topic identity]
|
||||
(let [identities (get-identities storage topic)]
|
||||
(when (contains? identities identity)
|
||||
(->> (disj identities identity)
|
||||
(save-identities storage topic)))))
|
||||
|
||||
(defn group-member? [storage topic identity]
|
||||
(let [identities (get-identities storage topic)]
|
||||
(contains? identities identity)))
|
||||
|
||||
(defn get-peer-identities [storage topic]
|
||||
(-> (get-identities storage topic)
|
||||
(disj (state/my-identity))))
|
||||
|
@ -42,4 +55,12 @@
|
|||
(let [keypair-key (topic-keypair-key topic)
|
||||
identities-key (topic-identities-key topic)]
|
||||
(s/delete storage keypair-key)
|
||||
(s/delete storage identities-key)))
|
||||
(s/delete storage identities-key)))
|
||||
|
||||
(defn save-group-admin [storage topic identity]
|
||||
(let [key (topic-admin-ident-key topic)]
|
||||
(s/put storage key identity)))
|
||||
|
||||
(defn group-admin? [storage topic identity]
|
||||
(let [key (topic-admin-ident-key topic)]
|
||||
(= identity (s/get storage key))))
|
|
@ -74,6 +74,9 @@
|
|||
<button id="add-peer-button">Add Participant</button>
|
||||
<button id="remove-peer-button">Remove Participant</button>
|
||||
</div>
|
||||
<div>
|
||||
<button id="leave-group-button">Leave Group</button>
|
||||
</div>
|
||||
</div>
|
||||
<script src="js/compiled/syng_im.js" type="text/javascript"></script>
|
||||
</body>
|
||||
|
|
|
@ -107,6 +107,8 @@
|
|||
(remove-identity-from-group-list identity))
|
||||
:removed-from-group (let [{:keys [group-id from]} event]
|
||||
(add-to-chat "group-chat" ":" (str (shorten from) " removed you from group chat")))
|
||||
:participant-left-group (let [{:keys [group-id from]} event]
|
||||
(add-to-chat "group-chat" ":" (str (shorten from) " left group chat")))
|
||||
(add-to-chat "chat" ":" (str "Don't know how to handle " event-type))))})
|
||||
(e/listen (-> (g/getElement "msg")
|
||||
(goog.events.KeyHandler.))
|
||||
|
@ -153,6 +155,10 @@
|
|||
(remove-identity-from-group-list removed-identity)
|
||||
(p/group-remove-participant group-id removed-identity)))
|
||||
|
||||
(defn leave-group []
|
||||
(let [group-id (:group-id @state)]
|
||||
(p/leave-group-chat group-id)))
|
||||
|
||||
(let [button (g/getElement "connect-button")]
|
||||
(e/listen button EventType/CLICK
|
||||
(fn [e]
|
||||
|
@ -176,6 +182,11 @@
|
|||
(fn [e]
|
||||
(remove-peer-from-group))))
|
||||
|
||||
(let [button (g/getElement "leave-group-button")]
|
||||
(e/listen button EventType/CLICK
|
||||
(fn [e]
|
||||
(leave-group))))
|
||||
|
||||
(comment
|
||||
|
||||
(p/init-protocol {:ethereum-rpc-url "http://localhost:4546"
|
||||
|
|
Loading…
Reference in New Issue