1- import calendar
21from urllib .parse import urljoin
32import sys
43
@@ -62,6 +61,12 @@ def add_arguments(self, parser):
6261 """parse arguments"""
6362
6463 # pylint: disable=expression-not-assigned
64+ parser .add_argument (
65+ "--verbose" ,
66+ help = "Enable verbose logging" ,
67+ action = "store_true" ,
68+ default = False ,
69+ )
6570 parser .add_argument (
6671 "--client-id" ,
6772 required = True ,
@@ -150,17 +155,12 @@ def _generate_keycloak_user_payload(self, user, keycloak_group_path):
150155 dict: user representation for use with the Keycloak partialImport Admin REST API endpoint.
151156 """
152157 user_keycloak_payload = {
153- "createdTimestamp" : calendar . timegm ( user .date_joined .timetuple ()) ,
158+ "createdTimestamp" : user .date_joined .timestamp () * 1000 ,
154159 "username" : user .email ,
155160 "enabled" : True ,
156- "totp" : False ,
157161 "emailVerified" : True ,
158162 "email" : user .email ,
159- "credentials" : [],
160- "disableableCredentialTypes" : [],
161- "requiredActions" : [],
162- "realmRoles" : ["default-roles-master" ],
163- "notBefore" : 0 ,
163+ "realmRoles" : [f"default-roles-{ settings .KEYCLOAK_REALM_NAME } " ],
164164 "groups" : [keycloak_group_path ] if keycloak_group_path else [],
165165 "attributes" : {
166166 "fullName" : user .profile .name ,
@@ -190,7 +190,23 @@ def _verify_environment_variables_configured(self):
190190 "KEYCLOAK_REALM_NAME must be defined as an environment variable."
191191 )
192192
193+ def _log_api_call (self , response ):
194+ """Log the API call to keycloak"""
195+ status_code = response .status_code
196+
197+ if not self .verbose and status_code == 200 :
198+ return
199+
200+ log_out = self .stdout if status_code == 200 else self .stderr
201+
202+ log_out .write (f"{ response .request .method } { response .request .url } " )
203+ log_out .write (f"Status code: { status_code } " )
204+ log_out .write (f"Request:\t { response .request .body .decode ('utf-8' )} " )
205+ log_out .write (f"Response:\t { response .text } " )
206+
193207 def handle (self , * args , ** kwargs ):
208+ self .verbose = kwargs ["verbose" ]
209+
194210 self ._verify_environment_variables_configured ()
195211
196212 keycloak_partial_import_url = f"{ settings .KEYCLOAK_BASE_URL } /admin/realms/{ settings .KEYCLOAK_REALM_NAME } /partialImport"
@@ -239,14 +255,9 @@ def handle(self, *args, **kwargs):
239255 )
240256 response = session .post (keycloak_partial_import_url , json = payload )
241257
242- # If the response from Keycloak is not 200, print out an error and move on to
243- # the next batch of users to export.
244- if response .status_code != 200 :
245- self .stderr .write ("Error calling Keycloak REST API, returned:" )
246- self .stderr .write (f"Status code: { response .status_code } " )
247- self .stderr .write ("Content:" )
248- self .stderr .write (response .text )
249- else :
258+ self ._log_api_call (response )
259+
260+ if response .status_code == 200 :
250261 user_synced_with_keycloak_records = []
251262 keycloak_response_body = response .json ()
252263
@@ -258,12 +269,14 @@ def handle(self, *args, **kwargs):
258269 item ["resourceName" ]: item for item in keycloak_results
259270 }
260271 for user in batch :
261- if (
262- keycloak_results_email_key_dict [user .email ]["action" ]
263- == "ADDED"
264- ):
272+ action = keycloak_results_email_key_dict [user .email ]["action" ]
273+ if action in ("ADDED" , "SKIPPED" ):
265274 user_synced_with_keycloak_records .append (
266- UserExportToKeycloak (user = user )
275+ UserExportToKeycloak (user = user , action = action )
276+ )
277+ else :
278+ self .stderr .write (
279+ f"Unexpected action '{ action } for user '{ user .email } "
267280 )
268281 UserExportToKeycloak .objects .bulk_create (
269282 user_synced_with_keycloak_records , ignore_conflicts = True
0 commit comments