| 153 | |
| 154 | @dataclass |
| 155 | class User: |
| 156 | username: str |
| 157 | password: Password |
| 158 | sudo: bool |
| 159 | groups: list[str] = field(default_factory=list) |
| 160 | |
| 161 | @override |
| 162 | def __str__(self) -> str: |
| 163 | # safety overwrite to make sure password is not leaked |
| 164 | return f'User({self.username=}, {self.sudo=}, {self.groups=})' |
| 165 | |
| 166 | def table_data(self) -> dict[str, str | bool | list[str]]: |
| 167 | return { |
| 168 | 'username': self.username, |
| 169 | 'password': self.password.hidden(), |
| 170 | 'sudo': self.sudo, |
| 171 | 'groups': self.groups, |
| 172 | } |
| 173 | |
| 174 | def json(self) -> UserSerialization: |
| 175 | return { |
| 176 | 'username': self.username, |
| 177 | 'enc_password': self.password.enc_password, |
| 178 | 'sudo': self.sudo, |
| 179 | 'groups': self.groups, |
| 180 | } |
| 181 | |
| 182 | @classmethod |
| 183 | def parse_arguments( |
| 184 | cls, |
| 185 | args: list[UserSerialization], |
| 186 | ) -> list[Self]: |
| 187 | users = [] |
| 188 | |
| 189 | for entry in args: |
| 190 | username = entry.get('username') |
| 191 | password: Password | None = None |
| 192 | groups = entry.get('groups', []) |
| 193 | plaintext = entry.get('!password') |
| 194 | enc_password = entry.get('enc_password') |
| 195 | |
| 196 | # DEPRECATED: backwards compatibility |
| 197 | if plaintext: |
| 198 | password = Password(plaintext=plaintext) |
| 199 | elif enc_password: |
| 200 | password = Password(enc_password=enc_password) |
| 201 | |
| 202 | if not username or password is None: |
| 203 | continue |
| 204 | |
| 205 | user = cls( |
| 206 | username=username, |
| 207 | password=password, |
| 208 | sudo=entry.get('sudo', False) is True, |
| 209 | groups=groups, |
| 210 | ) |
| 211 | |
| 212 | users.append(user) |
no outgoing calls