from __future__ import annotations from dataclasses import dataclass, field from typing import Dict, List, Optional @dataclass class UserInputRecord: display_name: str sam_account_name: str email: str dept_ou: str base_group: str project_groups: List[str] = field(default_factory=list) resource_groups: List[str] = field(default_factory=list) @dataclass class ResolvedUserPlan: user_dn: str display_name: str sam_account_name: str email: str uid: str uid_number: int gid_number: int unix_home_directory: str base_group: str project_groups: List[str] resource_groups: List[str] optional_missing_groups: List[str] = field(default_factory=list) @dataclass class LdapConfig: host: str port: int use_ssl: bool bind_dn: str bind_password: str base_dn: str people_base_dn: str groups_base_dn: str upn_suffix: str = "" user_object_classes: List[str] = field(default_factory=list) user_rdn_attr: str = "CN" @dataclass class DefaultsConfig: base_group: str = "staff" initial_uid_number: int = 2106 initial_password: str = "1234.com" @dataclass class PathsConfig: uid_state_file: str = "state/uid_state.json" group_gid_map_file: str = "state/group_gid_map.yaml" batch_result_file: str = "state/last_batch_result.csv" log_file: str = "state/run.log" @dataclass class BehaviorConfig: skip_if_user_exists: bool = True skip_missing_optional_groups: bool = True dry_run: bool = False require_ldaps_for_password: bool = True @dataclass class AppConfig: ldap: LdapConfig defaults: DefaultsConfig = field(default_factory=DefaultsConfig) paths: PathsConfig = field(default_factory=PathsConfig) behavior: BehaviorConfig = field(default_factory=BehaviorConfig) @dataclass class UserProcessResult: status: str reason: str = "" user_dn: str = "" uid_number: Optional[int] = None raw: Optional[Dict[str, str]] = None