-
Notifications
You must be signed in to change notification settings - Fork 0
Update FHOW notebooks due to org-linked groups #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
WORKBENCH_USER_EMAIL,POLICY | ||
WORKBENCH_USER_EMAIL,ROLE | ||
[email protected],MEMBER | ||
[email protected],MEMBER | ||
[email protected],MEMBER |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import json | ||
import subprocess | ||
import sys | ||
|
||
def get_org_linked_group_roles(org_id, group_name): | ||
""" | ||
Return a flattened mapping of users to roles for a named org-linked group and org ID. | ||
""" | ||
roles_dict = {role: set() for role in ["ADMIN", "MEMBER", "READER", "SUPPORT"]} | ||
|
||
wb_command = ["wb","group","role","list",f"--org={org_id}",f"--name={group_name}","--format=JSON"] | ||
result = subprocess.run(wb_command,capture_output=True,text=True) | ||
nested_roles = json.loads(result.stdout) | ||
|
||
for item in nested_roles: | ||
if item['principal']['principalType'] == "GROUP": | ||
roles_dict[role].update(get_org_linked_group_roles(item['principal']['groupOrg'], item['principal']['groupName'])["MEMBER"]) | ||
else: | ||
for role in item['roles']: | ||
if item['principal']['userEmail'] != None: | ||
roles_dict[role].add(item['principal']['userEmail']) | ||
|
||
return roles_dict | ||
|
||
def get_flat_roles_html(roles_dict): | ||
html = f"""<table style='margin: 0 auto,text-align: left'>""" | ||
html += "<th>ROLE</th>" | ||
html += "<th>USER_EMAILS</th>" | ||
html += "<tr>" | ||
for role in roles_dict: | ||
html += "<tr>" | ||
if roles_dict[role] != set(): | ||
print(f"role: {role}, users: {roles_dict[role]}") | ||
users = ", ".join(str(e) for e in sorted(roles_dict[role])) | ||
html += f"<td>{role}</td>" | ||
html += f"<td>{users}</td>" | ||
else: | ||
html += f"<td>{role}</td>" | ||
html += f"<td>NONE</td>" | ||
html += "</table>" | ||
return html |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,25 +40,24 @@ def list_bq_tables(json_string): | |
for table in tables: | ||
all_tables.append(f"{row['projectId']}.{row['datasetId']}.{table.table_id}") | ||
return all_tables | ||
|
||
|
||
def list_groups(json_string): | ||
def list_legacy_groups(json_string): | ||
""" List VWB groups in which user is a member in HTML table form. | ||
""" | ||
html = f"""<table style='margin: 0 auto,text-align: left'>""" | ||
json_data = json.loads(json_string) | ||
# html += "<th>ORG_ID</th>" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this communicating intent of some kind, or a stray comment? there are a few similar commented-out html strings below |
||
html += "<th>NAME</th>" | ||
html += "<th>EMAIL</th>" | ||
html += "<th>POLICIES</th>" | ||
html += "<th>CURRENT_USER_ROLES</th>" | ||
for row in json_data: | ||
html += "<tr>" | ||
html += f"<td>{row['name']}</td>" | ||
html += f"<td>{row['email']}</td>" | ||
html += f"<td>{row['currentUserPolicies'][0]}</td>" | ||
if not row['orgId']: | ||
html += "<tr>" | ||
html += f"<td>{row['name']}</td>" | ||
html += f"<td>{sorted(row['currentUserRoles'])}</td>" | ||
html += "</table>" | ||
return html | ||
|
||
def list_group_members(json_string): | ||
def list_legacy_group_members(json_string): | ||
""" | ||
List members of a VWB group in HTML table form. | ||
""" | ||
|
@@ -69,10 +68,29 @@ def list_group_members(json_string): | |
for row in json_data: | ||
html += "<tr>" | ||
html += f"<td>{row['email']}</td>" | ||
html += f"<td>{row['policies'][0]}</td>" | ||
html += f"<td>{sorted(row['policies'])}</td>" | ||
html += "</table>" | ||
return html | ||
|
||
|
||
def list_org_groups(json_string): | ||
""" List VWB groups in which user is a member in HTML table form. | ||
""" | ||
html = f"""<table style='margin: 0 auto,text-align: left'>""" | ||
json_data = json.loads(json_string) | ||
html += "<th>ORG_ID</th>" | ||
html += "<th>NAME</th>" | ||
# html += "<th>CURRENT_USER_ROLES</th>" | ||
for row in json_data: | ||
if row['orgId'] != 'null': | ||
html += "<tr>" | ||
html += f"<td>{row['orgId']}</td>" | ||
html += f"<td>{row['name']}</td>" | ||
# html += f"<td>{sorted(row['currentUserRoles'])}</td>" | ||
html += "</table>" | ||
return html | ||
|
||
|
||
def list_data_collections(json_string): | ||
""" | ||
Given the output of the command `wb workspace list`, | ||
|
@@ -149,6 +167,32 @@ def get(self): | |
return self.dropdown_widget | ||
|
||
|
||
@dataclass | ||
class BoundIntInputWidget: | ||
"""A styled input accepting bounded integers widget with layout. | ||
""" | ||
default_value: int = 0 | ||
min_value: int = 0 | ||
max_value: int = 0 | ||
description: str = "" | ||
bound_int_widget: widgets.BoundedIntText = None | ||
|
||
def __post_init__(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. neato. I didn't know about this function |
||
self.bound_int_widget = widgets.BoundedIntText( | ||
value=self.default_value, | ||
min=self.min_value, | ||
max=self.max_value, | ||
step=1, | ||
description=self.description, | ||
disabled=False, | ||
layout = {'width' : 'max-content'}, | ||
style=input_style | ||
) | ||
|
||
def get(self): | ||
'''Return widget.''' | ||
return self.bound_int_widget | ||
|
||
@dataclass | ||
class StyledButton(): | ||
""" A styled button widget with layout. | ||
|
@@ -162,7 +206,7 @@ def __post_init__(self): | |
self.button = widgets.Button( | ||
description=self.description, | ||
disabled=False, | ||
layout=widgets.Layout(width='75%'), | ||
layout=widgets.Layout(width='100%'), | ||
display='flex', | ||
align_items='stretch', | ||
button_style='', | ||
|
@@ -203,3 +247,20 @@ def __init__(self): | |
def get(self): | ||
'''Return widget.''' | ||
return self.checkbox | ||
|
||
|
||
class LongLabelCheckbox: | ||
""" Creates a styled checkbox. | ||
""" | ||
def __init__(self, description): | ||
self.checkbox = widgets.Checkbox( | ||
False, | ||
description = description, | ||
layout = {'width' : 'max-content'}, | ||
disabled = False, | ||
indent = False | ||
) | ||
|
||
def get(self): | ||
'''Return widget.''' | ||
return self.checkbox |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whenever I have to do something like this (construct html from strings) I wonder if there's a better way...
not asking for a change -- I think this is perfectly fine in small doses. just musing that it might be worth some thought someday.