diff --git a/README.md b/README.md
index 64b9deb1..f35d2ad6 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,10 @@ Swarmpit is published on port `888` by default.
Refer to following [document](https://github.com/swarmpit/swarmpit/blob/master/doc/configuration.md)
+## User Types
+
+Refer to following [document](https://github.com/swarmpit/swarmpit/blob/master/doc/user_types.md)
+
## Development
Swarmpit is written purely in Clojure and utilizes React on front-end. CouchDB is used to persist application data & InfluxDB for cluster statistics.
diff --git a/doc/user_types.md b/doc/user_types.md
new file mode 100644
index 00000000..6fef278c
--- /dev/null
+++ b/doc/user_types.md
@@ -0,0 +1,15 @@
+# User Types
+
+# User & Admin Roles
+
+Both User & Admin have full access to make modifications to all stacks, services, secrets etc. - however, only Admin users can create/edit other users.
+
+# View Only Role
+
+As you would expect, 'View only' users can not make any modifications except pinning/unpinning dashboard entries and changing their password.
+With the exception of secret values (which are kept secret to full users and admins), they can view all information.
+
+
+
+
+
diff --git a/resources/public/CreateUser.png b/resources/public/CreateUser.png
new file mode 100644
index 00000000..e96b08d9
Binary files /dev/null and b/resources/public/CreateUser.png differ
diff --git a/resources/public/UserList.png b/resources/public/UserList.png
new file mode 100644
index 00000000..1a9ceb1a
Binary files /dev/null and b/resources/public/UserList.png differ
diff --git a/src/clj/swarmpit/authorization.clj b/src/clj/swarmpit/authorization.clj
index 7d4ea950..c9c8e455 100644
--- a/src/clj/swarmpit/authorization.clj
+++ b/src/clj/swarmpit/authorization.clj
@@ -3,6 +3,7 @@
[buddy.auth.accessrules :refer [success error wrap-access-rules]]
[swarmpit.handler :refer [resp-error]]
[swarmpit.token :refer [admin?]]
+ [swarmpit.token :refer [user?]]
[swarmpit.couchdb.client :as cc]))
(defn- authenticated-access
@@ -25,6 +26,15 @@
(error {:code 403
:message "Unauthorized admin access"}))))
+(defn- user-access
+ [{:keys [identity]}]
+ (let [username (get-in identity [:usr :username])
+ user (cc/user-by-username username)]
+ (if (or (admin? user) (user? user))
+ true
+ (error {:code 403
+ :message "Unauthorized user access"}))))
+
(defn- owner-access
[{:keys [path-params identity]}]
(let [user (get-in identity [:usr :username])
@@ -65,16 +75,26 @@
:handler {:and [authenticated-access admin-access]}}
{:pattern #"^/api/registry/(dockerhub|v2|ecr|acr|gitlab)/[a-zA-Z0-9]*/repositories$"
:request-method :get
- :handler {:and [authenticated-access registry-access]}}
+ :handler {:and [authenticated-access registry-access user-access]}}
{:pattern #"^/api/registry/(dockerhub|v2|ecr|acr|gitlab)/[a-zA-Z0-9]*/tags$"
:request-method :get
- :handler {:and [authenticated-access registry-access]}}
+ :handler {:and [authenticated-access registry-access user-access]}}
{:pattern #"^/api/registry/(dockerhub|v2|ecr|acr|gitlab)/[a-zA-Z0-9]*/ports$"
:request-method :get
- :handler {:and [authenticated-access registry-access]}}
+ :handler {:and [authenticated-access registry-access user-access]}}
{:pattern #"^/api/registry/(dockerhub|v2|ecr|acr|gitlab)/[a-zA-Z0-9]*$"
:request-method #{:get :delete :post}
- :handler {:and [authenticated-access owner-access]}}
+ :handler {:and [authenticated-access owner-access user-access]}}
+ {:pattern #"^/api/.*/dashboard$"
+ :request-method #{:delete :post}
+ :handler {:and [authenticated-access]}} ;;Allow pin/unpin by authenticated
+ {:pattern #"^/api/.*"
+ :request-method #{:delete :post}
+ :handler {:and [authenticated-access user-access]}} ;;Restrict ALL delete/post to user level and higher
+ {:pattern #"^/api/secrets/$"
+ :handler {:and [authenticated-access user-access]}} ;;Restrict getting secrets to user level and higher
+ {:pattern #"^/api/secrets/.*$"
+ :handler {:and [authenticated-access user-access]}} ;;Restrict getting secrets to user level and higher
{:pattern #"^/api/.*"
:handler authenticated-access}])
diff --git a/src/cljc/swarmpit/token.cljc b/src/cljc/swarmpit/token.cljc
index f25d3c0d..d7ff0adb 100644
--- a/src/cljc/swarmpit/token.cljc
+++ b/src/cljc/swarmpit/token.cljc
@@ -18,6 +18,10 @@
[user]
(= "admin" (:role user)))
+(defn user?
+ [user]
+ (or (= "admin" (:role user)) (= "user" (:role user))))
+
(defn token-value
[token]
(second (str/split token #" ")))
diff --git a/src/cljs/swarmpit/component/account_settings.cljs b/src/cljs/swarmpit/component/account_settings.cljs
index 209b6096..3f4ba6d3 100644
--- a/src/cljs/swarmpit/component/account_settings.cljs
+++ b/src/cljs/swarmpit/component/account_settings.cljs
@@ -3,7 +3,8 @@
[material.components :as comp]
[swarmpit.component.password :as password]
[swarmpit.component.api-access :as api-access]
- [sablono.core :refer-macros [html]]))
+ [sablono.core :refer-macros [html]]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -30,4 +31,4 @@
{:maxWidth "sm"
:className "Swarmpit-container"}
(form-password)
- (form-api-access))]])))
\ No newline at end of file
+ (form-api-access))]])))
\ No newline at end of file
diff --git a/src/cljs/swarmpit/component/common.cljs b/src/cljs/swarmpit/component/common.cljs
index 9b6568fd..50883ebf 100644
--- a/src/cljs/swarmpit/component/common.cljs
+++ b/src/cljs/swarmpit/component/common.cljs
@@ -106,10 +106,11 @@
(comp/grid
{:container true
:spacing 2}
- (comp/grid
- {:item true
- :xs 12}
- (toolbar/list-toobar title items filtered-items toolbar-render-metadata))
+ (if (not= "" toolbar-render-metadata)
+ (comp/grid
+ {:item true
+ :xs 12}
+ (toolbar/list-toobar title items filtered-items toolbar-render-metadata)))
(comp/grid
{:item true
:xs 12}
diff --git a/src/cljs/swarmpit/component/config/info.cljs b/src/cljs/swarmpit/component/config/info.cljs
index 41aad220..0080a7fa 100644
--- a/src/cljs/swarmpit/component/config/info.cljs
+++ b/src/cljs/swarmpit/component/config/info.cljs
@@ -17,7 +17,8 @@
[swarmpit.base64 :as base64]
[sablono.core :refer-macros [html]]
[clojure.contrib.inflect :as inflect]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -119,10 +120,11 @@
(comp/grid
{:container true
:spacing 2}
- (comp/grid
- {:item true
- :xs 12}
- (toolbar/toolbar "Config" (:configName config) form-actions))
+ (if (storage/user?)
+ (comp/grid
+ {:item true
+ :xs 12}
+ (toolbar/toolbar "Config" (:configName config) form-actions)))
(comp/grid
{:item true
:xs 12}
diff --git a/src/cljs/swarmpit/component/config/list.cljs b/src/cljs/swarmpit/component/config/list.cljs
index 82e302c6..0762e107 100644
--- a/src/cljs/swarmpit/component/config/list.cljs
+++ b/src/cljs/swarmpit/component/config/list.cljs
@@ -12,7 +12,8 @@
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
[rum.core :as rum]
- [swarmpit.component.common :as common]))
+ [swarmpit.component.common :as common]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -84,4 +85,6 @@
(reverse))
render-metadata
onclick-handler
- toolbar-render-metadata))))
+ (if (storage/user?)
+ toolbar-render-metadata
+ "")))))
diff --git a/src/cljs/swarmpit/component/network/info.cljs b/src/cljs/swarmpit/component/network/info.cljs
index 1eed7251..86d4fbe7 100644
--- a/src/cljs/swarmpit/component/network/info.cljs
+++ b/src/cljs/swarmpit/component/network/info.cljs
@@ -18,7 +18,8 @@
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
[rum.core :as rum]
- [clojure.string :as str]))
+ [clojure.string :as str]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -133,10 +134,11 @@
(comp/grid
{:container true
:spacing 2}
- (comp/grid
- {:item true
- :xs 12}
- (toolbar/toolbar "Network" (:networkName network) form-actions))
+ (if (storage/user?)
+ (comp/grid
+ {:item true
+ :xs 12}
+ (toolbar/toolbar "Network" (:networkName network) form-actions)))
(comp/grid
{:item true
:xs 12}
diff --git a/src/cljs/swarmpit/component/network/list.cljs b/src/cljs/swarmpit/component/network/list.cljs
index 5ed52be6..65ec7a22 100644
--- a/src/cljs/swarmpit/component/network/list.cljs
+++ b/src/cljs/swarmpit/component/network/list.cljs
@@ -12,7 +12,8 @@
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
[rum.core :as rum]
- [swarmpit.component.common :as common]))
+ [swarmpit.component.common :as common]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -79,4 +80,6 @@
filtered-items
render-metadata
onclick-handler
- toolbar-render-metadata))))
+ (if (storage/user?)
+ toolbar-render-metadata
+ "")))))
diff --git a/src/cljs/swarmpit/component/registry/list.cljs b/src/cljs/swarmpit/component/registry/list.cljs
index 05085c95..8ea38f10 100644
--- a/src/cljs/swarmpit/component/registry/list.cljs
+++ b/src/cljs/swarmpit/component/registry/list.cljs
@@ -13,7 +13,8 @@
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
[cljs.core :as core]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -181,6 +182,10 @@
distributions
filtered-distributions
render-metadata
- onclick-handler
- toolbar-render-metadata))))
+ (if (storage/user?)
+ onclick-handler
+ "")
+ (if (storage/user?)
+ toolbar-render-metadata
+ "")))))
diff --git a/src/cljs/swarmpit/component/secret/list.cljs b/src/cljs/swarmpit/component/secret/list.cljs
index 31e38e01..47b59111 100644
--- a/src/cljs/swarmpit/component/secret/list.cljs
+++ b/src/cljs/swarmpit/component/secret/list.cljs
@@ -11,7 +11,8 @@
[swarmpit.routes :as routes]
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -74,5 +75,9 @@
(sort-by :createdAt)
(reverse))
render-metadata
- onclick-handler
- toolbar-render-metadata))))
+ (if (storage/user?)
+ onclick-handler
+ nil)
+ (if (storage/user?)
+ toolbar-render-metadata
+ "")))))
diff --git a/src/cljs/swarmpit/component/service/info.cljs b/src/cljs/swarmpit/component/service/info.cljs
index edecef55..1ea411b8 100644
--- a/src/cljs/swarmpit/component/service/info.cljs
+++ b/src/cljs/swarmpit/component/service/info.cljs
@@ -28,7 +28,8 @@
[swarmpit.ajax :as ajax]
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -167,6 +168,18 @@
(filter #(not (= "shutdown" (:state %)))))
tasks/onclick-handler))))
+(defn form-pin-action
+ [service service-id pinned?]
+ (if pinned?
+ {:onClick #(detach-service-handler service-id)
+ :icon (comp/svg icon/pin-path)
+ :group false
+ :name "Detach"}
+ {:onClick #(pin-service-handler service-id)
+ :icon (comp/svg icon/pin-path)
+ :group false
+ :name "Pin"}))
+
(defn form-actions
[service service-id pinned?]
[(if pinned?
@@ -348,7 +361,12 @@
(comp/grid
{:item true
:xs 12}
- (toolbar/toolbar "Service" (:serviceName service) (form-actions service id pinned?)))
+ (toolbar/toolbar
+ "Service"
+ (:serviceName service)
+ (if (storage/user?)
+ (form-actions service id pinned?)
+ [(form-pin-action service id pinned?)])))
(comp/grid
{:item true
:sm 6
@@ -385,7 +403,12 @@
(comp/grid
{:item true
:xs 12}
- (toolbar/toolbar "Service" (:serviceName service) (form-actions service id pinned?)))
+ (toolbar/toolbar
+ "Service"
+ (:serviceName service)
+ (if (storage/user?)
+ (form-actions service id pinned?)
+ [(form-pin-action service id pinned?)])))
(form-settings-grid service tasks stats)
(form-tasks-grid service tasks)
(form-networks-grid networks id immutable?)
diff --git a/src/cljs/swarmpit/component/service/info/configs.cljs b/src/cljs/swarmpit/component/service/info/configs.cljs
index 9ee16c5a..c96f0425 100644
--- a/src/cljs/swarmpit/component/service/info/configs.cljs
+++ b/src/cljs/swarmpit/component/service/info/configs.cljs
@@ -6,7 +6,8 @@
[swarmpit.routes :as routes]
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -24,14 +25,16 @@
(comp/card-header
{:className "Swarmpit-table-card-header"
:title (comp/typography {:variant "h6"} "Configs")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 2})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 2})}
+ (comp/svg icon/edit-path))
+ nil)})
(if (empty? configs)
(comp/card-content
{}
diff --git a/src/cljs/swarmpit/component/service/info/deployment.cljs b/src/cljs/swarmpit/component/service/info/deployment.cljs
index f7c3fdb3..c9681bb0 100644
--- a/src/cljs/swarmpit/component/service/info/deployment.cljs
+++ b/src/cljs/swarmpit/component/service/info/deployment.cljs
@@ -4,7 +4,8 @@
[material.component.form :as form]
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -28,14 +29,16 @@
(comp/card-header
{:className "Swarmpit-form-card-header"
:title (comp/typography {:variant "h6"} "Deployment")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 4})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 4})}
+ (comp/svg icon/edit-path))
+ nil)})
(comp/card-content
{}
(comp/grid
diff --git a/src/cljs/swarmpit/component/service/info/hosts.cljs b/src/cljs/swarmpit/component/service/info/hosts.cljs
index c8f00db3..66903e70 100644
--- a/src/cljs/swarmpit/component/service/info/hosts.cljs
+++ b/src/cljs/swarmpit/component/service/info/hosts.cljs
@@ -5,7 +5,8 @@
[material.component.list.basic :as list]
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -19,14 +20,16 @@
(comp/card-header
{:className "Swarmpit-table-card-header"
:title (comp/typography {:variant "h6"} "Extra hosts")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 1})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 1})}
+ (comp/svg icon/edit-path))
+ nil)})
(if (empty? hosts)
(comp/card-content
{}
diff --git a/src/cljs/swarmpit/component/service/info/labels.cljs b/src/cljs/swarmpit/component/service/info/labels.cljs
index 86aca613..374dcf49 100644
--- a/src/cljs/swarmpit/component/service/info/labels.cljs
+++ b/src/cljs/swarmpit/component/service/info/labels.cljs
@@ -5,7 +5,8 @@
[material.component.list.basic :as list]
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -19,14 +20,16 @@
(comp/card-header
{:className "Swarmpit-table-card-header"
:title (comp/typography {:variant "h6"} "Labels")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 4})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 4})}
+ (comp/svg icon/edit-path))
+ nil)})
(if (empty? labels)
(comp/card-content
diff --git a/src/cljs/swarmpit/component/service/info/logdriver.cljs b/src/cljs/swarmpit/component/service/info/logdriver.cljs
index 493c021a..e2bb16eb 100644
--- a/src/cljs/swarmpit/component/service/info/logdriver.cljs
+++ b/src/cljs/swarmpit/component/service/info/logdriver.cljs
@@ -5,7 +5,8 @@
[material.component.list.basic :as list]
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -19,14 +20,16 @@
(comp/card-header
{:className "Swarmpit-table-card-header"
:title (comp/typography {:variant "h6"} "Log driver")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 5})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 5})}
+ (comp/svg icon/edit-path))
+ nil)})
(comp/card-content
{}
(comp/grid
diff --git a/src/cljs/swarmpit/component/service/info/mounts.cljs b/src/cljs/swarmpit/component/service/info/mounts.cljs
index 7fa2db71..1a0eaa2b 100644
--- a/src/cljs/swarmpit/component/service/info/mounts.cljs
+++ b/src/cljs/swarmpit/component/service/info/mounts.cljs
@@ -6,7 +6,8 @@
[swarmpit.routes :as routes]
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -67,14 +68,16 @@
(comp/card-header
{:className "Swarmpit-table-card-header"
:title (comp/typography {:variant "h6"} "Mounts")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 2})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 2})}
+ (comp/svg icon/edit-path))
+ nil)})
(if (empty? mounts)
(comp/card-content
diff --git a/src/cljs/swarmpit/component/service/info/networks.cljs b/src/cljs/swarmpit/component/service/info/networks.cljs
index 12863082..3fe997de 100644
--- a/src/cljs/swarmpit/component/service/info/networks.cljs
+++ b/src/cljs/swarmpit/component/service/info/networks.cljs
@@ -6,7 +6,8 @@
[swarmpit.component.network.list :as networks]
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -16,14 +17,16 @@
(comp/card-header
{:className "Swarmpit-table-card-header"
:title (comp/typography {:variant "h6"} "Networks")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 1})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 1})}
+ (comp/svg icon/edit-path))
+ nil)})
(if (empty? networks)
(comp/card-content
{}
diff --git a/src/cljs/swarmpit/component/service/info/ports.cljs b/src/cljs/swarmpit/component/service/info/ports.cljs
index 6bfc8482..0f8673dc 100644
--- a/src/cljs/swarmpit/component/service/info/ports.cljs
+++ b/src/cljs/swarmpit/component/service/info/ports.cljs
@@ -5,7 +5,8 @@
[material.component.list.basic :as list]
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -27,14 +28,16 @@
(comp/card-header
{:className "Swarmpit-table-card-header"
:title (comp/typography {:variant "h6"} "Ports")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 1})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 1})}
+ (comp/svg icon/edit-path))
+ nil)})
(if (empty? ports)
(comp/card-content
{}
diff --git a/src/cljs/swarmpit/component/service/info/resources.cljs b/src/cljs/swarmpit/component/service/info/resources.cljs
index 8c82a646..b59a6577 100644
--- a/src/cljs/swarmpit/component/service/info/resources.cljs
+++ b/src/cljs/swarmpit/component/service/info/resources.cljs
@@ -4,7 +4,8 @@
[material.component.form :as form]
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(defn format-cpu
[value]
@@ -24,14 +25,16 @@
(comp/card-header
{:className "Swarmpit-form-card-header"
:title (comp/typography {:variant "h6"} "Resources")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 3})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 3})}
+ (comp/svg icon/edit-path))
+ nil)})
(comp/card-content
{}
(comp/grid
diff --git a/src/cljs/swarmpit/component/service/info/secrets.cljs b/src/cljs/swarmpit/component/service/info/secrets.cljs
index 3ed33e0d..1ba4407f 100644
--- a/src/cljs/swarmpit/component/service/info/secrets.cljs
+++ b/src/cljs/swarmpit/component/service/info/secrets.cljs
@@ -6,7 +6,8 @@
[swarmpit.routes :as routes]
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -24,14 +25,16 @@
(comp/card-header
{:className "Swarmpit-table-card-header"
:title (comp/typography {:variant "h6"} "Secrets")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 2})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 2})}
+ (comp/svg icon/edit-path))
+ nil)})
(if (empty? secrets)
(comp/card-content
{}
@@ -41,5 +44,7 @@
(list/list
render-metadata
secrets
- onclick-handler)))))
+ (if (storage/user?)
+ onclick-handler
+ nil))))))
diff --git a/src/cljs/swarmpit/component/service/info/variables.cljs b/src/cljs/swarmpit/component/service/info/variables.cljs
index b6d757aa..a8527820 100644
--- a/src/cljs/swarmpit/component/service/info/variables.cljs
+++ b/src/cljs/swarmpit/component/service/info/variables.cljs
@@ -5,7 +5,8 @@
[material.component.list.basic :as list]
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -19,14 +20,16 @@
(comp/card-header
{:className "Swarmpit-table-card-header"
:title (comp/typography {:variant "h6"} "Environment variables")
- :action (comp/icon-button
- {:aria-label "Edit"
- :disabled immutable?
- :href (routes/path-for-frontend
- :service-edit
- {:id service-id}
- {:section 2})}
- (comp/svg icon/edit-path))})
+ :action (if (storage/user?)
+ (comp/icon-button
+ {:aria-label "Edit"
+ :disabled immutable?
+ :href (routes/path-for-frontend
+ :service-edit
+ {:id service-id}
+ {:section 2})}
+ (comp/svg icon/edit-path))
+ nil)})
(if (empty? variables)
(comp/card-content
{}
diff --git a/src/cljs/swarmpit/component/service/list.cljs b/src/cljs/swarmpit/component/service/list.cljs
index 23c34c3a..4dda9d5d 100644
--- a/src/cljs/swarmpit/component/service/list.cljs
+++ b/src/cljs/swarmpit/component/service/list.cljs
@@ -14,7 +14,8 @@
[swarmpit.routes :as routes]
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -180,5 +181,7 @@
filtered-items
render-metadata
onclick-handler
- toolbar-render-metadata)
+ (if (storage/user?)
+ toolbar-render-metadata
+ ""))
(form-filters filterOpen? filter)))))
diff --git a/src/cljs/swarmpit/component/stack/info.cljs b/src/cljs/swarmpit/component/stack/info.cljs
index 17da9541..81e30963 100644
--- a/src/cljs/swarmpit/component/stack/info.cljs
+++ b/src/cljs/swarmpit/component/stack/info.cljs
@@ -26,7 +26,8 @@
[clojure.contrib.inflect :as inflect]
[clojure.contrib.humanize :as humanize]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -337,7 +338,9 @@
(list/list
(:list secrets/render-metadata)
(sort-by :secretName secrets)
- secrets/onclick-handler)))))
+ (if (storage/user?)
+ secrets/onclick-handler
+ nil))))))
(defn- init-form-state
[]
@@ -417,10 +420,11 @@
(comp/grid
{:container true
:spacing 2}
- (comp/grid
- {:item true
- :xs 12}
- (toolbar/toolbar "Stack" stack-name (form-actions stack-name stackfile)))
+ (if (storage/user?)
+ (comp/grid
+ {:item true
+ :xs 12}
+ (toolbar/toolbar "Stack" stack-name (form-actions stack-name stackfile))))
(comp/grid
{:item true
:sm 6
@@ -447,10 +451,11 @@
(comp/grid
{:container true
:spacing 2}
- (comp/grid
- {:item true
- :xs 12}
- (toolbar/toolbar "Stack" stack-name (form-actions stack-name stackfile)))
+ (if (storage/user?)
+ (comp/grid
+ {:item true
+ :xs 12}
+ (toolbar/toolbar "Stack" stack-name (form-actions stack-name stackfile))))
(form-general-grid stack-name stackfile item)
(form-services-grid stack-name services)
(form-networks-grid stack-name networks)
diff --git a/src/cljs/swarmpit/component/stack/list.cljs b/src/cljs/swarmpit/component/stack/list.cljs
index b033477d..9ea4b437 100644
--- a/src/cljs/swarmpit/component/stack/list.cljs
+++ b/src/cljs/swarmpit/component/stack/list.cljs
@@ -12,7 +12,8 @@
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
[rum.core :as rum]
- [swarmpit.component.common :as common]))
+ [swarmpit.component.common :as common]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -106,4 +107,6 @@
(sort-by :stackName))
render-metadata
onclick-handler
- toolbar-render-metadata))))
+ (if (storage/user?)
+ toolbar-render-metadata
+ "")))))
diff --git a/src/cljs/swarmpit/component/user/create.cljs b/src/cljs/swarmpit/component/user/create.cljs
index e3aff7f3..72fb871b 100644
--- a/src/cljs/swarmpit/component/user/create.cljs
+++ b/src/cljs/swarmpit/component/user/create.cljs
@@ -58,6 +58,14 @@
:key "role-rg"
:value value
:onChange #(state/update-value [:role] (-> % .-target .-value) state/form-value-cursor)}
+ (comp/form-control-label
+ {:control (comp/radio
+ {:name "viewer-role"
+ :color "primary"
+ :key "viewer-role"})
+ :key "viewer-role"
+ :value "viewer"
+ :label "View Only"})
(comp/form-control-label
{:control (comp/radio
{:name "user-role"
@@ -114,7 +122,7 @@
(state/set-value {:username ""
:password ""
:email ""
- :role "user"} state/form-value-cursor))
+ :role "viewer"} state/form-value-cursor))
(def mixin-init-form
(mixin/init-form
diff --git a/src/cljs/swarmpit/component/user/edit.cljs b/src/cljs/swarmpit/component/user/edit.cljs
index 189b9330..73662a6d 100644
--- a/src/cljs/swarmpit/component/user/edit.cljs
+++ b/src/cljs/swarmpit/component/user/edit.cljs
@@ -42,6 +42,14 @@
:key "role-rg"
:value value
:onChange #(state/update-value [:role] (-> % .-target .-value) state/form-value-cursor)}
+ (comp/form-control-label
+ {:control (comp/radio
+ {:name "viewer-role"
+ :color "primary"
+ :key "viewer-role"})
+ :key "viewer-role"
+ :value "viewer"
+ :label "View Only"})
(comp/form-control-label
{:control (comp/radio
{:name "user-role"
diff --git a/src/cljs/swarmpit/component/user/list.cljs b/src/cljs/swarmpit/component/user/list.cljs
index 87580539..eb126e60 100644
--- a/src/cljs/swarmpit/component/user/list.cljs
+++ b/src/cljs/swarmpit/component/user/list.cljs
@@ -20,8 +20,15 @@
:render-fn (fn [item] (:username item))}
{:name "Email"
:render-fn (fn [item] (:email item))}
+ {:name "Role"
+ :render-fn (fn [item]
+ (if (="admin" (:role item))
+ "Admin"
+ (if (="user" (:role item))
+ "User"
+ "View Only")))}
{:name "Is Admin"
- :render-fn (fn [item] (if (:role item) "yes" "no"))}]}
+ :render-fn (fn [item] (if (= "admin" (:role item)) "Yes" "-"))}]}
:list {:primary (fn [item] (:username item))
:secondary (fn [item] (:email item))}})
diff --git a/src/cljs/swarmpit/component/volume/info.cljs b/src/cljs/swarmpit/component/volume/info.cljs
index 0c58e428..8e0e4cd1 100644
--- a/src/cljs/swarmpit/component/volume/info.cljs
+++ b/src/cljs/swarmpit/component/volume/info.cljs
@@ -17,7 +17,8 @@
[swarmpit.routes :as routes]
[sablono.core :refer-macros [html]]
[clojure.contrib.humanize :as humanize]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -117,10 +118,11 @@
(comp/grid
{:container true
:spacing 2}
- (comp/grid
- {:item true
- :xs 12}
- (toolbar/toolbar "Volume" (:volumeName volume) form-actions))
+ (if (storage/user?)
+ (comp/grid
+ {:item true
+ :xs 12}
+ (toolbar/toolbar "Volume" (:volumeName volume) form-actions)))
(comp/grid
{:item true
:xs 12}
diff --git a/src/cljs/swarmpit/component/volume/list.cljs b/src/cljs/swarmpit/component/volume/list.cljs
index 8eabbd01..5a9eee09 100644
--- a/src/cljs/swarmpit/component/volume/list.cljs
+++ b/src/cljs/swarmpit/component/volume/list.cljs
@@ -11,7 +11,8 @@
[swarmpit.routes :as routes]
[swarmpit.url :refer [dispatch!]]
[sablono.core :refer-macros [html]]
- [rum.core :as rum]))
+ [rum.core :as rum]
+ [swarmpit.storage :as storage]))
(enable-console-print!)
@@ -73,4 +74,6 @@
filtered-items
render-metadata
onclick-handler
- toolbar-render-metadata))))
+ (if (storage/user?)
+ toolbar-render-metadata
+ "")))))
diff --git a/src/cljs/swarmpit/storage.cljs b/src/cljs/swarmpit/storage.cljs
index 54f92513..9075fd99 100644
--- a/src/cljs/swarmpit/storage.cljs
+++ b/src/cljs/swarmpit/storage.cljs
@@ -49,3 +49,7 @@
(defn admin?
[]
(token/admin? (get-in (claims) [:usr])))
+
+(defn user?
+ []
+ (token/user? (get-in (claims) [:usr])))