-
Notifications
You must be signed in to change notification settings - Fork 27
/
user.clj
110 lines (99 loc) · 6.46 KB
/
user.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
(ns keycloak.user
(:require [clojure.tools.logging :as log :refer [info warn]]
[clojure.java.data :refer [from-java]]
[clojure.java.io :as io]
[cheshire.core :as json :refer [encode]])
(:import [org.keycloak.representations.idm CredentialRepresentation UserRepresentation RoleRepresentation]))
(defn user-for-update [{:keys [username first-name last-name email] :as person} roles]
(doto (UserRepresentation.)
(.setUsername username)
(.setFirstName first-name)
(.setLastName last-name)
(.setEmail email)
(.setRealmRoles (java.util.ArrayList. (vec (map name roles))))
;;setRealmRoles has a bug with the admin REST API and doesn't work, keep it here, but need to deal with UserResource to add them
(.setEnabled true)))
(defn user-for-creation [{:keys [username first-name last-name email password] :as person}]
(doto (user-for-update person)
(.setRequiredActions (java.util.ArrayList. ["UPDATE_PASSWORD"]))
(.setCredentials [(doto (CredentialRepresentation.)
(.setType CredentialRepresentation/PASSWORD)
(.setValue password))])))
(defn search-user
([keycloak-client realm-name user-attribute]
(try
(-> keycloak-client (.realm realm-name) (.users) (.search user-attribute (int 0) (int 10)))
(catch javax.ws.rs.NotFoundException nfe nil)))
([keycloak-client realm-name username first-name last-name email]
(try
(-> keycloak-client (.realm realm-name) (.users) (.search username first-name last-name email (int 0) (int 10)))
(catch javax.ws.rs.NotFoundException nfe nil))))
(defn user-id
([keycloak-client realm-name user-attribute]
(let [search-result (search-user keycloak-client realm-name user-attribute)]
(if (and search-result (> (count search-result) 0))
(.getId (first search-result))
(do (info "user with attribute"user-attribute"not found in realm"realm-name) nil))))
([keycloak-client realm-name username first-name last-name email]
(let [search-result (search-user keycloak-client realm-name username first-name last-name email)]
(if (and search-result (> (count search-result) 0))
(.getId (first search-result))
(do (info "user with attributes username:"username ",first-name" first-name ",last-name:" last-name ",email:" email "not found in realm"realm-name) nil)))))
(defn delete-user!
[keycloak-client realm-name user-attribute]
(info "Delete user with attribute"user-attribute"from realm"realm-name)
(let [user-id (user-id keycloak-client realm-name user-attribute)]
(if user-id
(-> keycloak-client (.realm realm-name) (.users) (.delete user-id))
(info "user"user-attribute"not found in realm"realm-name))))
(defn username-or-email-exists? [keycloak-client realm-name user]
(let [username-exists? (not (nil? (user-id keycloak-client realm-name (.getUsername user))))
email-exists? (not (nil? (user-id keycloak-client realm-name (.getEmail user))))]
(or username-exists? email-exists?)))
(defn add-roles!
[keycloak-client realm-name username roles]
(let [user-searched (search-user keycloak-client realm-name username)
user-id (-> user-searched first (.getId))
user-resource (-> keycloak-client (.realm realm-name) (.users) (.get user-id))
roles-representations (doall (map (fn [role] (-> keycloak-client (.realm realm-name) (.roles) (.get role) (.toRepresentation))) (map name roles)))]
(-> user-resource (.roles) (.realmLevel) (.add (java.util.ArrayList. (vec roles-representations))))))
(defn- check-user-properly-created [keycloak-client realm-name username email]
(let [user-searched (search-user keycloak-client realm-name username)]
(when (or (nil? user-searched) (empty? user-searched))
(throw (ex-info (str "Can't find user " username " due to creation failure. Check the uniqueness and validity of the username and email in Keycloak (email:"email")") {:username username :email email})))))
(defn delete-and-create-user!
([keycloak-client realm-name person]
(delete-and-create-user! keycloak-client realm-name person nil))
([keycloak-client realm-name {:keys [username first-name last-name email password is-manager] :as person} roles]
(info "create user" username "in realm" realm-name"with roles"roles". If user already exists, delete it and re-create it.")
(let [username-exists? (not (nil? (user-id keycloak-client realm-name username)))
email-exists? (not (nil? (user-id keycloak-client realm-name email)))
_ (if username-exists? (do (delete-user! keycloak-client realm-name username) (Thread/sleep 250)))
_ (if email-exists? (do (delete-user! keycloak-client realm-name email) (Thread/sleep 250)))
response (-> keycloak-client (.realm realm-name) (.users) (.create (user-for-creation person)))
_ (check-user-properly-created keycloak-client realm-name username email)]
(when roles (add-roles! keycloak-client realm-name username roles))
person)))
(defn create-or-update-user!
[keycloak-client realm-name {:keys [username first-name last-name email password is-manager] :as person} roles]
(let [_ (info "Create or update user" username "in realm" realm-name "with roles" (roles person))
username-exists? (not (nil? (user-id keycloak-client realm-name username)))
email-exists? (not (nil? (user-id keycloak-client realm-name email)))
user-id (user-id keycloak-client realm-name username first-name last-name email)]
(if username-exists? (info (str "User already exists with username: " username)))
(if email-exists? (info (str "User already exists with email: " email)))
(when (and email-exists? (not username-exists?))
(warn (str "Email " email " already exists in realm " realm-name))
;(throw (ex-info (str "Email " email " already exists in realm " realm-name) {:realm-name realm-name :email email})
)
(try
(if (and username-exists? user-id)
(-> keycloak-client (.realm realm-name) (.users) (.get user-id) (.update (user-for-update person)))
(-> keycloak-client (.realm realm-name) (.users) (.create (user-for-creation person))))
(catch javax.ws.rs.ClientErrorException cee
(warn "Exception while creating or updating " person (.getMessage cee))))
(check-user-properly-created keycloak-client realm-name username email)
(add-roles! keycloak-client realm-name username roles)))
(defn get-users
([keycloak-client realm-name]
(-> keycloak-client (.realm realm-name) (.users) (.list))))