Merge branch 'deny-dupped-relations' into 'master'

Deny dupped relations

See merge request ZeusWPI/cat!4
This commit is contained in:
flynn 2019-06-09 23:32:18 +02:00
commit 46b5b4df1a
6 changed files with 101 additions and 75 deletions

View file

@ -105,7 +105,7 @@
<div class="card"> <div class="card">
<header class="card-header"> <header class="card-header">
<p class="card-header-title"> <p class="card-header-title">
Your cuddles Your hugs
</p> </p>
</header> </header>
@ -114,15 +114,13 @@
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th>Person 1</th> <th>With</th>
<th>Person 2</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for relation in user-relations %} {% for relation in user-relations %}
<tr> <tr>
<td>{{relation.name}}</td> <td>{{relation.other_name}}</td>
<td>{{relation.name_2}}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -147,14 +145,14 @@
<div class="select"> <div class="select">
<select name="to_id" id="to_id"> <select name="to_id" id="to_id">
<option hidden disabled selected value> -- select an option -- </option> <option hidden disabled selected value> -- select an option -- </option>
{% for user in non_requested_users %} {% for user in non_connected_users %}
<option value="{{user.id}}">{{user.name}}</option> <option value="{{user.id}}">{{user.name}}</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
</div> </div>
<div class="control"> <div class="control">
<input class="button is-link" type="submit" value="Request cuddle!"> <input class="button is-link" type="submit" value="Request hug!">
</div> </div>
</div> </div>
</form> </form>
@ -283,9 +281,9 @@
</table> </table>
</div> </div>
<div class="column"> <div class="column">
<h3 class="title is-3">Cozy cuddles</h3> <h3 class="title is-3">Cozy hugs</h3>
<div> <div>
<h3 class="subtitle is-4">Add cuddle</h3> <h3 class="subtitle is-4">Add hug</h3>
<form action="/relations" method="post"> <form action="/relations" method="post">
{% csrf-field %} {% csrf-field %}
<div class="field"> <div class="field">
@ -319,15 +317,15 @@
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th>Person 1</th> <th>From</th>
<th>Person 2</th> <th>To</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for relation in relations %} {% for relation in relations %}
<tr> <tr>
<td>{{relation.name}}</td> <td>{{relation.from_name}}</td>
<td>{{relation.name_2}}</td> <td>{{relation.to_name}}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View file

@ -28,6 +28,6 @@ body {
} }
#view { #view {
height: 600px; height: 550px;
max-height: 100%; max-height: 100%;
} }

View file

@ -34,7 +34,7 @@ VALUES (:from_id, :to_id)
-- :name get-relations :? :* -- :name get-relations :? :*
-- :doc retrieves all relations -- :doc retrieves all relations
SELECT * FROM relations SELECT u_from.name from_name, u_to.name to_name, from_id, to_id FROM relations
JOIN users u_from on relations.from_id = u_from.id JOIN users u_from on relations.from_id = u_from.id
JOIN users u_to on relations.to_id = u_to.id JOIN users u_to on relations.to_id = u_to.id
@ -68,6 +68,22 @@ WHERE from_id = :from_id
-- :name get-relation-requests-to-user :? :* -- :name get-relation-requests-to-user :? :*
-- :doc retrieves all relations requests send to a user -- :doc retrieves all relations requests send to a user
SELECT rr.id as rr_id, rr.status, u_from.name as from_name FROM relation_requests as rr SELECT rr.id as rr_id, rr.status, u_from.name as from_name, u_from.id as from_id FROM relation_requests as rr
JOIN users u_from on rr.from_id = u_from.id JOIN users u_from on rr.from_id = u_from.id
WHERE to_id = :to_id WHERE to_id = :to_id
/*
COMPLEX QUERIES
*/
-- :name get-connection-existence :? :1
-- :doc retrieves all relations-requests or relations between 2 users
SELECT count(*) count
FROM(
SELECT rr.from_id FROM relation_requests rr WHERE rr.from_id = :user_id and rr.to_id = :other_id
UNION ALL
SELECT rr.to_id FROM relation_requests rr WHERE rr.from_id = :other_id and rr.to_id = :user_id
UNION ALL
SELECT rel.from_id FROM relations rel WHERE rel.from_id = :user_id and rel.to_id = :other_id
UNION ALL
SELECT rel.to_id FROM relations rel WHERE rel.from_id = :other_id and rel.to_id = :user_id) x

View file

@ -20,7 +20,7 @@
(GET "/relations_zeroed" [] (show-relations))) (GET "/relations_zeroed" [] (show-relations)))
(defroutes user-routes (defroutes user-routes
(POST "/relation_request/:id/status" [id & body] (update-relationrequest-status id body)) ; STATUS ENUM: (open, accepted, rejected) (POST "/relation_request/:id/status" [id & body :as req] (update-relationrequest-status id body req)) ; STATUS ENUM: (open, accepted, rejected)
(POST "/request_relation" req (create-relation-request req))) (POST "/request_relation" req (create-relation-request req)))
(defroutes oauth-routes (defroutes oauth-routes

View file

@ -15,11 +15,6 @@
(defn- home-page [params] (defn- home-page [params]
(layout/render "home.html" params)) (layout/render "home.html" params))
(defn- get-relations []
(map
(fn [relation] (select-keys relation [:name :name_2]))
(db/get-relations)))
(defn- get-users [] (defn- get-users []
(db/get-users)) (db/get-users))
@ -30,33 +25,43 @@
(defn show-home [req] (defn show-home [req]
(let [users (get-users) (let [users (get-users)
relations (get-relations) relations (db/get-relations)
user (-> (get-in req [:session :user])) user (get-in req [:session :user])
user-relations (when user user-relations (when user
(seq (filter (fn [rel] ;; This can probably be compacted to one reduce operation
;; -> filter for only our relations, remove our name
(->> relations
(filter (fn [rel]
(or (or
(= (:name rel) (:name user)) (= (:from_name rel) (:name user))
(= (:name_2 rel) (:name user)))) (= (:to_name rel) (:name user)))))
relations))) (map (fn [rel] (if (= (:from_name rel) (:name user))
(-> rel
(assoc :other_name (:to_name rel))
(assoc :other_id (:to_id rel)))
(-> rel
(assoc :other_name (:from_name rel))
(assoc :other_id (:from_id rel))))))))
other_users (when user other_users (when user
(seq (filter (fn [usr] (not (= (:id usr) (:id user)))) (filter (fn [usr] (not (= (:id usr) (:id user))))
users))) users))
rel-requests-out (seq (db/get-relation-requests-from-user {:from_id (:id user)})) rel-requests-out (db/get-relation-requests-from-user {:from_id (:id user)})
rel-requests-in (seq (db/get-relation-requests-to-user {:to_id (:id user)})) rel-requests-in (db/get-relation-requests-to-user {:to_id (:id user)})
non_requested_users (seq (filter (fn [other-user] (not (some (partial = (:id other-user)) (map :to_id rel-requests-out)))) other_users))] ;; This can be done in one SQL query but since we already have the data for the other operations...
non_connected_users (filter (fn [other_user] (not (some (partial = (:id other_user))
(concat
(map :from_id rel-requests-in)
(map :to_id rel-requests-out)
(map :other_id user-relations)))))
other_users)]
(log/debug (str "Session: " (:session req))) (log/debug (str "Session: " (:session req)))
;(log/info (str "Relation requests: \n OUTGOING: " rel-requests-out "\n INCOMING: " rel-requests-in))
;(log/info (str "User relations: " user-relations))
;(log/info (str "Other Users: " other_users))
;(log/info (str "rel reqs out: " rel-requests-out))
;(log/info (str "rel reqs out id: " (seq (map :to_id rel-requests-out))))
(home-page {:relations relations (home-page {:relations relations
:users users :users users
:user user :user user
:user-relations user-relations :user-relations user-relations
:rel-requests-out rel-requests-out :rel-requests-out rel-requests-out
:rel-requests-in rel-requests-in :rel-requests-in rel-requests-in
:non_requested_users non_requested_users :non_connected_users non_connected_users
:flash (:flash req)}))) :flash (:flash req)})))
(defn show-relations (defn show-relations
@ -85,38 +90,46 @@
:links rels-indexed}))) :links rels-indexed})))
(defn update-relationrequest-status (defn update-relationrequest-status
[id body] "Updates the status of a relationship request"
(let [rr_id_map {:id id} [id body {:keys [:session]}]
success (cond (let [rr (db/get-relation-request {:id id})]
(contains? body :accept) ; Check that you are authorized to change this request
(do (if-not (= (:to_id rr) (get-in session [:user :id]))
(let [rr (db/get-relation-request rr_id_map)] (response/unauthorized "You can only update requests send to you")
(db/create-relation! {:from_id (:from_id rr) :to_id (:to_id rr)})) (if-not (= "open" (:status rr))
(db/update-relation-request-status! (assoc rr_id_map :status "accepted"))) (response/gone "Request is not open anymore")
(contains? body :decline) (let [correct-params?
(db/update-relation-request-status! (assoc rr_id_map :status "declined")) (cond
:else false)] (contains? body :accept)
(if success (do
(response/found "/") (db/create-relation! (select-keys rr [:from_id :to_id]))
(response-wrong-parameters)))) (db/update-relation-request-status! {:id id :status "accepted"}))
(contains? body :decline)
(db/update-relation-request-status! {:id id :status "declined"})
:else false)]
(if correct-params?
(response/found "/")
(response-wrong-parameters)))))))
(defn create-relation-request (defn create-relation-request
[req] "Creates a new request, as requests are unidirectional,
(let [data (:params req) this gets denied if there is a request pending or a relation already established"
[err result] (st/validate data request_relation-schema) [{:keys [:params :session :uri]}]
from-id (get-in req [:session :user :id])] (let [[err result] (st/validate params request_relation-schema)
(if (nil? from-id) (response/found (error-page from_id (get-in session [:user :id])
{:status 400 to_id (:to_id result)]
:title "No user id found in session"}))) (if (= from_id to_id)
(log/debug "Post to " (:uri req) "\n with data " result) (response/unprocessable-entity "Sadly enough, you can't hug yourself :'(")
(if (nil? err) (if-not (nil? err)
(do (response/unprocessable-entity "Incorrect input")
(log/debug "Create relation request") (let [count (db/get-connection-existence {:user_id from_id :other_id to_id})]
(db/create-relation-request! {:from_id from-id (if-not (= 0 (:count count))
:to_id (:to_id result) (do
:status "open"}) (log/info "Existing connections found, aborting.")
(response/found "/")) (response/conflict "There is already a request or relation between you and the other user"))
(do (do
(log/debug "Relation request failed") (log/debug "Create relation request")
(log/debug err) (db/create-relation-request! {:from_id from_id
(response/unprocessable-entity "Incorrect input"))))) :to_id to_id
:status "open"})
(response/found "/"))))))))

View file

@ -16,8 +16,7 @@
(cond-> (some (partial = (select-keys user [:zeusid :name])) admins) (cond-> (some (partial = (select-keys user [:zeusid :name])) admins)
(-> (->
(assoc-in [:user :admin] {:enabled false}) (assoc-in [:user :admin] {:enabled false})
(assoc-in [:user :roles] #{:admin}) (assoc-in [:user :roles] #{:admin}))))]
(assoc :identity "foo"))))]
(-> (found redirect-url) (-> (found redirect-url)
(assoc :session new-session)))) (assoc :session new-session))))