Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

206 grant admin UI #208

Merged
merged 11 commits into from
Jul 26, 2023
40 changes: 23 additions & 17 deletions client/common/src/flybot/client/common/db/event.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
(let [post (-> posts :removed-post)
user-name (-> db :app/user :user/name)]
{:fx [[:dispatch [:evt.post/delete-post post]]
[:dispatch [:evt.post.form/clear-form]]
[:dispatch [:evt.form/clear :form/fields]]
[:dispatch [:evt.error/clear-errors]]
[:fx.log/message ["Post " (:post/id post) " deleted by " user-name "."]]]})))

Expand All @@ -68,15 +68,21 @@
:fx [[:fx.log/message ["User logged out."]]]}))

(rf/reg-event-fx
:fx.http/grant-admin-success
(fn [_ [_ {:keys [users]}]]
(let [{:user/keys [name roles]} (-> users :new-role :admin)]
{:fx [[:dispatch [:evt.post.form/clear-form]]
:fx.http/grant-role-success
(fn [_ [_ role-granted {:keys [users]}]]
(let [{:user/keys [name roles]} (-> users :new-role role-granted)]
{:fx [[:dispatch [:evt.form/clear :form.role/fields]]
[:dispatch [:evt.error/clear-errors]]
[:fx.log/message ["User " name " 's roles are now " (map :role/name roles)]]]})))

;; ---------- User ----------

(rf/reg-event-db
:evt.role.form/set-field
[(rf/path :form.role/fields)]
(fn [form [_ role id value]]
(assoc-in form [role id] value)))

(rf/reg-event-db
:evt.user/toggle-mode
[(rf/path :user/mode)]
Expand All @@ -93,23 +99,23 @@
:on-failure [:fx.http/failure]}}))

(rf/reg-event-fx
:evt.user.form/grant-admin
(fn [{:keys [db]} _]
(let [new-admin-email (-> db :form/fields :new-admin/email (valid/validate valid/user-email-schema))]
(if (:errors new-admin-email)
{:fx [[:dispatch [:evt.error/set-validation-errors (valid/error-msg new-admin-email)]]]}
:evt.user.form/grant-role
(fn [{:keys [db]} [_ role]]
(let [new-role-email (-> db :form.role/fields role :user/email (valid/validate valid/user-email-schema))]
(if (:errors new-role-email)
{:fx [[:dispatch [:evt.error/set-validation-errors (valid/error-msg new-role-email)]]]}
{:http-xhrio {:method :post
:uri (base-uri "/users/new-role/admin")
:uri (base-uri (str "/users/new-role/" (name role)))
:headers {:cookie (:user/cookie db)}
:params {:users
{:new-role
{(list :admin :with [new-admin-email])
{(list role :with [new-role-email])
{:user/name '?
:user/roles [{:role/name '?
:role/date-granted '?}]}}}}
:format (edn-request-format {:keywords? true})
:response-format (edn-response-format {:keywords? true})
:on-success [:fx.http/grant-admin-success]
:on-success [:fx.http/grant-role-success role]
:on-failure [:fx.http/failure]}}))))

;; ---------- Post ----------
Expand Down Expand Up @@ -137,7 +143,7 @@
(let [post (-> db :app/posts (get post-id))]
(if (= :edit (:post/mode post))
{:db (assoc-in db [:app/posts post-id :post/mode] :read)
:fx [[:dispatch [:evt.post.form/clear-form]]
:fx [[:dispatch [:evt.form/clear :form/fields]]
[:dispatch [:evt.error/clear-errors]]]}
{:db (assoc-in db [:app/posts post-id :post/mode] :edit)
:fx [[:dispatch [:evt.post.form/autofill post-id]]]}))))
Expand Down Expand Up @@ -273,9 +279,9 @@
(assoc post id value)))

(rf/reg-event-db
:evt.post.form/clear-form
(fn [db _]
(dissoc db :form/fields)))
:evt.form/clear
(fn [db [_ form]]
(dissoc db form)))

;; post deletion

Expand Down
4 changes: 2 additions & 2 deletions client/mobile/src/flybot/client/mobile/core/db/event.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
(fn [_ [_ {:keys [posts]}]]
(let [{:post/keys [id] :as post} (:new-post posts)]
{:fx [[:dispatch [:evt.post/add-post post]]
[:dispatch [:evt.post.form/clear-form]]
[:dispatch [:evt.form/clear :form/fields]]
[:dispatch [:evt.error/clear-errors]]
[:dispatch [:evt.post/set-modes :read]]
[:fx.log/message ["Post " id " sent."]]
Expand Down Expand Up @@ -102,7 +102,7 @@
:evt.post.edit/cancel
(fn [_ [_ post-id]]
(let [go-back-screen (if (temporary-id? (str post-id)) "posts-list" "post-read")]
{:fx [[:dispatch [:evt.post.form/clear-form]]
{:fx [[:dispatch [:evt.form/clear :form/fields]]
[:dispatch [:evt.error/clear-errors]]
[:dispatch [:evt.nav/navigate go-back-screen post-id]]]})))

Expand Down
2 changes: 1 addition & 1 deletion client/web/src/flybot/client/web/core/db/event.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
(fn [_ [_ {:keys [posts]}]]
(let [{:post/keys [id] :as post} (:new-post posts)]
{:fx [[:dispatch [:evt.post/add-post post]]
[:dispatch [:evt.post.form/clear-form]]
[:dispatch [:evt.form/clear :form/fields]]
[:dispatch [:evt.error/clear-errors]]
[:dispatch [:evt.post/set-modes :read]]
[:fx.log/message ["Post " id " sent."]]]})))
Expand Down
2 changes: 0 additions & 2 deletions client/web/src/flybot/client/web/core/dom/header.cljs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
(ns flybot.client.web.core.dom.header
(:require [flybot.client.web.core.dom.common.link :refer [internal-link]]
[flybot.client.web.core.dom.common.svg :as svg]
[flybot.client.web.core.dom.page.admin :as admin]
[re-frame.core :as rf]))

(defn login-link
Expand All @@ -19,7 +18,6 @@
(internal-link :flybot/about "About Us")
(internal-link :flybot/blog "Blog")
(internal-link :flybot/contact "Contact" false)
(when (admin/admin?) (internal-link :flybot/admin "Admin"))
(login-link)])

(defn navbar-web []
Expand Down
65 changes: 38 additions & 27 deletions client/web/src/flybot/client/web/core/dom/page/admin.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,56 @@
[flybot.client.web.core.dom.common.svg :as svg]
[re-frame.core :as rf]))

(defn admin?
[]
(some #{:admin} (->> @(rf/subscribe [:subs/pattern '{:app/user {:user/roles [{:role/name ?} ?x]}}])
(map :role/name))))
(defn has-role?
[role]
(some #{role} (->> @(rf/subscribe [:subs/pattern '{:app/user {:user/roles [{:role/name ?} ?x]}}])
(map :role/name))))

;;---------- Button ----------
(defn submit-admin-button
[]
(defn submit-role-button
[role]
[:button
{:type "button"
:on-click #(rf/dispatch [:evt.user.form/grant-admin])}
:on-click #(rf/dispatch [:evt.user.form/grant-role role])}
svg/done-icon])

;;---------- From ----------

(defn admin-form
[]
[:form
[:fieldset
[:label {:for "add-admin"} "Email of new admin:"]
[:br]
[:input
{:type "text"
:name "add-admin"
:placeholder "somebody@basecity.com"
:value @(rf/subscribe [:subs/pattern '{:form/fields {:new-admin/email ?x}}])
:on-change #(rf/dispatch [:evt.post.form/set-field
:new-admin/email
(.. % -target -value)])}]]])
(defn grant-role-form
[role]
(let [role-str (name role)
for-val (str "email-input-name-" role-str)]
[:form
[:fieldset
[:label {:for for-val} (str "Email of new " role-str ":")]
[:br]
[:input
{:type "text"
:name for-val
:placeholder "somebody@basecity.com"
:value @(rf/subscribe [:subs/pattern {:form.role/fields {role '{:user/email ?x}}}])
:on-change #(rf/dispatch [:evt.role.form/set-field
role
:user/email
(.. % -target -value)])}]]]))

;;---------- Admin div ----------

(defn admin-panel
[]
(when (admin?)
[:section.container.admin
[:h1 "Admin"]
[:section.container.admin
[:h1 "Admin"]
(if (has-role? :owner)
[:<>
[errors "admin-page" [:validation-errors :failure-http-result]]
[:form
[submit-admin-button]]
[admin-form]]]))
[:div
[:form
[submit-role-button :admin]]
[grant-role-form :admin]]
[:div
[:form
[submit-role-button :owner]]
[grant-role-form :owner]]]
[:div
[:h2 "You do not have the required permissions."]
[:p "This section is dedicated to the owners of the website."]])])
59 changes: 59 additions & 0 deletions client/web/test/flybot/client/web/core/dom/page/admin_test.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
(ns flybot.client.web.core.dom.page.admin-test
(:require [cljs.test :refer-macros [deftest is testing use-fixtures]]
[day8.re-frame.test :as rf-test]
[flybot.client.web.core.db]
[flybot.client.web.core.router :as router]
[flybot.common.test-sample-data :as s]
[flybot.common.utils :as utils]
[re-frame.core :as rf]))

;; ---------- Fixtures ----------

(use-fixtures :once
{:before (fn [] (router/init-routes!))})

(defn test-fixtures
"Set local storage values and initialize DB with sample data."
[]
;; Mock local storage store
(rf/reg-cofx
:cofx.app/local-store-theme
(fn [coeffects _]
(assoc coeffects :local-store-theme :dark)))
;; Mock success http request
(rf/reg-fx :http-xhrio
(fn [_]
(rf/dispatch [:fx.http/all-success s/init-data])))
;; Initialize db
(rf/dispatch [:evt.app/initialize]))

(deftest add-roles
(with-redefs [utils/mk-date (constantly s/alice-date-granted)]
(rf-test/run-test-sync
(test-fixtures)
(let [{:user/keys [email] :as editor-alice} s/alice-user
admin-alice (update editor-alice :user/roles conj
[#:role{:name :admin :date-granted s/alice-date-granted}])
role-form (rf/subscribe [:subs/pattern '{:form.role/fields ?x}])
errors (rf/subscribe [:subs/pattern '{:app/errors ?x}])]

;;---------- GRANT ROLE ERROR
(rf/dispatch [:evt.role.form/set-field :admin :user/email "email@wrong.com"])
;; Send role but validation error
(rf/dispatch [:evt.user.form/grant-role :admin])
(testing "Form not cleared and error added to db."
(is @role-form)
(is @errors))

;;---------- GRANT ROLE SUCCESS
(rf/reg-fx :http-xhrio
(fn [_] (rf/dispatch
[:fx.http/grant-role-success
{:users {:new-role {:admin admin-alice}}}])))
;; fill the new role form
(rf/dispatch [:evt.role.form/set-field :admin :user/email email])
;; grant new role to user in the server
(rf/dispatch [:evt.user.form/grant-role :admin])
(testing "Form and error cleared."
(is (not @role-form))
(is (not @errors)))))))
13 changes: 7 additions & 6 deletions client/web/test/flybot/client/web/test_runner.cljs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
(ns flybot.client.web.test-runner
(:require
[figwheel.main.testing :refer-macros [run-tests-async]]
[figwheel.main.testing :refer-macros [run-tests-async]]
;; require all the namespaces that have tests in them
[flybot.client.web.core.db-test]
[flybot.client.web.core.dom.common.link-test]
[flybot.client.web.core.dom.page.post-test]
[flybot.client.web.core.router-test]
[flybot.common.validation.markdown-test]))
[flybot.client.web.core.db-test]
[flybot.client.web.core.dom.common.link-test]
[flybot.client.web.core.dom.page.admin-test]
[flybot.client.web.core.dom.page.post-test]
[flybot.client.web.core.router-test]
[flybot.common.validation.markdown-test]))

(defn -main [& args]
;; this needs to be the last statement in the main function so that it can
Expand Down
4 changes: 2 additions & 2 deletions resources/public/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -586,8 +586,8 @@ section .team img {
border-bottom-color: var(--border-primary-color);
}

section.admin h1 {
text-align: center;
.admin div {
margin: 1rem;
}

/* Blog Page */
Expand Down