def get_by_id_untrusted(session, user_id, project_string_id, file_id, directory_id=None): """ Even if we trust the directory (ie from project default), still have to check the file is in it! TODO make user_id and proejct_string_id optional (ie if directory is supplied?) This needs work but is used in a ton of places so review carefully! Plus want to keep as "one function" so we don't have a bunch of random checks """ from shared.database.project import Project from shared.database.source_control.working_dir import WorkingDirFileLink if not directory_id: project = Project.get(session, project_string_id) # start_time = time.time() working_dir = project.directory_default directory_id = working_dir.id working_dir_sub_query = session.query(WorkingDirFileLink).filter( WorkingDirFileLink.working_dir_id == directory_id).subquery('working_dir_sub_query') file = session.query(File).filter( File.id == working_dir_sub_query.c.file_id, File.id == file_id).first() # end_time = time.time() # print("File access time", end_time - start_time) return file
def register_user(user_data, session): """ :param user_data: Example user_data={ 'username': '******', 'email': '*****@*****.**', 'password': '******', 'project_string_id': 'myproject' } :return: """ # User registration password_hash = hashing_functions.make_password_hash( user_data['email'], user_data['password']) # TODO could insert logic here to attach a user to a project based on say the sigup code # ie signup_code.something? username = user_data['username'] user_email = user_data['email'] new_user = User( email = user_email, password_hash = password_hash, username = username, api_enabled_builder = True, api_enabled_trainer = True, security_email_verified = True, last_builder_or_trainer_mode = 'builder', permissions_general = {'general': ['normal_user']} ) new_user.permissions_projects = {} # I don't like having this here but alternative of committing object seems worse session.add(new_user) if 'project_string_id' in user_data: new_user.current_project_string_id = user_data['project_string_id'] project = Project.get(session, user_data['project_string_id']) if project is not None: new_user.projects.append(project) new_user_working_dir = WorkingDir.new_user_working_dir( session, None, project, new_user ) permission_result, permission_error = Project_permissions.add(user_data['project_string_id'], new_user, user_data['project_string_id']) return new_user
def has_project_permissions_for_export(export, project_string_id, session): log = regular_log.default() project = Project.get(session, project_string_id) # Theory is that if a user has access to project # They have access to download from project if export.project_id == project.id: log['error'][ 'project_permissions'] = 'Permission error, invalid project export match' return log
def generate_mask_by_project_id(project_string_id): # TODO use a thread, this is a long running process semantic_segmentation_data_prep = Semantic_segmentation_data_prep() with sessionMaker.session_scope() as session: project = Project.get(session, project_string_id) type = "joint" # type = "binary" semantic_segmentation_data_prep.generate_mask_core( session, project, type) return "ok", 200, {'ContentType': 'application/json'}
def by_project_core(project_string_id: str, Roles: list, apis_project_list: list = [], apis_user_list: list = []): with sessionMaker.session_scope() as session: if not project_string_id or project_string_id == "null" or project_string_id == "undefined": raise Forbidden(default_denied_message) if request.authorization is not None: result = API_Permissions.by_project( session=session, project_string_id=project_string_id, Roles=Roles) if result is not True: raise Forbidden(default_denied_message + " API Permissions") # At the moment auth doesn't actually # get project as it has all results stored... # not clear that we would need a None check here # given its checked in auth? project = Project.get(session, project_string_id) if project is None: raise Forbidden(default_denied_message + " Can't find project") # Project APIs, maybe should role this into API_Permissions check_all_apis(project=project, apis_required_list=apis_project_list) return True result = Project_permissions.check_permissions( session=session, apis_project_list=apis_project_list, apis_user_list=apis_user_list, project_string_id=project_string_id, Roles=Roles) if result is True: return True else: raise Forbidden(default_denied_message)
def web_build_name_to_file_id_dict(project_string_id): """ Given we know a label_name, and where we are working, return the label_file_id Arguments: project_string_id, integer working_dir_id, integer Returns: dict of label files or None / failure case """ log = {"success": False, "errors": []} directory_id = request.headers.get('directory_id', None) if directory_id is None: log["errors"].append("'directory_id' not supplied") return jsonify(log), 200 with sessionMaker.session_scope() as session: project = Project.get(session, project_string_id) verify_result = WorkingDir.verify_directory_in_project( session, project, directory_id) if verify_result is False: log["errors"].append("Invalid directory id") log["success"] = False return jsonify(log=log), 200 name_to_file_id, result = build_name_to_file_id_dict( session=session, directory_id=directory_id) if result == True: log["success"] = True return jsonify(log=log, name_to_file_id=name_to_file_id), 200
def check_permissions(Roles, project_string_id, session, apis_project_list=None, apis_user_list=None): """ TODO this could use better organization ie project_string_id is None check could be here, but we seem to do it an extra time on line 123 """ if project_string_id is None: # TODO merge None checks from other thing up top here. raise Forbidden("project_string_id is None") if 'allow_anonymous' in Roles: return True project = Project.get(session, project_string_id) if project is None: raise Forbidden(default_denied_message) # Careful here! Just becuase a project is public # Doesn't mean public is allowed acccess to all # routes. ie only admins can delete project # if a project is public we don't need to check a user's apis right? if 'allow_if_project_is_public' in Roles: if project: if project.is_public is True: return True # TODO merge LoggedIn() with getUserID() similar internal logic if LoggedIn() != True: raise Forbidden(default_denied_message) if 'allow_any_logged_in_user' in Roles: # TODO not happy with this name, want more clarity on how this effects other permissions like apis / project etc. return True user = session.query(User).filter(User.id == getUserID()).one() if user.is_super_admin == True: return True if apis_project_list: check_all_apis(project=project, apis_required_list=apis_project_list) if apis_user_list: User_Permissions.general(user=user, apis_user_list=apis_user_list) # This could be slow if a user has a lot of projects? for project, Permissions in user.permissions_projects.items(): if Permissions is None: continue if project_string_id == project: check_role_result = check_roles(Roles, Permissions) if check_role_result is True: return True # Default # Good to have this here so we can call # this function as one line and don't ahve to worry # About returning False (must have returned True eariler) raise Forbidden(default_denied_message)
def filter_by_project(session, project_string_id, query): project = Project.get(session=session, project_string_id=project_string_id) query = query.filter(Job.project == project) return query
def update_tags(project_string_id): """ Update tags to latest """ have_error = False error_message_list = [] with sessionMaker.session_scope() as session: data = request.get_json(force=True) tag_list = data.get('tag_list', None) # tag_list could be none, ie deleted all tags... #if tag_list is None: #error_message_list.append("tag list is None") #return jsonify(error_message_list), 400, {'ContentType' : 'application/json'} project = Project.get(session, project_string_id) print(tag_list) rebuilt_tag_list = [] for tag in tag_list: if valid_tag(tag): name = tag.lower() #Check if tag with same name already exists #If so can just add that database object to tag_db = session.query(Tag).filter(Tag.name == name).first() if not tag_db: tag_db = Tag() tag_db.name = name tag_db.is_public = project.is_public session.add(tag_db) if tag_db: session.add(tag_db) # TODO handle counts properly ie on tag being removed etc. #tag_db.count += 1 rebuilt_tag_list.append(tag_db) session.add(project) # This handles removing link to tag that's no longer in project project.tag_list = rebuilt_tag_list return json.dumps({'success': True}), 200, { 'ContentType': 'application/json' }