Exemple #1
0
    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
Exemple #2
0
    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
Exemple #3
0
    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)
Exemple #4
0
    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,
        )
Exemple #5
0
    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
        )
Exemple #6
0
    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
        )
Exemple #7
0
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()