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
11 changes: 10 additions & 1 deletion tabcmd/commands/user/user_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,16 @@ 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)
# 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
# so CSVs authored for Classic import without crashing.
auth = self.auth
if isinstance(auth, str) and auth.lower() == "local":
logging.getLogger(__name__).warning(
_("tabcmd.user.warning.local_auth_remapped").format(self.name)
)
auth = TSC.UserItem.Auth.ServerDefault
user = TSC.UserItem(self.name, site_role, auth)
user.email = self.email
user.fullname = self.fullname
return user
Expand Down
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
28 changes: 28 additions & 0 deletions tests/commands/test_user_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,31 @@ 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
# In tests the gettext catalog isn't loaded, so `_()` returns the raw key;
# we just assert the localize key made it to the log record.
assert any("local_auth_remapped" 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