diff --git a/generate_api_doc.py b/generate_api_doc.py index afc62902..3e232c5d 100755 --- a/generate_api_doc.py +++ b/generate_api_doc.py @@ -24,25 +24,30 @@ def main(): with open('action_map.yml') as f: action_map = yaml.load(f) - base_info = { + resource_list = { 'apiVersion': '0.1', 'swaggerVersion': '1.1', 'basePath': 'http://'+ domain + ':6767', 'apis': [] } - resource_list = base_info resources = {} del action_map['general_arguments'] for category, category_params in action_map.items(): if 'category_help' not in category_params: category_params['category_help'] = '' - resource_path = '/'+ category + resource_path = '/api/'+ category resource_list['apis'].append({ 'path': resource_path, 'description': category_params['category_help'] }) - resources[category] = base_info + resources[category] = { + 'apiVersion': '0.1', + 'swaggerVersion': '1.1', + 'basePath': 'http://'+ domain + ':6767', + 'apis': [] + } + resources[category]['resourcePath'] = resource_path registered_paths = {} @@ -66,37 +71,29 @@ def main(): operation = { 'httpMethod': method, 'nickname': category +'_'+ action, - 'responseClass': 'container', 'summary': action_params['action_help'], 'notes': notes, - 'parameters': [], 'errorResponses': [] } if 'arguments' in action_params: + operation['parameters'] = [] for arg_name, arg_params in action_params['arguments'].items(): if 'help' not in arg_params: arg_params['help'] = '' param_type = 'query' allow_multiple = False required = True - allowable_values = {} + allowable_values = None name = arg_name.replace('-', '_') - if name[0] == '-': + if name[0] == '_': required = False - if 'nargs' not in arg_params: - allow_multiple = False if 'full' in arg_params: name = arg_params['full'][2:] else: - name = arg_params[2:] + name = name[2:] name = name.replace('-', '_') - if name == key_param: - param_type = 'path' - required = True - allow_multiple = False - if 'nargs' in arg_params: if arg_params['nargs'] == '*': allow_multiple = True @@ -104,6 +101,8 @@ def main(): if arg_params['nargs'] == '+': allow_multiple = False required = True + else: + allow_multiple = False if 'choices' in arg_params: allowable_values = { 'valueType': 'LIST', @@ -112,18 +111,26 @@ def main(): if 'action' in arg_params and arg_params['action'] == 'store_true': allowable_values = { 'valueType': 'LIST', - 'values': ['true', 'True', 'yes', 'Yes'] + 'values': ['true', 'false'] } - operation['parameters'].append({ + if name == key_param: + param_type = 'path' + required = True + allow_multiple = False + + parameters = { 'paramType': param_type, 'name': name, 'description': arg_params['help'], 'dataType': 'string', 'required': required, - 'allowableValues': allowable_values, 'allowMultiple': allow_multiple - }) + } + if allowable_values is not None: + parameters['allowableValues'] = allowable_values + + operation['parameters'].append(parameters) if path in registered_paths: @@ -138,15 +145,13 @@ def main(): }) - #for category, api_dict in resources.items(): - # with open(os.getcwd() +'/doc/'+ category +'.json', 'w') as f: - # json.dump(api_dict, f) + for category, api_dict in resources.items(): + with open(os.getcwd() +'/doc/'+ category +'.json', 'w') as f: + json.dump(api_dict, f) - #with open(os.getcwd() +'/doc/resources.json', 'w') as f: - # json.dump(resource_list, f) - # - - print resource_list + with open(os.getcwd() +'/doc/resources.json', 'w') as f: + json.dump(resource_list, f) + if __name__ == '__main__': sys.exit(main()) diff --git a/ldap_scheme.yml b/ldap_scheme.yml index adcd46b7..75bdea6e 100644 --- a/ldap_scheme.yml +++ b/ldap_scheme.yml @@ -22,6 +22,11 @@ parents: objectClass: - organizationalUnit - top + ou=sudo: + ou: sudo + objectClass: + - organizationalUnit + - top children: cn=admins,ou=groups: @@ -40,3 +45,12 @@ children: - posixGroup - top + cn=admin,ou=sudo: + cn: admin + sudoUser: admin + sudoHost: ALL + sudoCommand: ALL + sudoOption: "!authenticate" + objectClass: + - sudoRole + - top diff --git a/sudo_ldap_scheme.yml b/sudo_ldap_scheme.yml deleted file mode 100644 index 546e03f5..00000000 --- a/sudo_ldap_scheme.yml +++ /dev/null @@ -1,26 +0,0 @@ -parents: - ou=sudo: - ou: sudo - objectClass: - - organizationalUnit - - top -children: - cn=admin,ou=sudo: - cn: admin - sudoUser: admin - sudoHost: ALL - sudoCommand: ALL - sudoOption: "!authenticate" - objectClass: - - sudoRole - - top - - cn=yunohost-admin,ou=sudo: - cn: yunohost-admin - sudoUser: yunohost-admin - sudoHost: ALL - sudoCommand: /usr/bin/yunohost - sudoOption: "!authenticate" - objectClass: - - sudoRole - - top diff --git a/yunohost.tac b/yunohost.tac index 32bf9da5..656d6bd7 100755 --- a/yunohost.tac +++ b/yunohost.tac @@ -30,16 +30,20 @@ def http_exec(request, **kwargs): # Return OK to 'OPTIONS' xhr requests if request.method == 'OPTIONS': request.setResponseCode(200, 'OK') - request.setHeader('Access-Control-Allow-Headers', 'Authorization') + request.setHeader('Access-Control-Allow-Headers', 'Authorization, Content-Type') + request.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') return '' # Simple HTTP auth else: authorized = request.getUser() == 'admin' + pwd = request.getPassword() + if 'api_key' in request.args: + pwd = request.args['api_key'][0] + authorized = True if authorized: - try: YunoHostLDAP(password=request.getPassword()) + try: YunoHostLDAP(password=pwd) except YunoHostError: authorized = False - if not authorized: request.setResponseCode(401, 'Unauthorized') request.setHeader('Access-Control-Allow-Origin', '*') @@ -69,10 +73,11 @@ def http_exec(request, **kwargs): if 'nargs' not in params: possible_args[arg]['nargs'] = '*' if 'full' in params: - new_key = params['full'][2:].replace('-', '_') + new_key = params['full'][2:] else: - new_key = arg[2:].replace('-', '_') - possible_args[new_key] = possible_args[arg] + new_key = arg[2:] + new_key = new_key.replace('-', '_') + possible_args[new_key] = possible_args[arg] del possible_args[arg] try: @@ -128,17 +133,49 @@ def http_exec(request, **kwargs): return json.dumps(result) +def api_doc(request): + request.setHeader('Access-Control-Allow-Origin', '*') # Allow cross-domain requests + request.setHeader('Content-Type', 'application/json') # Return JSON anyway + + # Return OK to 'OPTIONS' xhr requests + if request.method == 'OPTIONS': + request.setResponseCode(200, 'OK') + request.setHeader('Access-Control-Allow-Headers', 'Authorization') + return '' + + if request.path == '/api': + with open('doc/resources.json') as f: + return f.read() + + category = request.path.split('/')[2] + try: + with open('doc/'+ category +'.json') as f: + return f.read() + except IOError: + return '' + +def favicon(request): + request.setHeader('Access-Control-Allow-Origin', '*') # Allow cross-domain requests + request.setResponseCode(404, 'Not Found') + return '' def main(): global action_dict global api + # Register API doc service + api.register('ALL', '/api', api_doc) + + # favicon.ico error + api.register('ALL', '/favicon.ico', favicon) + # Load & parse yaml file with open('action_map.yml') as f: action_map = yaml.load(f) del action_map['general_arguments'] for category, category_params in action_map.items(): + api.register('ALL', '/api/'+ category, api_doc) for action, action_params in category_params['actions'].items(): if 'action_help' not in action_params: action_params['action_help'] = ''