Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dodo.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ def uniquify_file(filename):
)
)
else:
print("Saved {} sorted unique lines to {}".format(len(uniques), filename))
print("Saved {} sorted unique lines to {}".format(len(unique_lines), filename))


def task_clean_all():
Expand Down
2 changes: 1 addition & 1 deletion tabcmd/commands/user/create_site_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def run_command(cls, args):
if args.role:
user_obj.site_role = args.role # tsc is case sensitive
if args.auth_type:
user_obj.auth_setting = args.auth_type
user_obj.auth_setting = UserCommand.normalize_auth_setting(args.auth_type, user_obj.name)
number_of_users_listed += 1
result = server.users.add(user_obj)
logger.info(_("common.output.succeeded").format(user_obj.name))
Expand Down
2 changes: 1 addition & 1 deletion tabcmd/commands/user/create_users_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def run_command(cls, args):
if args.role:
user_obj.site_role = args.role
if args.auth_type:
user_obj.auth_setting = args.auth_type
user_obj.auth_setting = UserCommand.normalize_auth_setting(args.auth_type, user_obj.name)
server.users.add(user_obj)
logger.info(_("common.output.succeeded").format(user_obj.name))
number_of_users_added += 1
Expand Down
17 changes: 16 additions & 1 deletion tabcmd/commands/user/user_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def to_tsc_user(self) -> TSC.UserItem:
site_role = UserCommand.evaluate_site_role(self.license_level, self.admin_level, self.publisher)
if not site_role:
raise AttributeError(_("tabcmd.user.error.site_role_required"))
user = TSC.UserItem(self.name, site_role, self.auth)
auth = UserCommand.normalize_auth_setting(self.auth, self.name)
user = TSC.UserItem(self.name, site_role, auth)
user.email = self.email
user.fullname = self.fullname
return user
Expand Down Expand Up @@ -104,6 +105,20 @@ class UserCommand(Server):
This class acts as a base class for user related group of commands
"""

# tabcmd Classic accepts "Local" as an auth type; TSC's UserItem.Auth enum
# has no Local value and rejects it. Map Classic's "Local" to ServerDefault
# (both for CSV values and for the CLI --auth-type override) so inputs
# authored for Classic import without crashing, and log a warning so the
# operator sees the remap happened.
@staticmethod
def normalize_auth_setting(auth, username: Optional[str] = None):
if isinstance(auth, str) and auth.lower() == "local":
logging.getLogger(__name__).warning(
_("tabcmd.user.warning.local_auth_remapped").format(username)
)
Comment on lines +116 to +118
return TSC.UserItem.Auth.ServerDefault
return auth

@staticmethod
def set_role_arg(parser):
parser.add_argument(
Expand Down
Binary file modified tabcmd/locales/de/LC_MESSAGES/tabcmd.mo
Binary file not shown.
Binary file modified tabcmd/locales/en/LC_MESSAGES/tabcmd.mo
Binary file not shown.
1 change: 1 addition & 0 deletions tabcmd/locales/en/tabcmd_messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ tabcmd.status.job_completed=Job completed
tabcmd.status.waiting_for_refresh_job=Waiting for refresh job to begin
tabcmd.user.error.site_role_required=Site role is required
tabcmd.user.help.auth_type=Assigns the authentication type for all users in the CSV file. Possible values:
tabcmd.user.warning.local_auth_remapped=User '{0}': auth_setting 'Local' is not a Tableau Server auth type; mapped to ServerDefault. The site's default auth method will be used.
tabcmd.user.help.site_role=Specifies a site role for all users in the .csv file. Possible roles:
tabcmd.warning.calculations_not_supported=Adding or removing Calculations tasks are not supported
tabcmdparser.global.behaviors=Global behaviors:
Expand Down
Binary file modified tabcmd/locales/es/LC_MESSAGES/tabcmd.mo
Binary file not shown.
Binary file modified tabcmd/locales/fr/LC_MESSAGES/tabcmd.mo
Binary file not shown.
Binary file modified tabcmd/locales/ga/LC_MESSAGES/tabcmd.mo
Binary file not shown.
Binary file modified tabcmd/locales/it/LC_MESSAGES/tabcmd.mo
Binary file not shown.
Binary file modified tabcmd/locales/ja/LC_MESSAGES/tabcmd.mo
Binary file not shown.
Binary file modified tabcmd/locales/ko/LC_MESSAGES/tabcmd.mo
Binary file not shown.
Binary file modified tabcmd/locales/pt/LC_MESSAGES/tabcmd.mo
Binary file not shown.
Binary file modified tabcmd/locales/sv/LC_MESSAGES/tabcmd.mo
Binary file not shown.
Binary file modified tabcmd/locales/zh/LC_MESSAGES/tabcmd.mo
Binary file not shown.
29 changes: 29 additions & 0 deletions tests/commands/test_user_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,32 @@ def test_parse_line_preserves_role(self):
user = UserCommand._parse_line("username, pword, fname, creator, none, yes, email")
assert user is not None
assert user.site_role == "Creator", f"Expected Creator, got {user.site_role}"

def test_local_auth_maps_to_server_default(self):
# tabcmd Classic accepts "Local" as an auth type; TSC's Auth enum has no
# Local value, so passing it through raises ValueError on server.users.add.
# to_tsc_user should map Classic's "Local" -> ServerDefault for parity
# and log a warning so the operator sees the remap happened.
data = Userdata()
data.populate(["username", "pword", "fname", "creator", "none", "yes", "email", "Local"])
with self.assertLogs("tabcmd.commands.user.user_data", level="WARNING") as logs:
user = data.to_tsc_user()
assert user.auth_setting == TSC.UserItem.Auth.ServerDefault, user.auth_setting
# Assert the warning names the affected user so the operator can act on
# it. Avoid coupling to the localize key -- once the .mo catalog carries
# this msgid, `_()` returns the translated text instead of the key.
assert any("username" in msg for msg in logs.output), logs.output

def test_local_auth_case_insensitive(self):
data = Userdata()
data.populate(["username", "pword", "fname", "creator", "none", "yes", "email", "local"])
with self.assertLogs("tabcmd.commands.user.user_data", level="WARNING"):
user = data.to_tsc_user()
assert user.auth_setting == TSC.UserItem.Auth.ServerDefault, user.auth_setting

def test_non_local_auth_passes_through(self):
# SAML/OpenID/etc. are not remapped.
data = Userdata()
data.populate(["username", "pword", "fname", "creator", "none", "yes", "email", TSC.UserItem.Auth.SAML])
user = data.to_tsc_user()
assert user.auth_setting == TSC.UserItem.Auth.SAML, user.auth_setting
Loading