def delete_project(self, project: models.Project, current_time: datetime.datetime): """Delete project: Make status Deleted. Only possible from In Progress. """ # Check if valid status transition self.check_transition_possible(current_status=project.current_status, new_status="Deleted") # Can only be Deleted if never made Available if project.has_been_available: raise DDSArgumentError( "You cannot delete a project that has been made available previously. " "Please abort the project if you wish to proceed." ) project.is_active = False try: # Deletes files (also commits session in the function - possibly refactor later) RemoveContents().delete_project_contents(project=project) self.rm_project_user_keys(project=project) # Delete metadata from project row self.delete_project_info(proj=project) except (TypeError, DatabaseError, DeletionError, BucketNotFoundError) as err: flask.current_app.logger.exception(err) db.session.rollback() raise DeletionError( project=project.public_id, message="Server Error: Status was not updated" ) from err delete_message = ( f"\nAll files in project '{project.public_id}' deleted and project info cleared" ) return models.ProjectStatuses(status="Deleted", date_created=current_time), delete_message
def create_project(self, data, **kwargs): """Create project row in db.""" # Lock db, get unit row and update counter unit_row = (models.Unit.query.filter_by( id=auth.current_user().unit_id).with_for_update().one_or_none()) if not unit_row: raise ddserr.AccessDeniedError( message="Error: Your user is not associated to a unit.") unit_row.counter = unit_row.counter + 1 if unit_row.counter else 1 data["public_id"] = "{}{:05d}".format(unit_row.internal_ref, unit_row.counter) # Generate bucket name data["bucket"] = self.generate_bucketname( public_id=data["public_id"], created_time=data["date_created"]) # Create project current_user = auth.current_user() new_project = models.Project( **{ **data, "unit_id": current_user.unit.id, "created_by": current_user.username }) new_project.project_statuses.append( models.ProjectStatuses(**{ "status": "In Progress", "date_created": data["date_created"], })) generate_project_key_pair(current_user, new_project) return new_project
def retract_project(self, project: models.Project, current_time: datetime.datetime): """Retract project: Make status In Progress. Only possible from Available. """ # Check if valid status transition self.check_transition_possible( current_status=project.current_status, new_status="In Progress" ) return models.ProjectStatuses(status="In Progress", date_created=current_time)
def archive_project(self, project: models.Project, current_time: datetime.datetime, aborted: bool = False): """Archive project: Make status Archived. Only possible from In Progress, Available and Expired. Optional aborted flag if something has gone wrong. """ # Check if valid status transition self.check_transition_possible(current_status=project.current_status, new_status="Archived") if project.current_status == "In Progress": if project.has_been_available and not aborted: raise DDSArgumentError( "You cannot archive a project that has been made available previously. " "Please abort the project if you wish to proceed.") project.is_active = False try: # Deletes files (also commits session in the function - possibly refactor later) RemoveContents().delete_project_contents(project=project) delete_message = f"\nAll files in {project.public_id} deleted" self.rm_project_user_keys(project=project) # Delete metadata from project row if aborted: project = self.delete_project_info(project) delete_message += " and project info cleared" except (TypeError, DatabaseError, DeletionError, BucketNotFoundError) as err: flask.current_app.logger.exception(err) db.session.rollback() raise DeletionError( project=project.public_id, message="Server Error: Status was not updated") from err return ( models.ProjectStatuses(status="Archived", date_created=current_time, is_aborted=aborted), delete_message, )
def expire_project( self, project: models.Project, current_time: datetime.datetime, deadline_in: int ) -> models.ProjectStatuses: """Expire project: Make status Expired. Only possible from Available. """ # Check if valid status transition self.check_transition_possible(current_status=project.current_status, new_status="Expired") if deadline_in > 30: raise DDSArgumentError( message="The deadline needs to be less than (or equal to) 30 days." ) deadline = dds_web.utils.current_time(to_midnight=True) + datetime.timedelta( days=deadline_in ) return models.ProjectStatuses( status="Expired", date_created=current_time, deadline=deadline )
def release_project( self, project: models.Project, current_time: datetime.datetime, deadline_in: int ) -> models.ProjectStatuses: """Release project: Make status Available. Only allowed from In Progress and Expired. """ # Check if valid status transition self.check_transition_possible( current_status=project.current_status, new_status="Available" ) if deadline_in > 90: raise DDSArgumentError( message="The deadline needs to be less than (or equal to) 90 days." ) deadline = dds_web.utils.current_time(to_midnight=True) + datetime.timedelta( days=deadline_in ) # Project can only move from Expired 2 times if project.current_status == "Expired": if project.times_expired > 2: raise DDSArgumentError( "Project availability limit: Project cannot be made Available any more times" ) else: # current status is in progress if project.has_been_available: # No change in deadline if made available before deadline = project.current_deadline else: project.released = current_time # Create row in ProjectStatuses return models.ProjectStatuses( status="Available", date_created=current_time, deadline=deadline )
def fill_db(): """Fills the database with initial entries used for development.""" # Foreign key/relationship updates: # The model with the row db.relationship should append the row of the model with foreign key password = "******" # Super Admin superadmin = models.SuperAdmin(username="******", password=password, name="Super Admin") superadmin_email = models.Email(email="*****@*****.**", primary=True) superadmin_email.user = superadmin db.session.add(superadmin_email) # Create first unit user unituser_1 = models.UnitUser( username="******", password=password, name="First Unit User", ) # Create second unit user unituser_2 = models.UnitUser( username="******", password=password, name="Second Unit User", ) # create a few e-mail addresses email_unituser_1 = models.Email(email="*****@*****.**", primary=True) email_unituser_1b = models.Email(email="*****@*****.**", primary=False) email_unituser_2 = models.Email(email="*****@*****.**", primary=True) email_unituser_1.user = unituser_1 email_unituser_1b.user = unituser_1 email_unituser_2.user = unituser_2 unituser_1.active = True unituser_2.active = True # Create first unit unit_1 = models.Unit( public_id="unit_1", name="Unit 1", external_display_name="Unit 1 external", contact_email="*****@*****.**", internal_ref="someunit", safespring_endpoint=current_app.config.get("SAFESPRING_URL"), safespring_name=current_app.config.get("DDS_SAFESPRING_PROJECT"), safespring_access=current_app.config.get("DDS_SAFESPRING_ACCESS"), safespring_secret=current_app.config.get("DDS_SAFESPRING_SECRET"), ) unit_1.users.extend([unituser_1, unituser_2]) # Create first project - leave out foreign key project_1 = models.Project( public_id="project_1", title="First Project", description= "This is a test project. You will be able to upload to but NOT download " "from this project. Create a new project to test the entire system. ", pi="*****@*****.**", bucket="testbucket", ) project_1.project_statuses.append( models.ProjectStatuses(**{ "status": "In Progress", "date_created": dds_web.utils.current_time() })) unituser_1.created_projects.append(project_1) generate_project_key_pair(unituser_1, project_1) # Create second project - leave out foreign key project_2 = models.Project( public_id="project_2", title="Second Project", description= "This is a test project. You will be able to upload to but NOT download " "from this project. Create a new project to test the entire system. ", pi="*****@*****.**", bucket= f"secondproject-{str(dds_web.utils.timestamp(ts_format='%Y%m%d%H%M%S'))}-{str(uuid.uuid4())}", ) project_2.project_statuses.append( models.ProjectStatuses(**{ "status": "In Progress", "date_created": dds_web.utils.current_time() })) unituser_2.created_projects.append(project_2) generate_project_key_pair(unituser_2, project_2) # Connect project to unit. append (not =) due to many projects per unit unit_1.projects.extend([project_1, project_2]) # Create an email email_researchuser_1 = models.Email(email="*****@*****.**", primary=True) # Create first research user researchuser_1 = models.ResearchUser( username="******", password=password, name="First Research User", ) email_researchuser_1.user = researchuser_1 # Create association with user - not owner of project project_1_user_1_association = models.ProjectUsers(owner=False) # Connect research user to association row. = (not append) due to one user per ass. row project_1_user_1_association.researchuser = researchuser_1 # Connect project to association row. = (not append) due to one project per ass. row project_1_user_1_association.project = project_1 researchuser_1.active = True email_researchuser_2 = models.Email(email="*****@*****.**", primary=True) # Create second research user researchuser_2 = models.ResearchUser( username="******", password=password, name="Second Research User", ) email_researchuser_2.user = researchuser_2 # Create association with user - is owner of project project_1_user_2_association = models.ProjectUsers(owner=True) # Connect research user to association row. = (not append) due to one user per ass. row project_1_user_2_association.researchuser = researchuser_2 # Connect project to association row. = (not append) due to one project per ass. row project_1_user_2_association.project = project_1 researchuser_2.active = True # Add unit to database - relationship will add the rest because of foreign key constraints db.session.add(unit_1) db.session.commit() unituser_1_token = encrypted_jwt_token( username=unituser_1.username, sensitive_content=password, ) share_project_private_key( from_user=unituser_1, to_another=researchuser_1, from_user_token=unituser_1_token, project=project_1, ) share_project_private_key( from_user=unituser_1, to_another=researchuser_2, from_user_token=unituser_1_token, project=project_1, ) db.session.commit()