johannes-ws opened a new issue, #34548:
URL: https://github.com/apache/superset/issues/34548
### Bug description
When i run this code,
import requests
import os
import json
# --- REQUIRED CONFIGURATION ---
SUPERSET_URL = os.getenv("SUPERSET_URL", "http://localhost:8088")
ADMIN_USERNAME = os.getenv("SUPERSET_USER", "admin")
ADMIN_PASSWORD = os.getenv("SUPERSET_PASSWORD", "admin")
# --- PROGRAM STUDY CODE MAPPING (KAPRODI) ---
# REQUIRED: Complete this dictionary with your data.
# Format: "short_program_name_from_role": numeric_program_code
KAPRODI_CODE_MAPPING = {
"if": 135,
"mesin": 131,
# "elektro": 133,
# Add all your kaprodi (program study) mappings here
}
def main():
"""Main function to run the automation process with CREATE or UPDATE
logic."""
# Use a session object to maintain login cookies, which are needed
for CSRF
with requests.Session() as session:
# 1. Authenticate and get CSRF token
print("1. Authenticating to Superset...")
try:
# Login
login_data = {"username": ADMIN_USERNAME, "password":
ADMIN_PASSWORD, "provider": "db"}
r_login =
session.post(f"{SUPERSET_URL}/api/v1/security/login", json=login_data)
r_login.raise_for_status()
access_token = r_login.json()["access_token"]
# Set headers for the entire session
session.headers.update({
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
})
print(" -> Authentication successful.")
# Get CSRF token
print(" -> Fetching CSRF token...")
r_csrf =
session.get(f"{SUPERSET_URL}/api/v1/security/csrf_token/")
r_csrf.raise_for_status()
csrf_token = r_csrf.json()['result']
# Add CSRF token to headers for all future state-changing
requests (POST, PUT, DELETE)
session.headers['X-CSRFToken'] = csrf_token
print(" -> CSRF token obtained.")
except requests.exceptions.RequestException as e:
print(f" -> FAILED during login/CSRF process: {e}")
return
# 2. Fetch all necessary data
print("\n2. Fetching data from Superset...")
params = {"q": json.dumps({"page_size": -1})}
try:
r_datasets = session.get(f"{SUPERSET_URL}/api/v1/dataset/",
params=params)
r_datasets.raise_for_status()
all_dataset_ids = [ds['id'] for ds in
r_datasets.json()['result']]
r_roles =
session.get(f"{SUPERSET_URL}/api/v1/security/roles/", params=params)
r_roles.raise_for_status()
roles_map = {role['name']: role['id'] for role in
r_roles.json()['result']}
# IMPORTANT CHANGE: Store the NAME and ID of existing rules
in a dictionary/map
r_rls =
session.get(f"{SUPERSET_URL}/api/v1/rowlevelsecurity/", params=params)
r_rls.raise_for_status()
existing_rules_map = {rule['name']: rule['id'] for rule in
r_rls.json()['result']}
print(f" -> Found {len(all_dataset_ids)} datasets,
{len(roles_map)} roles, and {len(existing_rules_map)} existing RLS rules.")
except requests.exceptions.RequestException as e:
print(f" -> FAILED to fetch data: {e}")
return
if not all_dataset_ids:
print("\nWARNING: No datasets found. No rules will be
created or updated.")
return
print("\n3. Processing roles and creating or updating RLS
rules...")
for role_name, role_id in roles_map.items():
rule_name = None
clause = None
# Logic to determine rule_name and clause remains the same
if role_name.lower().startswith('dekan ') and
role_name.lower() != 'dekan':
fakultas_code = role_name.split(' ', 1)[1].upper()
rule_name = f"Rule Dekan {fakultas_code}"
clause = f"kd_fak = '{fakultas_code}'"
elif role_name.lower().startswith('kaprodi ') and
role_name.lower() != 'kaprodi':
prodi_short_name = role_name.split(' ', 1)[1].lower()
prodi_code = KAPRODI_CODE_MAPPING.get(prodi_short_name)
if prodi_code:
rule_name = f"Rule Kaprodi
{prodi_short_name.upper()}"
clause = f"no_ps = {prodi_code}"
else:
if prodi_short_name: # Only print warning if there
is a name to warn about
print(f"\n- WARNING: No code mapping found for
'{prodi_short_name}'. Skipping role '{role_name}'.")
continue
# --- NEW LOGIC: CREATE OR UPDATE ---
if rule_name:
print(f"\n- Processing rule for role: '{role_name}'")
# This payload will be used for both creating (POST) and
updating (PUT)
payload = {
"name": rule_name,
"filter_type": "Regular",
"clause": clause,
"roles": [role_id],
"tables": all_dataset_ids,
"description": "Automatically created or updated by
Python script."
}
if rule_name in existing_rules_map:
# --- IF RULE EXISTS: PERFORM UPDATE (PUT) ---
rule_id_to_update = existing_rules_map[rule_name]
print(f" -> Rule '{rule_name}' exists (ID:
{rule_id_to_update}). Updating...")
try:
r_update =
session.put(f"{SUPERSET_URL}/api/v1/rowlevelsecurity/{rule_id_to_update}",
json=payload)
if r_update.status_code == 200:
print(f" -> SUCCESS: Rule updated.")
else:
print(f" -> FAILED to update. Status:
{r_update.status_code}, Message: {r_update.text}")
except requests.exceptions.RequestException as e:
print(f" -> FAILED due to an exception: {e}")
else:
# --- IF RULE DOES NOT EXIST: PERFORM CREATE (POST)
---
print(f" -> Rule '{rule_name}' does not exist.
Creating...")
try:
r_create =
session.post(f"{SUPERSET_URL}/api/v1/rowlevelsecurity/", json=payload)
if r_create.status_code == 201:
print(f" -> SUCCESS: Rule created.")
# Add the new rule to the map so we don't
try to re-create it in the same session
new_rule_id = r_create.json().get('id')
if new_rule_id:
existing_rules_map[rule_name] =
new_rule_id
else:
print(f" -> FAILED to create. Status:
{r_create.status_code}, Message: {r_create.text}")
except requests.exceptions.RequestException as e:
print(f" -> FAILED due to an exception: {e}")
print("\n4. Process finished.")
if __name__ == "__main__":
main()
i got an error message when try to update rules.
- Processing rule for role: 'Kaprodi Mesin'
-> Rule 'Rule Kaprodi MESIN' exists (ID: 12). Updating...
-> FAILED to update. Status: 201, Message: {
"id": 12,
"result": {
"clause": "no_ps = 131",
"description": "Automatically created or updated by Python script.",
"filter_type": "Regular",
"name": "Rule Kaprodi MESIN",
"roles": [
9
],
"tables": [
25,
20,
11,
17,
12,
10,
18,
2,
15,
13,
21,
5,
19,
24,
8,
6,
16,
4,
23,
1,
22,
3,
14,
9,
7
]
}
}
In https://superset.apache.org/docs/api, there is not response with code 201
at method put endpoint /api/v1/rowlevelsecurity/{pk}.
Anyone can help me?
### Screenshots/recordings
_No response_
### Superset version
5.0.0
### Python version
3.11
### Node version
18 or greater
### Browser
Chrome
### Additional context
_No response_
### Checklist
- [x] I have searched Superset docs and Slack and didn't find a solution to
my problem.
- [x] I have searched the GitHub issue tracker and didn't find a similar bug
report.
- [x] I have checked Superset's logs for errors and if I found a relevant
Python stacktrace, I included it here as text in the "additional context"
section.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]