Skip to content
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

fix: jans-cli fixes #2429

Merged
merged 13 commits into from
Sep 28, 2022
Merged
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
62 changes: 44 additions & 18 deletions jans-cli/cli/config_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
config_dir.mkdir(parents=True, exist_ok=True)
config_ini_fn = config_dir.joinpath('jans-cli.ini')
cur_dir = os.path.dirname(os.path.realpath(__file__))
log_dir = os.environ.get('cli_log_dir', cur_dir)
sys.path.append(cur_dir)

from pylib.tabulate.tabulate import tabulate
Expand All @@ -43,6 +44,7 @@
'jca.get-all-attribute': ['inum', 'name', 'displayName', 'status', 'dataType', 'claimName'],
'jca.get-oauth-openid-clients': ['inum', 'displayName', 'clientName', 'applicationType'],
'jca.get-oauth-scopes': ['dn', 'id', 'scopeType'],
'jca.get-oauth-uma-resources': ['dn', 'name', 'expirationDate'],
'scim.get-users': ['id', 'userName', 'displayName', 'active']
}

Expand Down Expand Up @@ -73,8 +75,6 @@
client_secret = os.environ.get(my_op_mode + 'jca_client_secret')
access_token = None
debug = os.environ.get('jans_client_debug')
debug_log_file = os.environ.get('jans_debug_log_file')
error_log_file = os.path.join(cur_dir, 'error.log')

def encode_decode(s, decode=False):
cmd = '/opt/jans/bin/encode.py '
Expand Down Expand Up @@ -114,7 +114,6 @@ def join(self):
parser.add_argument("--access-token", help="JWT access token or path to file containing JWT access token")
parser.add_argument("--plugins", help="Available plugins separated by comma")
parser.add_argument("-debug", help="Run in debug mode", action='store_true')
parser.add_argument("--debug-log-file", default='swagger.log', help="Log file name when run in debug mode")
parser.add_argument("--operation-id", help="Operation ID to be done")
parser.add_argument("--url-suffix", help="Argument to be added api endpoint url. For example inum:2B29")
parser.add_argument("--info", choices=op_list, help="Help for operation")
Expand All @@ -136,11 +135,18 @@ def join(self):
parser.add_argument("--patch-replace", help="Colon delimited key:value pair for replace patch operation. For example loggingLevel:DEBUG")
parser.add_argument("--patch-remove", help="Key for remove patch operation. For example imgLocation")
parser.add_argument("--no-suggestion", help="Do not use prompt toolkit to display word completer", action='store_true')
parser.add_argument("-log-dir", help="Do not use prompt toolkit to display word completer", default=log_dir)


# parser.add_argument("-show-data-type", help="Show data type in schema query", action='store_true')
parser.add_argument("--data", help="Path to json data file")
args = parser.parse_args()

if args.config_api_mtls_client_cert and args.config_api_mtls_client_key:
excluded_operations['jca'] += [
'get-user', 'post-user', 'put-user', 'get-user-by-inum', 'delete-user', 'patch-user-by-inum',
'get-properties-fido2', 'put-properties-fido2', 'get-registration-entries-fido2',
]

if not args.no_suggestion:
from prompt_toolkit import prompt, HTML
Expand All @@ -165,7 +171,6 @@ def write_config():
client_id = args.client_id
client_secret = args.client_secret
debug = args.debug
debug_log_file = args.debug_log_file

access_token = args.access_token
if access_token and os.path.isfile(access_token):
Expand Down Expand Up @@ -194,7 +199,8 @@ def write_config():
client_secret = encode_decode(client_secret_enc, decode=True)

debug = config['DEFAULT'].get('debug')
debug_log_file = config['DEFAULT'].get('debug_log_file')
log_dir = config['DEFAULT'].get('log_dir', log_dir)

else:
config['DEFAULT'] = {'jans_host': 'jans server hostname,e.g, jans.foo.net',
'jca_client_id': 'your jans config api client id',
Expand Down Expand Up @@ -309,7 +315,7 @@ def __init__(self, host, client_id, client_secret, access_token, test_client=Fal

self.swagger_configuration.debug = debug
if self.swagger_configuration.debug:
self.swagger_configuration.logger_file = debug_log_file
self.swagger_configuration.logger_file = os.path.join(log_dir, 'swagger.log')

self.swagger_yaml_fn = os.path.join(cur_dir, my_op_mode + '.yaml')

Expand Down Expand Up @@ -793,10 +799,14 @@ def get_input(self, values=[], text='Selection', default=None, itype=None,
print(' ' * spacing, self.colored_text('«{}»'.format(help_text), 244), sep='')

if example:
join_char = '_,' if itype == 'array' else ', '
if isinstance(example, list):
example_str = ', '.join(example)
example_str = join_char.join(example)
else:
example_str = str(example)
if join_char == '_,':
example_str = example_str.replace(' ', join_char)

print(' ' * spacing, self.colored_text('Example: {}'.format(example_str), 244), sep='')

if not default is None:
Expand All @@ -820,6 +830,11 @@ def get_input(self, values=[], text='Selection', default=None, itype=None,
selection = prompt(HTML(' ' * spacing + text + ' '), completer=html_completer)

selection = selection.strip()

if selection == '_b':
self.display_menu(self.current_menu)
break

if selection.startswith('_file '):
fname = selection.split()[1]
if os.path.isfile(fname):
Expand Down Expand Up @@ -1190,24 +1205,24 @@ def process_get(self, endpoint, return_value=False, parameters=None):
elif attrib['name'] in tabulate_endpoints[op_mode_endpoint]:
entry[attrib['name']] = attrib['values'][0]

elif endpoint.info['operationId'] == 'get-all-attribute':
if 'data' in api_response_unmapped_ext:
api_response_unmapped_ext = api_response_unmapped_ext['data']

elif endpoint.info['operationId'] == 'get-oauth-openid-clients':
if 'entries' in api_response_unmapped_ext:
api_response_unmapped_ext = api_response_unmapped_ext['entries']

if endpoint.info['operationId'] == 'get-oauth-openid-clients':
for entry in api_response_unmapped_ext:
if entry.get('displayName'):
break
for custom_attrib in entry.get('customAttributes', []):
if custom_attrib.get('name') == 'displayName':
entry['displayName'] = custom_attrib.get('value') or custom_attrib.get('values',['?'])[0]
break
if isinstance(entry['clientName'], dict) and 'value' in entry['clientName']:
entry['clientName'] = entry['clientName']['value']

tab_data = api_response_unmapped_ext
if op_mode_endpoint in tabular_dataset:
tab_data = api_response_unmapped_ext[tabular_dataset[op_mode_endpoint]]
self.tabular_data(tab_data, op_mode_endpoint)
item_counters = [str(i + 1) for i in range(len(api_response_unmapped))]
item_counters = [str(i + 1) for i in range(len(tab_data))]
tabulated = True
else:
self.print_colored_output(api_response_unmapped)
Expand All @@ -1230,8 +1245,8 @@ def process_get(self, endpoint, return_value=False, parameters=None):
elif selection in item_counters:
if my_op_mode == 'scim' and 'Resources' in api_response_unmapped:
items = api_response_unmapped['Resources']
elif my_op_mode == 'jca' and 'data' in api_response_unmapped:
items = api_response_unmapped['data']
elif my_op_mode == 'jca' and 'entries' in api_response_unmapped:
items = api_response_unmapped['entries']
self.pretty_print(items[int(selection) - 1])

def get_schema_from_reference(self, ref):
Expand Down Expand Up @@ -1480,6 +1495,7 @@ def process_post(self, endpoint):
if not field in required_fields:
optional_fields.append(field)

optional_fields.sort()
if optional_fields:
fill_optional = self.get_input(values=['y', 'n'], text='Populate optional fields?')
fields_numbers = []
Expand Down Expand Up @@ -1559,7 +1575,6 @@ def process_delete(self, endpoint):
self.display_menu(endpoint.parent)

def process_patch(self, endpoint):

if endpoint.info['operationId'] == 'patch-user-by-inum':
schema = self.cfg_yml['components']['schemas']['CustomAttribute'].copy()
schema['__schema_name__'] = 'CustomAttribute'
Expand All @@ -1576,6 +1591,12 @@ def process_patch(self, endpoint):
schema['__schema_name__'] = 'PatchRequest'
model = getattr(swagger_client.models, 'PatchRequest')

parent_schema = {}

schema_ref = endpoint.info.get('responses', {}).get('200', {}).get('content', {}).get('application/json', {}).get('schema', {}).get('$ref')
if schema_ref:
parent_schema = self.get_schema_from_reference(schema_ref)

url_param_val = None
url_param = self.get_endpiont_url_param(endpoint)
if 'name' in url_param:
Expand All @@ -1597,6 +1618,11 @@ def process_patch(self, endpoint):
if my_op_mode == 'scim':
data.path = data.path.replace('/', '.')

if parent_schema and 'properties' in parent_schema:
for prop_ in parent_schema['properties']:
if data.path.lstrip('/') == prop_:
if parent_schema['properties'][prop_]['type'] == 'array':
data.value = data.value.split('_,')
body.append(data)
selection = self.get_input(text='Another patch operation?', values=['y', 'n'])
if selection == 'n':
Expand Down Expand Up @@ -2304,7 +2330,7 @@ def runApp(self):
def main():

cli_object = JCA_CLI(host, client_id, client_secret, access_token, test_client)

error_log_file = os.path.join(log_dir, 'error.log')
try:
if not access_token:
cli_object.check_connection()
Expand Down