예제 #1
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)
예제 #2
0
파일: test_api.py 프로젝트: xzwupeng/quay
def create_org(namespace, owner):
    try:
        User.get(username=namespace)
    except User.DoesNotExist:
        organization.create_organization(namespace,
                                         "*****@*****.**" % str(uuid.uuid1()),
                                         owner)
예제 #3
0
def test_delete_namespace_via_marker(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 repositories.
    create_repository("foobar", "somerepo", user)
    create_repository("foobar", "anotherrepo", user)

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

    # Delete the user.
    with check_transitive_modifications():
        delete_namespace_via_marker(marker_id, [])

    # Ensure the user was actually deleted.
    with pytest.raises(User.DoesNotExist):
        User.get(id=user.id)

    with pytest.raises(DeletedNamespace.DoesNotExist):
        DeletedNamespace.get(id=marker_id)
예제 #4
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"
예제 #5
0
def get_namespace_by_user_id(namespace_user_db_id):
    try:
        return User.get(User.id == namespace_user_db_id,
                        User.robot == False).username
    except User.DoesNotExist:
        raise InvalidUsernameException("User with id does not exist: %s" %
                                       namespace_user_db_id)
예제 #6
0
파일: repository.py 프로젝트: tkdchen/quay
def create_repository(
    namespace, name, creating_user, visibility="private", repo_kind="image", description=None
):
    namespace_user = User.get(username=namespace)
    yesterday = datetime.now() - timedelta(days=1)

    with db_transaction():
        repo = Repository.create(
            name=name,
            visibility=Repository.visibility.get_id(visibility),
            namespace_user=namespace_user,
            kind=Repository.kind.get_id(repo_kind),
            description=description,
        )

        RepositoryActionCount.create(repository=repo, count=0, date=yesterday)
        RepositorySearchScore.create(repository=repo, score=0)

        # Note: We put the admin create permission under the transaction to ensure it is created.
        if creating_user and not creating_user.organization:
            admin = Role.get(name="admin")
            RepositoryPermission.create(user=creating_user, repository=repo, role=admin)

    # Apply default permissions (only occurs for repositories under organizations)
    if creating_user and not creating_user.organization and creating_user.username != namespace:
        permission.apply_default_permissions(repo, creating_user)

    return repo
예제 #7
0
def create_mirror_repo_robot(rules, repo_name="repo", external_registry_config=None):
    try:
        user = User.get(User.username == "mirror")
    except User.DoesNotExist:
        user = create_user_noverify("mirror", "*****@*****.**", email_required=False)

    try:
        robot = lookup_robot("mirror+robot")
    except model.InvalidRobotException:
        robot, _ = create_robot("robot", user)

    repo = model.repository.create_repository(
        "mirror", repo_name, None, repo_kind="image", visibility="public"
    )
    repo.save()

    rule = model.repo_mirror.create_mirroring_rule(repo, rules)

    mirror_kwargs = {
        "repository": repo,
        "root_rule": rule,
        "internal_robot": robot,
        "external_reference": "registry.example.com/namespace/repository",
        "sync_interval": timedelta(days=1).total_seconds(),
        "external_registry_config": external_registry_config,
    }
    mirror = model.repo_mirror.enable_mirroring_for_repository(**mirror_kwargs)
    mirror.sync_status = RepoMirrorStatus.NEVER_RUN
    mirror.sync_start_date = datetime.utcnow() - timedelta(days=1)
    mirror.sync_retries_remaining = 3
    mirror.save()

    return (mirror, repo)
예제 #8
0
def delete_robot(robot_username):
    try:
        robot = User.get(username=robot_username, robot=True)
        robot.delete_instance(recursive=True, delete_nullable=True)

    except User.DoesNotExist:
        raise InvalidRobotException("Could not find robot with username: %s" % robot_username)
예제 #9
0
def cleanup_old_robots(page_size=50, force=False):
    """ Deletes any robots that live under namespaces that no longer exist. """
    if not force and not app.config.get("SETUP_COMPLETE", False):
        return

    # Collect the robot accounts to delete.
    page_number = 1
    to_delete = []
    encountered_namespaces = {}

    while True:
        found_bots = False
        for robot in list(User.select().where(User.robot == True).paginate(
                page_number, page_size)):
            found_bots = True
            logger.info("Checking robot %s (page %s)", robot.username,
                        page_number)
            parsed = parse_robot_username(robot.username)
            if parsed is None:
                continue

            namespace, _ = parsed
            if namespace in encountered_namespaces:
                if not encountered_namespaces[namespace]:
                    logger.info("Marking %s to be deleted", robot.username)
                    to_delete.append(robot)
            else:
                try:
                    User.get(username=namespace)
                    encountered_namespaces[namespace] = True
                except User.DoesNotExist:
                    # Save the robot account for deletion.
                    logger.info("Marking %s to be deleted", robot.username)
                    to_delete.append(robot)
                    encountered_namespaces[namespace] = False

        if not found_bots:
            break

        page_number = page_number + 1

    # Cleanup any robot accounts whose corresponding namespace doesn't exist.
    logger.info("Found %s robots to delete", len(to_delete))
    for index, robot in enumerate(to_delete):
        logger.info("Deleting robot %s of %s (%s)", index, len(to_delete),
                    robot.username)
        robot.delete_instance(recursive=True, delete_nullable=True)
예제 #10
0
파일: fixtures.py 프로젝트: epasham/quay-1
 def set_geo_block_for_namespace(namespace_name, iso_country_code):
     NamespaceGeoRestriction.create(
         namespace=User.get(username=namespace_name),
         description="",
         unstructured_json={},
         restricted_region_iso_code=iso_country_code,
     )
     return "OK"
예제 #11
0
def create_user_noverify(
    username, email, email_required=True, prompts=tuple(), is_possible_abuser=False
):
    if email_required:
        if not validate_email(email):
            raise InvalidEmailAddressException("Invalid email address: %s" % email)
    else:
        # If email addresses are not required and none was specified, then we just use a unique
        # ID to ensure that the database consistency check remains intact.
        email = email or str(uuid.uuid4())

    (username_valid, username_issue) = validate_username(username)
    if not username_valid:
        raise InvalidUsernameException("Invalid namespace %s: %s" % (username, username_issue))

    try:
        existing = User.get((User.username == username) | (User.email == email))
        logger.info("Existing user with same username or email.")

        # A user already exists with either the same username or email
        if existing.username == username:
            assert not existing.robot

            msg = (
                "Username has already been taken by an organization and cannot be reused: %s"
                % username
            )
            if not existing.organization:
                msg = "Username has already been taken by user cannot be reused: %s" % username

            raise InvalidUsernameException(msg)

        raise InvalidEmailAddressException("Email has already been used: %s" % email)
    except User.DoesNotExist:
        # This is actually the happy path
        logger.debug("Email and username are unique!")

    # Create the user.
    try:
        default_expr_s = _convert_to_s(config.app_config["DEFAULT_TAG_EXPIRATION"])
        default_max_builds = config.app_config.get("DEFAULT_NAMESPACE_MAXIMUM_BUILD_COUNT")
        threat_max_builds = config.app_config.get("THREAT_NAMESPACE_MAXIMUM_BUILD_COUNT")

        if is_possible_abuser and threat_max_builds is not None:
            default_max_builds = threat_max_builds

        new_user = User.create(
            username=username,
            email=email,
            removed_tag_expiration_s=default_expr_s,
            maximum_queued_builds_count=default_max_builds,
        )
        for prompt in prompts:
            create_user_prompt(new_user, prompt)

        return new_user
    except Exception as ex:
        raise DataModelException(ex.message)
예제 #12
0
def verify_robot(robot_username, password):
  try:
    password = remove_unicode(password)
  except UnicodeEncodeError:
    msg = ('Could not find robot with username: %s and supplied password.' %
            robot_username)
    raise InvalidRobotException(msg)

  result = parse_robot_username(robot_username)
  if result is None:
    raise InvalidRobotException('%s is an invalid robot name' % robot_username)

  robot = lookup_robot(robot_username)
  assert robot.robot

  # Lookup the token for the robot.
  try:
    token_data = RobotAccountToken.get(robot_account=robot)
    if not token_data.token.matches(password):
      msg = ('Could not find robot with username: %s and supplied password.' %
             robot_username)
      raise InvalidRobotException(msg)
  except RobotAccountToken.DoesNotExist:
    # TODO(remove-unenc): Remove once migrated.
    if not ActiveDataMigration.has_flag(ERTMigrationFlags.READ_OLD_FIELDS):
      raise InvalidRobotException(msg)

    if password.find('robot:') >= 0:
      # Just to be sure.
      raise InvalidRobotException(msg)

    query = (User
             .select()
             .join(FederatedLogin)
             .join(LoginService)
             .where(FederatedLogin.service_ident == password, LoginService.name == 'quayrobot',
                    User.username == robot_username))

    try:
      robot = query.get()
    except User.DoesNotExist:
      msg = ('Could not find robot with username: %s and supplied password.' %
             robot_username)
      raise InvalidRobotException(msg)

  # Find the owner user and ensure it is not disabled.
  try:
    owner = User.get(User.username == result[0])
  except User.DoesNotExist:
    raise InvalidRobotException('Robot %s owner does not exist' % robot_username)

  if not owner.enabled:
    raise InvalidRobotException('This user has been disabled. Please contact your administrator.')

  # Mark that the robot was accessed.
  _basequery.update_last_accessed(robot)

  return robot
예제 #13
0
def lookup_robot(robot_username):
    try:
        robot_username.encode("ascii")
    except UnicodeEncodeError:
        raise InvalidRobotException("Could not find robot with specified username")

    try:
        return User.get(username=robot_username, robot=True)
    except User.DoesNotExist:
        raise InvalidRobotException("Could not find robot with specified username")
예제 #14
0
def create_repository(namespace,
                      name,
                      creating_user,
                      visibility="private",
                      repo_kind="image",
                      description=None):
    namespace_user = User.get(username=namespace)
    yesterday = datetime.now() - timedelta(days=1)

    try:
        with db_transaction():
            # Check if the repository exists to avoid an IntegrityError if possible.
            existing = get_repository(namespace, name)
            if existing is not None:
                return None

            try:
                repo = Repository.create(
                    name=name,
                    visibility=Repository.visibility.get_id(visibility),
                    namespace_user=namespace_user,
                    kind=Repository.kind.get_id(repo_kind),
                    description=description,
                )
            except IntegrityError as ie:
                raise _RepositoryExistsException(ie)

            RepositoryActionCount.create(repository=repo,
                                         count=0,
                                         date=yesterday)
            RepositorySearchScore.create(repository=repo, score=0)

            # Note: We put the admin create permission under the transaction to ensure it is created.
            if creating_user and not creating_user.organization:
                admin = Role.get(name="admin")
                RepositoryPermission.create(user=creating_user,
                                            repository=repo,
                                            role=admin)
    except _RepositoryExistsException as ree:
        try:
            return Repository.get(namespace_user=namespace_user, name=name)
        except Repository.DoesNotExist:
            logger.error(
                "Got integrity error when trying to create repository %s/%s: %s",
                namespace,
                name,
                ree.internal_exception,
            )
            return None

    # Apply default permissions (only occurs for repositories under organizations)
    if creating_user and not creating_user.organization and creating_user.username != namespace:
        permission.apply_default_permissions(repo, creating_user)

    return repo
예제 #15
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

    # 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 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"
예제 #16
0
  def test_config_file_with_no_db_users(self):
    with FreshConfigProvider():
      # Write some config.
      self.putJsonResponse(SuperUserConfig, data=dict(config={}, hostname='foobar'))

      # Delete all the users in the DB.
      for user in list(User.select()):
        model.user.delete_user(user, all_queues)

      # This method should now succeed.
      data = dict(username='******', password='******', email='*****@*****.**')
      result = self.postJsonResponse(SuperUserCreateInitialSuperUser, data=data)
      self.assertTrue(result['status'])

      # Verify the superuser was created.
      User.get(User.username == 'cooluser')

      # Verify the superuser was placed into the config.
      result = self.getJsonResponse(SuperUserConfig)
      self.assertEquals(['cooluser'], result['config']['SUPER_USERS'])
예제 #17
0
def create_reset_password_email_code(email):
    try:
        user = User.get(User.email == email)
    except User.DoesNotExist:
        raise InvalidEmailAddressException("Email address was not found")

    if user.organization:
        raise InvalidEmailAddressException("Organizations can not have passwords")

    verification_code, unhashed = Credential.generate()
    code = EmailConfirmation.create(user=user, pw_reset=True, verification_code=verification_code)
    return encode_public_private_token(code.code, unhashed)
예제 #18
0
파일: log.py 프로젝트: sabre1041/quay-1
def log_action(
    kind_name,
    user_or_organization_name,
    performer=None,
    repository=None,
    ip=None,
    metadata={},
    timestamp=None,
):
    """
    Logs an entry in the LogEntry table.
    """
    if not timestamp:
        timestamp = datetime.today()

    account = None
    if user_or_organization_name is not None:
        account = User.get(User.username == user_or_organization_name).id
    else:
        account = config.app_config.get("SERVICE_LOG_ACCOUNT_ID")
        if account is None:
            account = user.get_minimum_user_id()

    if performer is not None:
        performer = performer.id

    if repository is not None:
        repository = repository.id

    kind = _get_log_entry_kind(kind_name)
    metadata_json = json.dumps(metadata, default=_json_serialize)
    log_data = {
        "kind": kind,
        "account": account,
        "performer": performer,
        "repository": repository,
        "ip": ip,
        "metadata_json": metadata_json,
        "datetime": timestamp,
    }

    try:
        LogEntry3.create(**log_data)
    except PeeweeException as ex:
        strict_logging_disabled = config.app_config.get(
            "ALLOW_PULLS_WITHOUT_STRICT_LOGGING")
        if strict_logging_disabled and kind_name in ACTIONS_ALLOWED_WITHOUT_AUDIT_LOGGING:
            logger.exception("log_action failed",
                             extra=({
                                 "exception": ex
                             }).update(log_data))
        else:
            raise
예제 #19
0
def log_action(kind_name,
               user_or_organization_name,
               performer=None,
               repository=None,
               ip=None,
               metadata={},
               timestamp=None):
    """ Logs an entry in the LogEntry table. """
    if not timestamp:
        timestamp = datetime.today()

    account = None
    if user_or_organization_name is not None:
        account = User.get(User.username == user_or_organization_name).id
    else:
        account = config.app_config.get('SERVICE_LOG_ACCOUNT_ID')
        if account is None:
            account = user.get_minimum_user_id()

    if performer is not None:
        performer = performer.id

    if repository is not None:
        repository = repository.id

    kind = _get_log_entry_kind(kind_name)
    metadata_json = json.dumps(metadata, default=_json_serialize)
    log_data = {
        'kind': kind,
        'account': account,
        'performer': performer,
        'repository': repository,
        'ip': ip,
        'metadata_json': metadata_json,
        'datetime': timestamp
    }

    try:
        LogEntry3.create(**log_data)
    except PeeweeException as ex:
        strict_logging_disabled = config.app_config.get(
            'ALLOW_PULLS_WITHOUT_STRICT_LOGGING')
        if strict_logging_disabled and kind_name in ACTIONS_ALLOWED_WITHOUT_AUDIT_LOGGING:
            logger.exception('log_action failed',
                             extra=({
                                 'exception': ex
                             }).update(log_data))
        else:
            raise
예제 #20
0
def test_cleanup_old_robots(initialized_db):
  before_robot_count = User.select().where(User.robot == True).count()
  before_user_count = User.select().count()

  # Run the cleanup once, and ensure it does nothing.
  cleanup_old_robots(force=True)

  after_robot_count = User.select().where(User.robot == True).count()
  after_user_count = User.select().count()

  assert before_robot_count == after_robot_count
  assert before_user_count == after_user_count

  # Create some orphan robots.
  created = set()
  for index in range(0, 50):
    created.add('doesnotexist+a%s' % index)
    created.add('anothernamespace+b%s' % index)

    User.create(username='******' % index, robot=True)
    User.create(username='******' % index, robot=True)

  before_robot_count = User.select().where(User.robot == True).count()
  before_user_count = User.select().count()

  cleanup_old_robots(page_size=10, force=True)

  after_robot_count = User.select().where(User.robot == True).count()
  after_user_count = User.select().count()

  assert before_robot_count == after_robot_count + len(created)
  assert before_user_count == after_user_count + len(created)

  for name in created:
    with pytest.raises(User.DoesNotExist):
      User.get(username=name)
예제 #21
0
def set_user_repo_permission(username, namespace_name, repository_name, role_name):
  if username == namespace_name:
    raise DataModelException('Namespace owner must always be admin.')

  try:
    user = User.get(User.username == username)
  except User.DoesNotExist:
    raise DataModelException('Invalid username: %s' % username)

  if user.robot:
    parts = parse_robot_username(user.username)
    if not parts:
      raise DataModelException('Invalid robot: %s' % username)

    robot_namespace, _ = parts
    if robot_namespace != namespace_name:
      raise DataModelException('Cannot add robot %s under namespace %s' %
                               (username, namespace_name))

  return __set_entity_repo_permission(user, 'user', namespace_name, repository_name, role_name)
예제 #22
0
def verify_robot(robot_username, password):
    try:
        password.encode("ascii")
    except UnicodeEncodeError:
        msg = "Could not find robot with username: %s and supplied password." % robot_username
        raise InvalidRobotException(msg)

    result = parse_robot_username(robot_username)
    if result is None:
        raise InvalidRobotException("%s is an invalid robot name" %
                                    robot_username)

    robot = lookup_robot(robot_username)
    assert robot.robot

    # Lookup the token for the robot.
    try:
        token_data = RobotAccountToken.get(robot_account=robot)
        if not token_data.token.matches(password):
            msg = "Could not find robot with username: %s and supplied password." % robot_username
            raise InvalidRobotException(msg)
    except RobotAccountToken.DoesNotExist:
        msg = "Could not find robot with username: %s and supplied password." % robot_username
        raise InvalidRobotException(msg)

    # Find the owner user and ensure it is not disabled.
    try:
        owner = User.get(User.username == result[0])
    except User.DoesNotExist:
        raise InvalidRobotException("Robot %s owner does not exist" %
                                    robot_username)

    if not owner.enabled:
        raise InvalidRobotException(
            "This user has been disabled. Please contact your administrator.")

    # Mark that the robot was accessed.
    _basequery.update_last_accessed(robot)

    return robot
예제 #23
0
def populate_database(minimal=False):
    logger.debug("Populating the DB with test data.")

    # Check if the data already exists. If so, we skip. This can happen between calls from the
    # "old style" tests and the new py.test's.
    try:
        User.get(username="******")
        logger.debug("DB already populated")
        return
    except User.DoesNotExist:
        pass

    # Note: databases set up with "real" schema (via Alembic) will not have these types
    # type, so we it here it necessary.
    try:
        ImageStorageLocation.get(name="local_eu")
        ImageStorageLocation.get(name="local_us")
    except ImageStorageLocation.DoesNotExist:
        ImageStorageLocation.create(name="local_eu")
        ImageStorageLocation.create(name="local_us")

    try:
        NotificationKind.get(name="test_notification")
    except NotificationKind.DoesNotExist:
        NotificationKind.create(name="test_notification")

    new_user_1 = model.user.create_user("devtable", "password",
                                        "*****@*****.**")
    new_user_1.verified = True
    new_user_1.stripe_id = TEST_STRIPE_ID
    new_user_1.save()

    if minimal:
        logger.debug(
            "Skipping most db population because user requested mininal db")
        return

    UserRegion.create(user=new_user_1,
                      location=ImageStorageLocation.get(name="local_us"))
    model.release.set_region_release("quay", "us", "v0.1.2")

    model.user.create_confirm_email_code(new_user_1,
                                         new_email="*****@*****.**")

    disabled_user = model.user.create_user("disabled", "password",
                                           "*****@*****.**")
    disabled_user.verified = True
    disabled_user.enabled = False
    disabled_user.save()

    dtrobot = model.user.create_robot("dtrobot", new_user_1)
    dtrobot2 = model.user.create_robot("dtrobot2", new_user_1)

    new_user_2 = model.user.create_user("public", "password",
                                        "*****@*****.**")
    new_user_2.verified = True
    new_user_2.save()

    new_user_3 = model.user.create_user("freshuser", "password",
                                        "*****@*****.**")
    new_user_3.verified = True
    new_user_3.save()

    another_robot = model.user.create_robot("anotherrobot", new_user_3)

    new_user_4 = model.user.create_user("randomuser", "password",
                                        "*****@*****.**")
    new_user_4.verified = True
    new_user_4.save()

    new_user_5 = model.user.create_user("unverified", "password",
                                        "*****@*****.**")
    new_user_5.save()

    reader = model.user.create_user("reader", "password", "*****@*****.**")
    reader.verified = True
    reader.save()

    creatoruser = model.user.create_user("creator", "password",
                                         "*****@*****.**")
    creatoruser.verified = True
    creatoruser.save()

    outside_org = model.user.create_user("outsideorg", "password",
                                         "*****@*****.**")
    outside_org.verified = True
    outside_org.save()

    model.notification.create_notification(
        "test_notification",
        new_user_1,
        metadata={
            "some": "value",
            "arr": [1, 2, 3],
            "obj": {
                "a": 1,
                "b": 2
            }
        },
    )

    from_date = datetime.utcnow()
    to_date = from_date + timedelta(hours=1)
    notification_metadata = {
        "from_date": formatdate(calendar.timegm(from_date.utctimetuple())),
        "to_date": formatdate(calendar.timegm(to_date.utctimetuple())),
        "reason": "database migration",
    }
    model.notification.create_notification("maintenance",
                                           new_user_1,
                                           metadata=notification_metadata)

    __generate_repository(
        new_user_4,
        "randomrepo",
        "Random repo repository.",
        False,
        [],
        (4, [], ["latest", "prod"]),
    )

    simple_repo = __generate_repository(
        new_user_1,
        "simple",
        "Simple repository.",
        False,
        [],
        (4, [], ["latest", "prod"]),
    )

    # Add some labels to the latest tag's manifest.
    repo_ref = RepositoryReference.for_repo_obj(simple_repo)
    tag = registry_model.get_repo_tag(repo_ref, "latest")
    manifest = registry_model.get_manifest_for_tag(tag)
    assert manifest

    first_label = registry_model.create_manifest_label(manifest, "foo", "bar",
                                                       "manifest")
    registry_model.create_manifest_label(manifest, "foo", "baz", "api")
    registry_model.create_manifest_label(manifest, "anotherlabel", "1234",
                                         "internal")
    registry_model.create_manifest_label(manifest, "jsonlabel",
                                         '{"hey": "there"}', "internal",
                                         "application/json")

    label_metadata = {
        "key": "foo",
        "value": "bar",
        "id": first_label._db_id,
        "manifest_digest": manifest.digest,
    }

    logs_model.log_action(
        "manifest_label_add",
        new_user_1.username,
        performer=new_user_1,
        timestamp=datetime.now(),
        metadata=label_metadata,
        repository=simple_repo,
    )

    model.blob.initiate_upload(new_user_1.username, simple_repo.name,
                               str(uuid4()), "local_us", {})
    model.notification.create_repo_notification(simple_repo, "repo_push",
                                                "quay_notification", {}, {})

    __generate_repository(
        new_user_1,
        "sharedtags",
        "Shared tags repository",
        False,
        [(new_user_2, "read"), (dtrobot[0], "read")],
        (
            2,
            [
                (3, [], ["v2.0", "v2.1", "v2.2"]),
                (
                    1,
                    [(1, [(1, [], ["prod", "581a284"])
                          ], ["staging", "8423b58"]), (1, [], None)],
                    None,
                ),
            ],
            None,
        ),
    )

    __generate_repository(
        new_user_1,
        "history",
        "Historical repository.",
        False,
        [],
        (4, [(2, [], "#latest"), (3, [], "latest")], None),
    )

    __generate_repository(
        new_user_1,
        "complex",
        "Complex repository with many branches and tags.",
        False,
        [(new_user_2, "read"), (dtrobot[0], "read")],
        (
            2,
            [(3, [], "v2.0"),
             (1, [(1, [(2, [], ["prod"])], "staging"), (1, [], None)], None)],
            None,
        ),
    )

    __generate_repository(
        new_user_1,
        "gargantuan",
        None,
        False,
        [],
        (
            2,
            [
                (3, [], "v2.0"),
                (1, [(1, [(1, [], ["latest", "prod"])], "staging"),
                     (1, [], None)], None),
                (20, [], "v3.0"),
                (5, [], "v4.0"),
                (1, [(1, [], "v5.0"), (1, [], "v6.0")], None),
            ],
            None,
        ),
    )

    trusted_repo = __generate_repository(
        new_user_1,
        "trusted",
        "Trusted repository.",
        False,
        [],
        (4, [], ["latest", "prod"]),
    )
    trusted_repo.trust_enabled = True
    trusted_repo.save()

    publicrepo = __generate_repository(
        new_user_2,
        "publicrepo",
        "Public repository pullable by the world.",
        True,
        [],
        (10, [], "latest"),
    )

    __generate_repository(outside_org, "coolrepo", "Some cool repo.", False,
                          [], (5, [], "latest"))

    __generate_repository(
        new_user_1,
        "shared",
        "Shared repository, another user can write.",
        False,
        [(new_user_2, "write"), (reader, "read")],
        (5, [], "latest"),
    )

    __generate_repository(
        new_user_1,
        "text-full-repo",
        "This is a repository for testing text search",
        False,
        [(new_user_2, "write"), (reader, "read")],
        (5, [], "latest"),
    )

    building = __generate_repository(
        new_user_1,
        "building",
        "Empty repository which is building.",
        False,
        [(new_user_2, "write"), (reader, "read")],
        (0, [], None),
    )

    new_token = model.token.create_access_token(building, "write",
                                                "build-worker")

    trigger = model.build.create_build_trigger(building,
                                               "github",
                                               "123authtoken",
                                               new_user_1,
                                               pull_robot=dtrobot[0])
    trigger.config = json.dumps({
        "build_source": "jakedt/testconnect",
        "subdir": "",
        "dockerfile_path": "Dockerfile",
        "context": "/",
    })
    trigger.save()

    repo = "ci.devtable.com:5000/%s/%s" % (building.namespace_user.username,
                                           building.name)
    job_config = {
        "repository": repo,
        "docker_tags": ["latest"],
        "build_subdir": "",
        "trigger_metadata": {
            "commit": "3482adc5822c498e8f7db2e361e8d57b3d77ddd9",
            "ref": "refs/heads/master",
            "default_branch": "master",
        },
    }

    model.repository.star_repository(new_user_1, simple_repo)

    record = model.repository.create_email_authorization_for_repo(
        new_user_1.username, "simple", "*****@*****.**")
    record.confirmed = True
    record.save()

    model.repository.create_email_authorization_for_repo(
        new_user_1.username, "simple", "*****@*****.**")

    build2 = model.build.create_repository_build(
        building,
        new_token,
        job_config,
        "68daeebd-a5b9-457f-80a0-4363b882f8ea",
        "build-name",
        trigger,
    )
    build2.uuid = "deadpork-dead-pork-dead-porkdeadpork"
    build2.save()

    build3 = model.build.create_repository_build(
        building,
        new_token,
        job_config,
        "f49d07f9-93da-474d-ad5f-c852107c3892",
        "build-name",
        trigger,
    )
    build3.uuid = "deadduck-dead-duck-dead-duckdeadduck"
    build3.save()

    build1 = model.build.create_repository_build(
        building, new_token, job_config, "701dcc3724fb4f2ea6c31400528343cd",
        "build-name", trigger)
    build1.uuid = "deadbeef-dead-beef-dead-beefdeadbeef"
    build1.save()

    org = model.organization.create_organization("buynlarge",
                                                 "*****@*****.**",
                                                 new_user_1)
    org.stripe_id = TEST_STRIPE_ID
    org.save()

    liborg = model.organization.create_organization(
        "library", "*****@*****.**", new_user_1)
    liborg.save()

    titiorg = model.organization.create_organization("titi",
                                                     "*****@*****.**",
                                                     new_user_1)
    titiorg.save()

    thirdorg = model.organization.create_organization(
        "sellnsmall", "*****@*****.**", new_user_1)
    thirdorg.save()

    model.user.create_robot("coolrobot", org)

    oauth_app_1 = model.oauth.create_application(
        org,
        "Some Test App",
        "http://localhost:8000",
        "http://localhost:8000/o2c.html",
        client_id="deadbeef",
    )

    model.oauth.create_application(
        org,
        "Some Other Test App",
        "http://quay.io",
        "http://localhost:8000/o2c.html",
        client_id="deadpork",
        description="This is another test application",
    )

    model.oauth.create_user_access_token(new_user_1,
                                         "deadbeef",
                                         "repo:admin",
                                         access_token="%s%s" %
                                         ("b" * 40, "c" * 40))

    oauth_credential = Credential.from_string("dswfhasdf1")
    OAuthAuthorizationCode.create(
        application=oauth_app_1,
        code="Z932odswfhasdf1",
        scope="repo:admin",
        data='{"somejson": "goeshere"}',
        code_name="Z932odswfhasdf1Z932o",
        code_credential=oauth_credential,
    )

    model.user.create_robot("neworgrobot", org)

    ownerbot = model.user.create_robot("ownerbot", org)[0]
    creatorbot = model.user.create_robot("creatorbot", org)[0]

    owners = model.team.get_organization_team("buynlarge", "owners")
    owners.description = "Owners have unfetterd access across the entire org."
    owners.save()

    org_repo = __generate_repository(
        org,
        "orgrepo",
        "Repository owned by an org.",
        False,
        [(outside_org, "read")],
        (4, [], ["latest", "prod"]),
    )

    __generate_repository(
        org,
        "anotherorgrepo",
        "Another repository owned by an org.",
        False,
        [],
        (4, [], ["latest", "prod"]),
    )

    creators = model.team.create_team("creators", org, "creator",
                                      "Creators of orgrepo.")

    reader_team = model.team.create_team("readers", org, "member",
                                         "Readers of orgrepo.")
    model.team.add_or_invite_to_team(new_user_1, reader_team, outside_org)
    model.permission.set_team_repo_permission(reader_team.name,
                                              org_repo.namespace_user.username,
                                              org_repo.name, "read")

    model.team.add_user_to_team(new_user_2, reader_team)
    model.team.add_user_to_team(reader, reader_team)
    model.team.add_user_to_team(ownerbot, owners)
    model.team.add_user_to_team(creatorbot, creators)
    model.team.add_user_to_team(creatoruser, creators)

    sell_owners = model.team.get_organization_team("sellnsmall", "owners")
    sell_owners.description = "Owners have unfettered access across the entire org."
    sell_owners.save()

    model.team.add_user_to_team(new_user_4, sell_owners)

    sync_config = {
        "group_dn": "cn=Test-Group,ou=Users",
        "group_id": "somegroupid"
    }
    synced_team = model.team.create_team("synced", org, "member",
                                         "Some synced team.")
    model.team.set_team_syncing(synced_team, "ldap", sync_config)

    another_synced_team = model.team.create_team("synced", thirdorg, "member",
                                                 "Some synced team.")
    model.team.set_team_syncing(another_synced_team, "ldap",
                                {"group_dn": "cn=Test-Group,ou=Users"})

    __generate_repository(
        new_user_1,
        "superwide",
        None,
        False,
        [],
        [
            (10, [], "latest2"),
            (2, [], "latest3"),
            (2, [(1, [], "latest11"), (2, [], "latest12")], "latest4"),
            (2, [], "latest5"),
            (2, [], "latest6"),
            (2, [], "latest7"),
            (2, [], "latest8"),
            (2, [], "latest9"),
            (2, [], "latest10"),
            (2, [], "latest13"),
            (2, [], "latest14"),
            (2, [], "latest15"),
            (2, [], "latest16"),
            (2, [], "latest17"),
            (2, [], "latest18"),
        ],
    )

    mirror_repo = __generate_repository(
        new_user_1,
        "mirrored",
        "Mirrored repository.",
        False,
        [(dtrobot[0], "write"), (dtrobot2[0], "write")],
        (4, [], ["latest", "prod"]),
    )
    mirror_rule = model.repo_mirror.create_mirroring_rule(
        mirror_repo, ["latest", "3.3*"])
    mirror_args = (mirror_repo, mirror_rule, dtrobot[0], "quay.io/coreos/etcd",
                   60 * 60 * 24)
    mirror_kwargs = {
        "external_registry_username": "******",
        "external_registry_password": "******",
        "external_registry_config": {},
        "is_enabled": True,
        "sync_start_date": datetime.utcnow(),
    }
    mirror = model.repo_mirror.enable_mirroring_for_repository(
        *mirror_args, **mirror_kwargs)

    read_only_repo = __generate_repository(
        new_user_1,
        "readonly",
        "Read-Only Repo.",
        False,
        [],
        (4, [], ["latest", "prod"]),
    )
    read_only_repo.state = RepositoryState.READ_ONLY
    read_only_repo.save()

    model.permission.add_prototype_permission(org,
                                              "read",
                                              activating_user=new_user_1,
                                              delegate_user=new_user_2)
    model.permission.add_prototype_permission(org,
                                              "read",
                                              activating_user=new_user_1,
                                              delegate_team=reader_team)
    model.permission.add_prototype_permission(org,
                                              "write",
                                              activating_user=new_user_2,
                                              delegate_user=new_user_1)

    today = datetime.today()
    week_ago = today - timedelta(6)
    six_ago = today - timedelta(5)
    four_ago = today - timedelta(4)
    yesterday = datetime.combine(date.today(),
                                 datetime.min.time()) - timedelta(hours=6)

    __generate_service_key("kid1", "somesamplekey", new_user_1, today,
                           ServiceKeyApprovalType.SUPERUSER)
    __generate_service_key(
        "kid2",
        "someexpiringkey",
        new_user_1,
        week_ago,
        ServiceKeyApprovalType.SUPERUSER,
        today + timedelta(days=14),
    )

    __generate_service_key("kid3", "unapprovedkey", new_user_1, today, None)

    __generate_service_key(
        "kid4",
        "autorotatingkey",
        new_user_1,
        six_ago,
        ServiceKeyApprovalType.KEY_ROTATION,
        today + timedelta(days=1),
        rotation_duration=timedelta(hours=12).total_seconds(),
    )

    __generate_service_key(
        "kid5",
        "key for another service",
        new_user_1,
        today,
        ServiceKeyApprovalType.SUPERUSER,
        today + timedelta(days=14),
        service="different_sample_service",
    )

    __generate_service_key(
        "kid6",
        "someexpiredkey",
        new_user_1,
        week_ago,
        ServiceKeyApprovalType.SUPERUSER,
        today - timedelta(days=1),
    )

    __generate_service_key(
        "kid7",
        "somewayexpiredkey",
        new_user_1,
        week_ago,
        ServiceKeyApprovalType.SUPERUSER,
        today - timedelta(days=30),
    )

    # Add the test pull key as pre-approved for local and unittest registry testing.
    # Note: this must match the private key found in the local/test config.
    _TEST_JWK = {
        "e":
        "AQAB",
        "kty":
        "RSA",
        "n":
        "yqdQgnelhAPMSeyH0kr3UGePK9oFOmNfwD0Ymnh7YYXr21VHWwyM2eVW3cnLd9KXywDFtGSe9oFDbnOuMCdUowdkBcaHju-isbv5KEbNSoy_T2Rip-6L0cY63YzcMJzv1nEYztYXS8wz76pSK81BKBCLapqOCmcPeCvV9yaoFZYvZEsXCl5jjXN3iujSzSF5Z6PpNFlJWTErMT2Z4QfbDKX2Nw6vJN6JnGpTNHZvgvcyNX8vkSgVpQ8DFnFkBEx54PvRV5KpHAq6AsJxKONMo11idQS2PfCNpa2hvz9O6UZe-eIX8jPo5NW8TuGZJumbdPT_nxTDLfCqfiZboeI0Pw",
    }

    key = model.service_keys.create_service_key("test_service_key",
                                                "test_service_key", "quay",
                                                _TEST_JWK, {}, None)

    model.service_keys.approve_service_key(
        key.kid,
        ServiceKeyApprovalType.SUPERUSER,
        notes="Test service key for local/test registry testing",
    )

    # Add an app specific token.
    token = model.appspecifictoken.create_token(new_user_1, "some app")
    token.token_name = "a" * 60
    token.token_secret = "b" * 60
    token.save()

    logs_model.log_action(
        "org_create_team",
        org.username,
        performer=new_user_1,
        timestamp=week_ago,
        metadata={"team": "readers"},
    )

    logs_model.log_action(
        "org_set_team_role",
        org.username,
        performer=new_user_1,
        timestamp=week_ago,
        metadata={
            "team": "readers",
            "role": "read"
        },
    )

    logs_model.log_action(
        "create_repo",
        org.username,
        performer=new_user_1,
        repository=org_repo,
        timestamp=week_ago,
        metadata={
            "namespace": org.username,
            "repo": "orgrepo"
        },
    )

    logs_model.log_action(
        "change_repo_permission",
        org.username,
        performer=new_user_2,
        repository=org_repo,
        timestamp=six_ago,
        metadata={
            "username": new_user_1.username,
            "repo": "orgrepo",
            "role": "admin"
        },
    )

    logs_model.log_action(
        "change_repo_permission",
        org.username,
        performer=new_user_1,
        repository=org_repo,
        timestamp=six_ago,
        metadata={
            "username": new_user_2.username,
            "repo": "orgrepo",
            "role": "read"
        },
    )

    logs_model.log_action(
        "add_repo_accesstoken",
        org.username,
        performer=new_user_1,
        repository=org_repo,
        timestamp=four_ago,
        metadata={
            "repo": "orgrepo",
            "token": "deploytoken"
        },
    )

    logs_model.log_action(
        "push_repo",
        org.username,
        performer=new_user_2,
        repository=org_repo,
        timestamp=today,
        metadata={
            "username": new_user_2.username,
            "repo": "orgrepo"
        },
    )

    logs_model.log_action(
        "pull_repo",
        org.username,
        performer=new_user_2,
        repository=org_repo,
        timestamp=today,
        metadata={
            "username": new_user_2.username,
            "repo": "orgrepo"
        },
    )

    logs_model.log_action(
        "pull_repo",
        org.username,
        repository=org_repo,
        timestamp=today,
        metadata={
            "token": "sometoken",
            "token_code": "somecode",
            "repo": "orgrepo"
        },
    )

    logs_model.log_action(
        "delete_tag",
        org.username,
        performer=new_user_2,
        repository=org_repo,
        timestamp=today,
        metadata={
            "username": new_user_2.username,
            "repo": "orgrepo",
            "tag": "sometag"
        },
    )

    logs_model.log_action(
        "pull_repo",
        org.username,
        repository=org_repo,
        timestamp=today,
        metadata={
            "token_code": "somecode",
            "repo": "orgrepo"
        },
    )

    logs_model.log_action(
        "pull_repo",
        new_user_2.username,
        repository=publicrepo,
        timestamp=yesterday,
        metadata={
            "token_code": "somecode",
            "repo": "publicrepo"
        },
    )

    logs_model.log_action(
        "build_dockerfile",
        new_user_1.username,
        repository=building,
        timestamp=today,
        metadata={
            "repo": "building",
            "namespace": new_user_1.username,
            "trigger_id": trigger.uuid,
            "config": json.loads(trigger.config),
            "service": trigger.service.name,
        },
    )

    model.message.create([{
        "content": "We love you, Quay customers!",
        "severity": "info",
        "media_type": "text/plain",
    }])

    model.message.create([{
        "content": "This is a **development** install of Quay",
        "severity": "warning",
        "media_type": "text/markdown",
    }])

    fake_queue = WorkQueue("fakequeue", tf)
    fake_queue.put(["canonical", "job", "name"], "{}")

    model.user.create_user_prompt(new_user_4, "confirm_username")

    for to_count in Repository.select():
        model.repositoryactioncount.count_repository_actions(
            to_count, datetime.utcnow())
        model.repositoryactioncount.update_repository_score(to_count)
예제 #24
0
def verify_user(username_or_email, password):
    """
    Verifies that the given username/email + password pair is valid.

    If the username or e-mail address is invalid, returns None. If the password specified does not
    match for the given user, either returns None or raises TooManyLoginAttemptsException if there
    have been too many invalid login attempts. Returns the user object if the login was valid.
    """

    # Make sure we didn't get any unicode for the username.
    try:
        username_or_email.encode("ascii")
    except UnicodeEncodeError:
        return None

    # Fetch the user with the matching username or e-mail address.
    try:
        fetched = User.get((User.username == username_or_email)
                           | (User.email == username_or_email))
    except User.DoesNotExist:
        return None

    # If the user has any invalid login attempts, check to see if we are within the exponential
    # backoff window for the user. If so, we raise an exception indicating that the user cannot
    # login.
    now = datetime.utcnow()
    if fetched.invalid_login_attempts > 0:
        can_retry_at = exponential_backoff(fetched.invalid_login_attempts,
                                           EXPONENTIAL_BACKOFF_SCALE,
                                           fetched.last_invalid_login)

        if can_retry_at > now:
            retry_after = can_retry_at - now
            raise TooManyLoginAttemptsException("Too many login attempts.",
                                                retry_after.total_seconds())

    # Hash the given password and compare it to the specified password.
    if (fetched.password_hash
            and hash_password(password, fetched.password_hash).decode("ascii")
            == fetched.password_hash):
        # If the user previously had any invalid login attempts, clear them out now.
        if fetched.invalid_login_attempts > 0:
            try:
                (User.update(invalid_login_attempts=0).where(
                    User.id == fetched.id).execute())

                # Mark that the user was accessed.
                _basequery.update_last_accessed(fetched)
            except ReadOnlyModeException:
                pass

        # Return the valid user.
        return fetched

    # Otherwise, update the user's invalid login attempts.
    try:
        (User.update(
            invalid_login_attempts=User.invalid_login_attempts + 1,
            last_invalid_login=now).where(User.id == fetched.id).execute())
    except ReadOnlyModeException:
        pass

    # We weren't able to authorize the user
    return None
예제 #25
0
def get_user_or_org_by_customer_id(customer_id):
    try:
        return User.get(User.stripe_id == customer_id)
    except User.DoesNotExist:
        return None
예제 #26
0
def get_user_by_uuid(user_uuid):
    try:
        return User.get(User.uuid == user_uuid, User.organization == False)
    except User.DoesNotExist:
        return None
예제 #27
0
def get_user_or_org(username):
    try:
        return User.get(User.username == username, User.robot == False)
    except User.DoesNotExist:
        return None
예제 #28
0
def get_namespace_user(username):
    try:
        return User.get(User.username == username)
    except User.DoesNotExist:
        return None
예제 #29
0
def get_user(username):
    try:
        return User.get(User.username == username, User.organization == False)
    except User.DoesNotExist:
        return None
예제 #30
0
def find_user_by_email(email):
    try:
        return User.get(User.email == email)
    except User.DoesNotExist:
        return None