示例#1
0
def create_federated_user(
        username,
        email,
        service_id,
        service_ident,
        set_password_notification,
        metadata={},
        email_required=True,
        confirm_username=True,
        prompts=tuple(),
):
    prompts = set(prompts)

    if confirm_username:
        prompts.add(UserPromptTypes.CONFIRM_USERNAME)

    new_user = create_user_noverify(username,
                                    email,
                                    email_required=email_required,
                                    prompts=prompts)
    new_user.verified = True
    new_user.save()

    FederatedLogin.create(
        user=new_user,
        service=_get_login_service(service_id),
        service_ident=service_ident,
        metadata_json=json.dumps(metadata),
    )

    if set_password_notification:
        notification.create_notification("password_required", new_user)

    return new_user
示例#2
0
def convert_user_to_organization(user_obj, admin_user):
    if user_obj.robot:
        raise DataModelException("Cannot convert a robot into an organization")

    with db_transaction():
        # Change the user to an organization and disable this account for login.
        user_obj.organization = True
        user_obj.password_hash = None
        user_obj.save()

        # Clear any federated auth pointing to this user.
        FederatedLogin.delete().where(
            FederatedLogin.user == user_obj).execute()

        # Delete any user-specific permissions on repositories.
        (RepositoryPermission.delete().where(
            RepositoryPermission.user == user_obj).execute())

        # Create a team for the owners
        owners_team = team.create_team("owners", user_obj, "admin")

        # Add the user who will admin the org to the owners team
        team.add_user_to_team(admin_user, owners_team)

        return user_obj
示例#3
0
def create_robot(robot_shortname, parent, description="", unstructured_metadata=None):
    (username_valid, username_issue) = validate_username(robot_shortname)
    if not username_valid:
        raise InvalidRobotException(
            "The name for the robot '%s' is invalid: %s" % (robot_shortname, username_issue)
        )

    username = format_robot_username(parent.username, robot_shortname)

    try:
        User.get(User.username == username)

        msg = "Existing robot with name: %s" % username
        logger.info(msg)
        raise InvalidRobotException(msg)
    except User.DoesNotExist:
        pass

    service = LoginService.get(name="quayrobot")
    try:
        with db_transaction():
            created = User.create(username=username, email=str(uuid.uuid4()), robot=True)
            token = random_string_generator(length=64)()
            RobotAccountToken.create(robot_account=created, token=token, fully_migrated=True)
            FederatedLogin.create(
                user=created, service=service, service_ident="robot:%s" % created.id
            )
            RobotAccountMetadata.create(
                robot_account=created,
                description=description[0:255],
                unstructured_json=unstructured_metadata or {},
            )
            return created, token
    except Exception as ex:
        raise DataModelException(ex.message)
示例#4
0
def detach_external_login(user, service_name):
    try:
        service = LoginService.get(name=service_name)
    except LoginService.DoesNotExist:
        return

    FederatedLogin.delete().where(FederatedLogin.user == user,
                                  FederatedLogin.service == service).execute()
示例#5
0
def attach_federated_login(user, service_id, service_ident, metadata=None):
    service = _get_login_service(service_id)
    FederatedLogin.create(
        user=user,
        service=service,
        service_ident=service_ident,
        metadata_json=json.dumps(metadata or {}),
    )
    return user
示例#6
0
def test_mark_namespace_for_deletion(initialized_db):
    def create_transaction(db):
        return db.transaction()

    # Create a user and then mark it for deletion.
    user = create_user_noverify("foobar",
                                "*****@*****.**",
                                email_required=False)

    # Add some robots.
    create_robot("foo", user)
    create_robot("bar", user)

    assert lookup_robot("foobar+foo") is not None
    assert lookup_robot("foobar+bar") is not None
    assert len(list(list_namespace_robots("foobar"))) == 2

    # Add some federated user links.
    attach_federated_login(user, "google", "someusername")
    attach_federated_login(user, "github", "someusername")
    assert FederatedLogin.select().where(
        FederatedLogin.user == user).count() == 2
    assert FederatedLogin.select().where(
        FederatedLogin.service_ident == "someusername").exists()

    # Mark the user for deletion.
    queue = WorkQueue("testgcnamespace", create_transaction)
    mark_namespace_for_deletion(user, [], queue)

    # Ensure the older user is still in the DB.
    older_user = User.get(id=user.id)
    assert older_user.username != "foobar"

    # Ensure the robots are deleted.
    with pytest.raises(InvalidRobotException):
        assert lookup_robot("foobar+foo")

    with pytest.raises(InvalidRobotException):
        assert lookup_robot("foobar+bar")

    assert len(list(list_namespace_robots(older_user.username))) == 0

    # Ensure the federated logins are gone.
    assert FederatedLogin.select().where(
        FederatedLogin.user == user).count() == 0
    assert (not FederatedLogin.select().where(
        FederatedLogin.service_ident == "someusername").exists())

    # Ensure we can create a user with the same namespace again.
    new_user = create_user_noverify("foobar",
                                    "*****@*****.**",
                                    email_required=False)
    assert new_user.id != user.id

    # Ensure the older user is still in the DB.
    assert User.get(id=user.id).username != "foobar"
示例#7
0
def list_federated_logins(user):
    selected = FederatedLogin.select(FederatedLogin.service_ident,
                                     LoginService.name,
                                     FederatedLogin.metadata_json)
    joined = selected.join(LoginService)
    return joined.where(LoginService.name != "quayrobot",
                        FederatedLogin.user == user)
示例#8
0
def regenerate_robot_token(robot_shortname, parent):
    robot_username = format_robot_username(parent.username, robot_shortname)

    robot, metadata = lookup_robot_and_metadata(robot_username)
    password = random_string_generator(length=64)()
    robot.email = str(uuid4())
    robot.uuid = str(uuid4())

    service = LoginService.get(name="quayrobot")
    login = FederatedLogin.get(FederatedLogin.user == robot,
                               FederatedLogin.service == service)
    login.service_ident = "robot:%s" % (robot.id)

    try:
        token_data = RobotAccountToken.get(robot_account=robot)
    except RobotAccountToken.DoesNotExist:
        token_data = RobotAccountToken.create(robot_account=robot)

    token_data.token = password

    with db_transaction():
        token_data.save()
        login.save()
        robot.save()

    return robot, password, metadata
示例#9
0
def _delete_user_linked_data(user):
    if user.organization:
        # Delete the organization's teams.
        with db_transaction():
            for team in Team.select().where(Team.organization == user):
                team.delete_instance(recursive=True)

        # Delete any OAuth approvals and tokens associated with the user.
        with db_transaction():
            for app in OAuthApplication.select().where(
                    OAuthApplication.organization == user):
                app.delete_instance(recursive=True)
    else:
        # Remove the user from any teams in which they are a member.
        TeamMember.delete().where(TeamMember.user == user).execute()

    # Delete any repository buildtriggers where the user is the connected user.
    with db_transaction():
        triggers = RepositoryBuildTrigger.select().where(
            RepositoryBuildTrigger.connected_user == user)
        for trigger in triggers:
            trigger.delete_instance(recursive=True, delete_nullable=False)

    with db_transaction():
        quotas = namespacequota.get_namespace_quota_list(user.username)
        for quota in quotas:
            namespacequota.delete_namespace_quota(quota)

    # Delete any mirrors with robots owned by this user.
    with db_transaction():
        robots = list(list_namespace_robots(user.username))
        RepoMirrorConfig.delete().where(
            RepoMirrorConfig.internal_robot << robots).execute()

    # Delete any robots owned by this user.
    with db_transaction():
        robots = list(list_namespace_robots(user.username))
        for robot in robots:
            robot.delete_instance(recursive=True, delete_nullable=True)

    # Null out any service key approvals. We technically lose information here, but its better than
    # falling and only occurs if a superuser is being deleted.
    ServiceKeyApproval.update(approver=None).where(
        ServiceKeyApproval.approver == user).execute()

    # Delete any federated user links.
    FederatedLogin.delete().where(FederatedLogin.user == user).execute()
示例#10
0
文件: user.py 项目: zhill/quay
def get_federated_logins(user_ids, service_name):
    """ Returns all federated logins for the given user ids under the given external service. """
    if not user_ids:
        return []

    return (FederatedLogin.select().join(User).switch(FederatedLogin).join(
        LoginService).where(FederatedLogin.user << user_ids,
                            LoginService.name == service_name))
def upgrade(tables, tester, progress_reporter):
    op = ProgressWrapper(original_op, progress_reporter)
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index("oauthaccesstoken_refresh_token", table_name="oauthaccesstoken")
    op.drop_column(u"oauthaccesstoken", "refresh_token")

    op.drop_column("accesstoken", "code")

    op.drop_column("appspecificauthtoken", "token_code")

    op.drop_column("oauthaccesstoken", "access_token")
    op.drop_column("oauthapplication", "client_secret")

    op.drop_column("oauthauthorizationcode", "code")

    op.drop_column("repositorybuildtrigger", "private_key")
    op.drop_column("repositorybuildtrigger", "auth_token")
    # ### end Alembic commands ###

    # Overwrite all plaintext robot credentials.
    from app import app

    if app.config.get("SETUP_COMPLETE", False) or tester.is_testing():
        while True:
            try:
                robot_account_token = RobotAccountToken.get(fully_migrated=False)
                logger.debug("Found robot account token %s migrate", robot_account_token.id)

                robot_account = robot_account_token.robot_account
                assert robot_account.robot

                result = (
                    User.update(email=str(uuid.uuid4()))
                    .where(
                        User.id == robot_account.id,
                        User.robot == True,
                        User.uuid == robot_account.uuid,
                    )
                    .execute()
                )
                assert result == 1

                try:
                    federated_login = FederatedLogin.get(user=robot_account)
                    assert federated_login.service.name == "quayrobot"

                    federated_login.service_ident = "robot:%s" % robot_account.id
                    federated_login.save()
                except FederatedLogin.DoesNotExist:
                    pass

                robot_account_token.fully_migrated = True
                robot_account_token.save()

                logger.debug("Finished migrating robot account token %s", robot_account_token.id)
            except RobotAccountToken.DoesNotExist:
                break
示例#12
0
def get_federated_team_member_mapping(team, login_service_name):
    """ Returns a dict of all federated IDs for all team members in the team whose users are
      bound to the login service within the given name. The dictionary is from federated service
      identifier (username) to their Quay User table ID.
  """
    login_service = LoginService.get(name=login_service_name)

    query = (FederatedLogin.select(
        FederatedLogin.service_ident,
        User.id).join(User).join(TeamMember).join(Team).where(
            Team.id == team, User.robot == False,
            FederatedLogin.service == login_service))
    return dict(query.tuples())
示例#13
0
def verify_federated_login(service_id, service_ident):
    try:
        found = (FederatedLogin.select(
            FederatedLogin,
            User).join(LoginService).switch(FederatedLogin).join(User).where(
                FederatedLogin.service_ident == service_ident,
                LoginService.name == service_id).get())

        # Mark that the user was accessed.
        _basequery.update_last_accessed(found.user)

        return found.user
    except FederatedLogin.DoesNotExist:
        return None
def upgrade(tables, tester, progress_reporter):
    op = ProgressWrapper(original_op, progress_reporter)
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index("oauthaccesstoken_refresh_token",
                  table_name="oauthaccesstoken")
    op.drop_column(u"oauthaccesstoken", "refresh_token")

    op.drop_column("accesstoken", "code")

    op.drop_column("appspecificauthtoken", "token_code")

    op.drop_column("oauthaccesstoken", "access_token")
    op.drop_column("oauthapplication", "client_secret")

    op.drop_column("oauthauthorizationcode", "code")

    op.drop_column("repositorybuildtrigger", "private_key")
    op.drop_column("repositorybuildtrigger", "auth_token")
    # ### end Alembic commands ###

    # Overwrite all plaintext robot credentials.
    from app import app

    if app.config.get("SETUP_COMPLETE", False) or tester.is_testing():
        while True:
            try:
                robot_account_token = RobotAccountToken.get(
                    fully_migrated=False)
                robot_account = robot_account_token.robot_account

                robot_account.email = str(uuid.uuid4())
                robot_account.save()

                federated_login = FederatedLogin.get(user=robot_account)
                federated_login.service_ident = "robot:%s" % robot_account.id
                federated_login.save()

                robot_account_token.fully_migrated = True
                robot_account_token.save()
            except RobotAccountToken.DoesNotExist:
                break
示例#15
0
def upgrade(tables, tester, progress_reporter):
    op = ProgressWrapper(original_op, progress_reporter)
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index('oauthaccesstoken_refresh_token',
                  table_name='oauthaccesstoken')
    op.drop_column(u'oauthaccesstoken', 'refresh_token')

    op.drop_column('accesstoken', 'code')

    op.drop_column('appspecificauthtoken', 'token_code')

    op.drop_column('oauthaccesstoken', 'access_token')
    op.drop_column('oauthapplication', 'client_secret')

    op.drop_column('oauthauthorizationcode', 'code')

    op.drop_column('repositorybuildtrigger', 'private_key')
    op.drop_column('repositorybuildtrigger', 'auth_token')
    # ### end Alembic commands ###

    # Overwrite all plaintext robot credentials.
    while True:
        try:
            robot_account_token = RobotAccountToken.get(fully_migrated=False)
            robot_account = robot_account_token.robot_account

            robot_account.email = str(uuid.uuid4())
            robot_account.save()

            federated_login = FederatedLogin.get(user=robot_account)
            federated_login.service_ident = 'robot:%s' % robot_account.id
            federated_login.save()

            robot_account_token.fully_migrated = True
            robot_account_token.save()
        except RobotAccountToken.DoesNotExist:
            break