Esempio n. 1
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()
Esempio n. 2
0
    def add_to_project(whom, project, role, send_email=True):
        """Add existing user or invite to a project"""

        allowed_roles = ["Project Owner", "Researcher"]

        if role not in allowed_roles:
            return {
                "status":
                ddserr.AccessDeniedError.code.value,
                "message": ("User Role should be either 'Project Owner' or "
                            "'Researcher' to be added to a project"),
            }

        if whom.role not in allowed_roles:
            return {
                "status":
                ddserr.AccessDeniedError.code.value,
                "message":
                ("Users affiliated with units can not be added to projects individually."
                 ),
            }

        is_owner = role == "Project Owner"
        ownership_change = False

        if isinstance(whom, models.ResearchUser):
            project_user_row = models.ProjectUsers.query.filter_by(
                project_id=project.id, user_id=whom.username).one_or_none()
        else:
            project_user_row = models.ProjectInviteKeys.query.filter_by(
                project_id=project.id, invite_id=whom.id).one_or_none()

        if project_user_row:
            send_email = False
            if project_user_row.owner == is_owner:
                return {
                    "status":
                    ddserr.RoleException.code.value,
                    "message":
                    f"{str(whom)} is already associated with the {str(project)} in this capacity. ",
                }
            ownership_change = True
            project_user_row.owner = is_owner

        if not ownership_change:
            if isinstance(whom, models.ResearchUser):
                project.researchusers.append(
                    models.ProjectUsers(
                        project_id=project.id,
                        user_id=whom.username,
                        owner=is_owner,
                    ))

            try:
                share_project_private_key(
                    from_user=auth.current_user(),
                    to_another=whom,
                    from_user_token=dds_web.security.auth.
                    obtain_current_encrypted_token(),
                    project=project,
                    is_project_owner=is_owner,
                )
            except ddserr.KeyNotFoundError as keyerr:
                return {
                    "message":
                    ("You do not have access to the current project. To get access, "
                     "ask the a user within the responsible unit to grant you access."
                     ),
                    "status":
                    ddserr.AccessDeniedError.code.value,
                }

        try:
            db.session.commit()
        except (
                sqlalchemy.exc.SQLAlchemyError,
                sqlalchemy.exc.IntegrityError,
                sqlalchemy.exc.OperationalError,
        ) as err:
            flask.current_app.logger.exception(err)
            db.session.rollback()
            raise ddserr.DatabaseError(
                message=str(err),
                alt_message=
                f"Server Error: User was not associated with the project" +
                (": Database malfunction." if isinstance(
                    err, sqlalchemy.exc.OperationalError) else "."),
            ) from err

        # If project is already released and not expired, send mail to user
        send_email = send_email and project.current_status == "Available"
        if send_email:
            AddUser.compose_and_send_email_to_user(whom,
                                                   "project_release",
                                                   project=project)

        flask.current_app.logger.debug(
            f"{str(whom)} was given access to the {str(project)} as a {'Project Owner' if is_owner else 'Researcher'}."
        )

        return {
            "status":
            http.HTTPStatus.OK,
            "message":
            (f"{str(whom)} was given access to the "
             f"{str(project)} as a {'Project Owner' if is_owner else 'Researcher'}. An e-mail notification has{' not ' if not send_email else ' '}been sent."
             ),
        }
Esempio n. 3
0
    def make_user(self, data, **kwargs):
        """Deserialize to an User object"""
        token = flask.session.get("invite_token")
        if not dds_web.security.auth.matching_email_with_invite(
                token, data.get("email")):
            raise ddserr.InviteError(
                message="Form email and token email are not the same")

        common_user_fields = {
            "username": data.get("username"),
            "password": data.get("password"),
            "name": data.get("name"),
        }

        # Create new user

        invite = data.get("invite")
        if invite.role == "Super Admin":
            new_user = models.SuperAdmin(**common_user_fields)
        elif invite.role in ["Unit Admin", "Unit Personnel"]:
            new_user = models.UnitUser(**common_user_fields)

            new_user.is_admin = invite.role == "Unit Admin"

            invite.unit.users.append(new_user)
        elif invite.role == "Researcher":
            new_user = models.ResearchUser(**common_user_fields)

        # Create new email and append to user relationship
        new_email = models.Email(email=data.get("email"), primary=True)
        new_user.emails.append(new_email)
        new_user.active = True

        db.session.add(new_user)

        # Verify and transfer invite keys to the new user
        if verify_and_transfer_invite_to_user(token, new_user,
                                              data.get("password")):
            for project_invite_key in invite.project_invite_keys:
                if isinstance(new_user, models.ResearchUser):
                    project_user = models.ProjectUsers(
                        project_id=project_invite_key.project_id,
                        owner=project_invite_key.owner)
                    new_user.project_associations.append(project_user)

                project_user_key = models.ProjectUserKeys(
                    project_id=project_invite_key.project_id,
                    user_id=new_user.username,
                    key=project_invite_key.key,
                )
                db.session.add(project_user_key)
                db.session.delete(project_invite_key)

            flask.session.pop("invite_token", None)

            # Delete old invite
            db.session.delete(invite)

            # Save and return
            db.session.commit()

            return new_user

        flask.session.pop("invite_token", None)
        db.session.delete(new_user)
        db.session.commit()
        raise ddserr.InviteError(message="Invite key verification has failed!")