def upload_images_route(): """ Upload images Request params: * Files uploaded as "multipart/form-data" Field names don't matter. Multiple files are supported """ user = request.get('REMOTE_USER') files = [ item.file for _, item in request.POST.items() if isinstance(item, FileUpload) ] try: assert files, "Files were not provided" if len(list(get_user_images(user))) + len(files) > max_images_per_uer: raise MaxImageLimitError('You cannot upload more than %s images' % max_images_per_uer) urls = upload_images(user, files) return {'data': urls} except (AssertionError, MaxImageLimitError) as e: return ErrorResponse(e, 400) except FileTooLargeError as e: return ErrorResponse(e, 413)
def get_extensions_route(): """ Returns all extensions Query params: * api_version: string. Version of Ulauncher Extension API. Returns all extensions by default """ result = [] # filter by required API version api_version = request.GET.get('api_version') try: sort_by = request.GET.get('sort_by') or allowed_sort_by[0] sort_order = request.GET.get('sort_order') or allowed_sort_order[0] assert sort_by in allowed_sort_by, 'allowed sorty_by: ' + ', '.join( allowed_sort_by) assert sort_order in allowed_sort_order, 'allowed sort_order: ' + ', '.join( map(str, allowed_sort_order)) except AssertionError as e: return ErrorResponse(e, 400) for ext in get_extensions(sort_by=sort_by, sort_order=int(sort_order)): if not api_version: result.append(ext) for req_version in ext.get('SupportedVersions', []): if satisfies(api_version, req_version): result.append(ext) return {'data': result}
def create_extension_route(): """ Create extension Request params: * GithubUrl: (string) * Name: (string) extension display name * Description: (string) * DeveloperName: (string) * Images: (list) list of image URLs Response: * Extension object """ user = request.get('REMOTE_USER') data = request.json try: assert data.get('Name'), 'Name cannot be empty' assert data.get('Description'), 'Description cannot be empty' assert data.get('DeveloperName'), 'DeveloperName cannot be empty' assert data.get('GithubUrl'), 'GithubUrl cannot be empty' assert isinstance(data.get('Images'), list), 'Images must be a list of URLs' # pylint: disable=len-as-condition assert 0 < len( data['Images'] ) < 6, 'You must upload at least 1 (max 5) screenshot of your extension' project_path = get_project_path(data['GithubUrl']) info = get_repo_info(project_path) try: versions = get_json(project_path, 'master', 'versions') versions_only = [v['required_api_version'] for v in versions] commit_or_branch = get_latest_version_commit(versions) except JsonFileNotFoundError: commit_or_branch = 'master' versions_only = ['^1.0.0'] manifest = get_json(project_path, commit_or_branch, 'manifest') validate_manifest(manifest) for image_url in data['Images']: validate_image_url(image_url) data = put_extension(User=user, GithubUrl=data['GithubUrl'], ProjectPath=project_path, Name=data['Name'], Description=data['Description'], DeveloperName=data['DeveloperName'], Images=data['Images'], SupportedVersions=versions_only, GithubStars=info['stargazers_count'], Published=True) return {'data': data} except (AssertionError, ImageUrlValidationError, InvalidGithubUrlError, HTTPError, ProjectValidationError, ExtensionAlreadyExistsError) as e: return ErrorResponse(e, 400)
def update_extension_route(id): """ Update extension Request params: * Name: (string) extension display name * Description: (string) * DeveloperName: (string) * Images: (list) list of image URLs Response: * Extension object """ user = request.get('REMOTE_USER') data = request.json try: ext = _verify_ext_auth(id) assert data.get('Name'), 'Name cannot be empty' assert data.get('Description'), 'Description cannot be empty' assert data.get('DeveloperName'), 'DeveloperName cannot be empty' assert isinstance(data.get('Images'), list), 'Images must be a list of URLs' # pylint: disable=len-as-condition assert 0 < len( data['Images'] ) < 6, 'You must upload at least 1 (max 5) screenshot of your extension' for image_url in data['Images']: validate_image_url(image_url) to_delete = set(ext['Images']) - set(data['Images']) delete_images(to_delete, user) data = update_extension(id, Name=data['Name'], Description=data['Description'], DeveloperName=data['DeveloperName'], Images=data['Images']) return {'data': data} except ExtensionNotFoundError as e: return ErrorResponse(e, 404) except (AssertionError, ImageUrlValidationError) as e: return ErrorResponse(e, 400) except AuthError as e: return ErrorResponse(e, 401)
def get_extension_route(id): """ Returns extension by ID """ try: return {'data': get_extension(id)} except ExtensionNotFoundError as e: return ErrorResponse(e, 404)
def validate_project(): """ Checks that versions.json file is valid Query params: * url: string. Example https://github.com/user/project Response: * {Name: (str), Description: (str), DeveloperName: (str)} """ try: url = request.GET.get('url') assert url, 'query argument "url" cannot be empty' project_path = get_project_path(url) get_repo_info(project_path) try: versions = get_json(project_path, 'master', 'versions') commit_or_branch = get_latest_version_commit(versions) except JsonFileNotFoundError: commit_or_branch = 'master' except json.JSONDecodeError as e: return ErrorResponse( ProjectValidationError(f'Error in versions.json: {str(e)}'), 400) manifest = get_json(project_path, commit_or_branch, 'manifest') validate_manifest(manifest) return { 'data': { 'GithubUrl': url, 'Name': manifest['name'], 'Description': manifest['description'], 'DeveloperName': manifest['developer_name'], } } except json.JSONDecodeError as e: return ErrorResponse( ProjectValidationError(f'Error in manifest.json: {str(e)}'), 400) except (InvalidGithubUrlError, HTTPError, ProjectValidationError, AssertionError) as e: return ErrorResponse(e, 400)
def delete_extension_route(id): """ Deletes extension by ID """ user = request.get('REMOTE_USER') try: ext = _verify_ext_auth(id) delete_images(ext['Images'], user) delete_extension(id, user=user) response.status = 204 except (ExtensionDoesntBelongToUserError, AuthError) as e: return ErrorResponse(e, 401)
def wrapper(*args, **kwargs): if hasattr(callback, 'auth_required') and not request.get('REMOTE_USER'): try: decoded = parse_token(request.get_header('Authorization')) assert decoded['sub'] except AuthError as e: return ErrorResponse(e, 401) request['REMOTE_USER'] = decoded['sub'] return callback(*args, **kwargs)
def get_ulauncher_release(version): """ Fetches Ulauncher release from Github by given git tag (version) Note: This is necessary because Github API limits number of unauthenticated requests and it often blocks IPs that Travis CI uses, so Ulauncher releases could fail """ headers = {'User-Agent': 'curl/7.47.0'} resp = http.request( 'GET', 'https://api.github.com/repos/ulauncher/ulauncher/releases', headers=headers) if resp.status != 200: return ErrorResponse( Exception('Could not get releases from Github. %s' % resp.data), 400) releases = json.loads(resp.data) try: return next((r for r in releases if r['tag_name'] == version)) except StopIteration: return ErrorResponse( Exception('Release version %s not found' % version), 404)