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
Issue/533 admin console features #652
Conversation
kardan
commented
Mar 13, 2017
- Update release notes
- Test plan | Unit test | Integration test
- Copyright header
- Code formatting
- Documentation
…vo-lumen into issue/533-admin-console-features
…vo-lumen into issue/533-admin-console-features
…vo-lumen into issue/533-admin-console-features
…vo-lumen into issue/533-admin-console-features
Pending parent component refresh strategy to reload user list
WIP extending admin scripts add-tenant
…vo-lumen into issue/533-admin-console-features
Disabled database setup while developing the Keycloak part. Don’t handle the case when the user not exists yet.
…vo-lumen into issue/533-admin-console-features
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
backend review
@@ -1,25 +1,59 @@ | |||
(ns akvo.lumen.admin.add-tenant | |||
"The following env vars are assumed to be present: | |||
KEYCLOAK, KEYCLOAK_SECRET These can be found in the Keycloak admin in the | |||
akvo-lumen-confidential client section. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we enumerate what the options to KEYCLOAK
are and what they mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do
[label] | ||
(cond | ||
(< (count label) 3) | ||
(throw (Exception. "To short label, should be 3 or more characters.")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We often use ex-info
instead of Exception
(or some subclass). Perhaps (ex-info "Too short label ......" {:label label})
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.
(< (count label) 3) | ||
(throw (Exception. "To short label, should be 3 or more characters.")) | ||
|
||
(not (empty? (set/intersection (set blacklist) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(contains? (set blacklist) label)
instead here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.
(try | ||
(setup-database (conform-label label) title) | ||
(let [user-creds (setup-keycloak label email)] | ||
(println "User creds:") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to print the admin users credentials?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we generate a password we want to be able to communicate it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about it maybe this should have been automated by sending an email in the script.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 I think it's fine for now that we communicate the admin credentials back to the user
(println "User creds:") | ||
(pprint user-creds)) | ||
(catch Exception e | ||
(println "Got error") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps print the stacktrace instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the top level Exception for ex-info instead.
@@ -93,6 +110,32 @@ | |||
(response {:status (:status ed) | |||
:body (:reasonPhrase ed)}))))) | |||
|
|||
(defn tenant-admin? | |||
[request-draft api-root tenant user-id] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kardan could you explain what this request-draft
object is? I see it's being used a lot but I'm not sure I understand what it is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Request-draft is a request object that is used with clj-http (the second argument to request functions). Thinking about it in hindsight I do think this is a questionable design. I should have named it request-headers and passed that around. Would have been just as simple to build a map with {:headers :body } as what I do now (assoc request-draft :body }.
(filter #(and (get % "emailVerified") | ||
(get % "enabled")) | ||
admins))] | ||
(not (empty? (set/intersection #{user-id} (set admin-ids)))))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could use contains?
here as well instead of (not (empty (set/intersection ...)))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree.
(http/ok (fetch-user-by-id request-draft api-root tenant user-id)) | ||
(do | ||
(println (format "Tried to promote user: %s" user-id)) | ||
(http/internal-server-error)))))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we actually get to this else
part if keycloak returns something other than 204? If I remember correctly clj.http client will throw an exception on 4XX/5XX so we would still see http/internal-server-error
but not generated from this part of the code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question for the two subsequent places where we have the same branching logic: Is the else
part reachable?
|
||
|
||
|
||
#_(defn do-promote-user-to-admin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the left overs!
(if (keycloak/tenant-member? keycloak tenant email) | ||
(http/bad-request {"reson" "Already tenant member"}) | ||
(do | ||
(future |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want/need to do this async and always return 200 OK
?
Now describes the different options for KEYCLOAK and where to find the KEYCLOAK_SECRET.
- Removed commented code - Removed the future - yikes!
- Moved for passing around a request-draft object to request-headers - Fixed bug when inviting non existing user and trying to use “nil” username in a keycloak api call.
@@ -19,3 +21,22 @@ | |||
password (env :pgpassword)}}] | |||
(format "jdbc:postgresql://%s/%s?user=%s&password=%s&ssl=true" | |||
host database user password))) | |||
|
|||
(defn- keycloak-url | |||
"Hardcoded urls, seemed like a fair thing to do." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is a bit weird?
@@ -37,7 +53,7 @@ | |||
(-> (client/get (format "%s/.well-known/openid-configuration" issuer)) | |||
:body json/decode)) | |||
|
|||
(defn request-draft | |||
(defn request-headers | |||
"Create a partial request with json content type and a valid bearer token. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this docstring should be tweaked a bit now when you return headers only?
|
||
(defn tenant-member? | ||
"Return true for both members and admins." | ||
[{api-root :api-root :as keycloak} tenant email] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it's better but usually when I don't want to rename the bindings I use :keys
instead:
{:keys [api-root] :as keycloak}