Skip to content

Commit a28470d

Browse files
committed
Release of version 1.3.0
1 parent c72636f commit a28470d

File tree

3 files changed

+113
-22
lines changed

3 files changed

+113
-22
lines changed

pyxecm/customizer/browser_automation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def get_page(self, url: str = "") -> bool:
119119
logger.error("Cannot load page -> %s; error -> %s", page_url, exception)
120120
return False
121121

122-
logger.info("Page title get page -> %s", self.browser.title)
122+
logger.info("Page title after get page -> %s", self.browser.title)
123123

124124
return True
125125

pyxecm/customizer/payload.py

Lines changed: 102 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@
118118
import json
119119
import logging
120120
import os
121+
import random
121122
import re
123+
import string
122124
from typing import Callable
123125
from urllib.parse import urlparse
124126

@@ -2095,7 +2097,7 @@ def process_group_placeholders(self):
20952097

20962098
# Now we determine the ID. Either it is in the payload section from
20972099
# the current customizer run or we try to look it up in the system.
2098-
# The latter case may happen if the custiomuer pod got restarted.
2100+
# The latter case may happen if the customizer pod got restarted.
20992101
group_id = self.determine_group_id(group)
21002102
if not group_id:
21012103
logger.warning(
@@ -2129,7 +2131,7 @@ def process_user_placeholders(self):
21292131
)
21302132
continue
21312133
user_name = user["name"]
2132-
# Check if group has been disabled in payload (enabled = false).
2134+
# Check if user has been disabled in payload (enabled = false).
21332135
# In this case we skip the element:
21342136
if "enabled" in user and not user["enabled"]:
21352137
logger.info(
@@ -2139,15 +2141,15 @@ def process_user_placeholders(self):
21392141

21402142
# Now we determine the ID. Either it is in the payload section from
21412143
# the current customizer run or we try to look it up in the system.
2142-
# The latter case may happen if the custiomuer pod got restarted.
2144+
# The latter case may happen if the customizer pod got restarted.
21432145
user_id = self.determine_user_id(user)
21442146
if not user_id:
21452147
logger.warning(
21462148
"User needs an ID for placeholder definition. Skipping..."
21472149
)
21482150
continue
21492151

2150-
# Add Group with its ID to the dict self._placeholder_values:
2152+
# Add user with its ID to the dict self._placeholder_values:
21512153
self._placeholder_values["OTCS_USER_ID_%s", user_name.upper()] = str(
21522154
user_id
21532155
)
@@ -2428,8 +2430,8 @@ def process_users(self, section_name: str = "users") -> bool:
24282430

24292431
# If this payload section has been processed successfully before we
24302432
# can return True and skip processing it once more:
2431-
if self.check_status_file(section_name):
2432-
return True
2433+
# if self.check_status_file(section_name):
2434+
# return True
24332435

24342436
success: bool = True
24352437

@@ -2452,13 +2454,28 @@ def process_users(self, section_name: str = "users") -> bool:
24522454
continue
24532455

24542456
# Sanity checks:
2455-
if not "password" in user:
2456-
logger.error(
2457-
"User -> %s is missing a password. Skipping to next user...",
2457+
if (
2458+
not "password" in user
2459+
or user["password"] is None
2460+
or user["password"] == ""
2461+
):
2462+
logger.info(
2463+
"User -> %s no password defined in payload, generating random password...",
24582464
user_name,
24592465
)
2460-
success = False
2461-
continue
2466+
user["password"] = self.generate_password(
2467+
length=10, use_special_chars=True
2468+
)
2469+
2470+
description_attribue = {
2471+
"name": "description",
2472+
"value": "initial password: " + user["password"],
2473+
}
2474+
2475+
try:
2476+
user["extra_attributes"].append(description_attribue)
2477+
except KeyError:
2478+
user["extra_attributes"] = [description_attribue]
24622479

24632480
# Sanity checks:
24642481
if not "base_group" in user:
@@ -3533,12 +3550,12 @@ def process_admin_settings(
35333550

35343551
if not admin_settings:
35353552
logger.info("Payload section -> %s is empty. Skipping...", section_name)
3536-
return True
3553+
return False # important to return False here as otherwise we are triggering a restart of services!!
35373554

35383555
# If this payload section has been processed successfully before we
35393556
# can return True and skip processing it once more:
35403557
if self.check_status_file(section_name):
3541-
return True
3558+
return False # important to return False here as otherwise we are triggering a restart of services!!
35423559

35433560
restart_required: bool = False
35443561
success: bool = True
@@ -5587,12 +5604,12 @@ def process_workspace_members(self, section_name: str = "workspaceMembers") -> b
55875604
# of automatically created workspaces - this can happen because the
55885605
# creator gets added to the leader role automatically:
55895606
leader_role_id = self._otcs.lookup_result_value(
5590-
workspace_roles, "leader", "True", "id"
5607+
workspace_roles, "leader", True, "id"
55915608
)
55925609

55935610
if leader_role_id:
55945611
leader_role_name = self._otcs.lookup_result_value(
5595-
workspace_roles, "leader", str(True), "name"
5612+
workspace_roles, "leader", True, "name"
55965613
)
55975614
response = self._otcs.remove_member_from_workspace(
55985615
workspace_node_id, leader_role_id, workspace_owner_id, False
@@ -8391,7 +8408,7 @@ def process_browser_automations(
83918408
success = False
83928409
break
83938410
else:
8394-
browser_automation_object.implict_wait(10.0)
8411+
browser_automation_object.implict_wait(15.0)
83958412
logger.info(
83968413
"Successfuly loaded page -> %s.", base_url + page
83978414
)
@@ -8415,7 +8432,7 @@ def process_browser_automations(
84158432
success = False
84168433
break
84178434
else:
8418-
browser_automation_object.implict_wait(10.0)
8435+
browser_automation_object.implict_wait(15.0)
84198436
logger.info("Successfuly clicked element -> %s.", elem)
84208437
case "set_elem":
84218438
elem = automation.get("elem", "")
@@ -8657,3 +8674,71 @@ def get_k8s(self) -> object:
86578674
def getM365(self) -> object:
86588675
"""Get M365 object"""
86598676
return self._m365
8677+
8678+
def generate_password(
8679+
self,
8680+
length: int,
8681+
use_special_chars: bool = False,
8682+
min_special: int = 1,
8683+
min_numerical: int = 1,
8684+
min_upper: int = 1,
8685+
min_lower: int = 1,
8686+
override_special: str = None,
8687+
):
8688+
"""Function to generate random passwords with a given specification
8689+
8690+
Args:
8691+
length (int): Define password length
8692+
use_special_chars (bool, optional): Define if special characters should be used. Defaults to False.
8693+
min_special (int, optional): Define min amount of special characters. Defaults to 1.
8694+
min_numerical (int, optional): Define if numbers should be used. Defaults to 1.
8695+
min_upper (int, optional): Define mininum number of upper case letters. Defaults to 1.
8696+
min_lower (int, optional): Define minimum number of lower case letters. Defaults to 1.
8697+
override_special (string | None, optional): Define special characters to be used, if not set: !@#$%^&*()_-+=<>?/{}[]. Defaults to None.
8698+
8699+
Raises:
8700+
ValueError: _description_
8701+
8702+
Returns:
8703+
_type_: _description_
8704+
"""
8705+
# Define character sets
8706+
lowercase_letters = string.ascii_lowercase
8707+
uppercase_letters = string.ascii_uppercase
8708+
numerical_digits = string.digits
8709+
special_characters = "!@#$%^&*()_-+=<>?/{}[]"
8710+
8711+
if override_special:
8712+
special_characters = override_special
8713+
# Ensure minimum requirements are met
8714+
8715+
if min_special + min_numerical + min_upper + min_lower > length:
8716+
raise ValueError("Minimum requirements exceed password length")
8717+
8718+
# Initialize the password
8719+
password = []
8720+
8721+
# Add required characters
8722+
password.extend(random.sample(lowercase_letters, min_lower))
8723+
password.extend(random.sample(uppercase_letters, min_upper))
8724+
password.extend(random.sample(numerical_digits, min_numerical))
8725+
8726+
if use_special_chars:
8727+
password.extend(random.sample(special_characters, min_special))
8728+
8729+
# Fill the rest of the password with random characters
8730+
remaining_length = length - len(password)
8731+
all_chars = lowercase_letters + uppercase_letters + numerical_digits
8732+
8733+
if use_special_chars:
8734+
all_chars += special_characters
8735+
8736+
password.extend(random.choices(all_chars, k=remaining_length))
8737+
8738+
# Shuffle the password to ensure randomness
8739+
random.shuffle(password)
8740+
8741+
# Convert the password list to a string
8742+
final_password = "".join(password)
8743+
8744+
return final_password

pyxecm/otds.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,10 +1369,16 @@ def update_user(
13691369
dict: Request response or None if the update fails.
13701370
"""
13711371

1372-
userPatchBodyJson = {
1373-
"userPartitionID": partition,
1374-
"values": [{"name": attribute_name, "values": [attribute_value]}],
1375-
}
1372+
if attribute_name in ["description"]:
1373+
userPatchBodyJson = {
1374+
"userPartitionID": partition,
1375+
attribute_name: attribute_value,
1376+
}
1377+
else:
1378+
userPatchBodyJson = {
1379+
"userPartitionID": partition,
1380+
"values": [{"name": attribute_name, "values": [attribute_value]}],
1381+
}
13761382

13771383
request_url = self.users_url() + "/" + user_id
13781384

0 commit comments

Comments
 (0)