Ejemplo n.º 1
0
def test_disabled(mocker, db_session, default_user, default_repo,
                  default_repo_access, default_source, outbox):
    auth.set_current_tenant(
        auth.Tenant(repository_ids=[default_source.repository_id]))

    build = factories.BuildFactory(source=default_source, failed=True)
    db_session.add(build)
    db_session.add(
        ItemOption(item_id=default_user.id,
                   name='mail.notify_author',
                   value='0'))
    db_session.flush()

    send_email_notification(build)

    assert len(outbox) == 0
Ejemplo n.º 2
0
def test_invalid_public_key(mocker, db_session, default_repo):
    option = ItemOption(item_id=default_repo.id,
                        name="auth.private-key",
                        value="foo")
    db_session.add(option)
    db_session.flush()

    mock_vcs_backend = mocker.MagicMock(spec=Vcs)
    mocker.patch.object(Repository, "get_vcs", return_value=mock_vcs_backend)

    mock_vcs_backend.exists.return_value = False
    mock_vcs_backend.clone.side_effect = InvalidPublicKey(["git", "clone"], 1)

    sync_repo(repo_id=default_repo.id)

    assert default_repo.status == RepositoryStatus.inactive
    assert not ItemOption.query.get(option.id)
Ejemplo n.º 3
0
def test_deactivate_repo(db_session, default_repo, default_repo_access,
                         default_user, outbox):
    db_session.add(
        ItemOption(item_id=default_repo.id, name="auth.private-key", value=""))
    db_session.flush()

    deactivate_repo(default_repo.id, DeactivationReason.invalid_pubkey)

    assert not ItemOption.query.filter(ItemOption.item_id == default_repo.id,
                                       ItemOption.name
                                       == "auth.private-key").first()
    assert default_repo.status == RepositoryStatus.inactive

    assert len(outbox) == 1
    msg = outbox[0]
    assert msg.subject == "Repository Disabled - getsentry/zeus"
    assert msg.recipients == [default_user.email]
Ejemplo n.º 4
0
def test_disabled(
    mocker,
    db_session,
    default_user,
    default_repo,
    default_repo_access,
    default_source,
    default_tenant,
    outbox,
):
    build = factories.BuildFactory(source=default_source, failed=True)
    db_session.add(build)
    db_session.add(
        ItemOption(item_id=default_user.id,
                   name="mail.notify_author",
                   value="0"))
    db_session.flush()

    send_email_notification(build)

    assert len(outbox) == 0
Ejemplo n.º 5
0
    def post(self):
        """
        Activate a GitHub repository.
        """
        repo_name = (request.get_json() or {}).get('name')
        if not repo_name:
            return self.error('missing repo_name parameter')

        user = auth.get_current_user()
        try:
            github, _ = self.get_github_client(user)
        except IdentityNeedsUpgrade as exc:
            return self.respond(
                {
                    'error': 'identity_needs_upgrade',
                    'url': exc.get_upgrade_url(),
                }, 401)

        # fetch repository details using their credentials
        repo_data = github.get('/repos/{}'.format(repo_name))
        owner_name, repo_name = repo_data['full_name'].split('/', 1)

        repo = Repository.query.filter(
            Repository.provider == RepositoryProvider.github,
            Repository.external_id == str(repo_data['id']),
        ).first()
        if repo is None:
            # bind various github specific attributes
            repo = Repository(
                backend=RepositoryBackend.git,
                provider=RepositoryProvider.github,
                status=RepositoryStatus.active,
                external_id=str(repo_data['id']),
                owner_name=owner_name,
                name=repo_name,
                url=repo_data['clone_url'],
                data={'github': {
                    'full_name': repo_data['full_name']
                }},
            )
            db.session.add(repo)

            # generate a new private key for use on github
            key = ssh.generate_key()
            db.session.add(
                ItemOption(
                    item_id=repo.id,
                    name='auth.private-key',
                    value=key.private_key,
                ))

            # register key with github
            github.post('/repos/{}/keys'.format(
                repo.data['github']['full_name']),
                        json={
                            'title': 'zeus',
                            'key': key.public_key,
                            'read_only': True,
                        })
            # we need to commit before firing off the task
            db.session.commit()

            import_repo.delay(repo_id=repo.id)

        try:
            with db.session.begin_nested():
                db.session.add(
                    RepositoryAccess(
                        repository_id=repo.id,
                        user_id=user.id,
                    ))
                db.session.flush()
        except IntegrityError:
            pass

        db.session.commit()
        return self.respond_with_schema(repo_schema, repo, 201)
Ejemplo n.º 6
0
    def post(self):
        """
        Activate a GitHub repository.
        """
        repo_name = (request.get_json() or {}).get('name')
        if not repo_name:
            return self.error('missing repo_name parameter')

        owner_name, repo_name = repo_name.split('/', 1)

        user = auth.get_current_user()
        provider = GitHubRepositoryProvider(cache=False)
        try:
            repo_data = provider.get_repo(user=user,
                                          owner_name=owner_name,
                                          repo_name=repo_name)
        except IdentityNeedsUpgrade as exc:
            return self.respond(
                {
                    'provider': 'github',
                    'error': 'identity_needs_upgrade',
                    'url': exc.get_upgrade_url(),
                }, 401)

        if not repo_data['admin']:
            return self.respond(
                {
                    'message':
                    'Insufficient permissions to activate repository',
                }, 403)

        lock_key = 'repo:{provider}/{owner_name}/{repo_name}'.format(
            provider='github',
            owner_name=owner_name,
            repo_name=repo_name,
        )
        with redis.lock(lock_key):
            try:
                with db.session.begin_nested():
                    # bind various github specific attributes
                    repo = Repository(
                        backend=RepositoryBackend.git,
                        provider=RepositoryProvider.github,
                        status=RepositoryStatus.active,
                        external_id=str(repo_data['id']),
                        owner_name=owner_name,
                        name=repo_name,
                        url=repo_data['url'],
                        data=repo_data['config'],
                    )
                    db.session.add(repo)
                    db.session.flush()
            except IntegrityError:
                repo = Repository.query.unrestricted_unsafe().filter(
                    Repository.provider == RepositoryProvider.github,
                    Repository.external_id == str(repo_data['id']),
                ).first()
                # it's possible to get here if the "full name" already exists
                assert repo
                needs_configured = repo.status == RepositoryStatus.inactive
                if needs_configured:
                    repo.status = RepositoryStatus.active
                    db.session.add(repo)
            else:
                needs_configured = True
            if needs_configured:
                # generate a new private key for use on github
                key = ssh.generate_key()
                db.session.add(
                    ItemOption(
                        item_id=repo.id,
                        name='auth.private-key',
                        value=key.private_key,
                    ))

                # register key with github
                provider.add_key(
                    user=user,
                    repo_name=repo_name,
                    owner_name=owner_name,
                    key=key,
                )

                # we need to commit before firing off the task
                db.session.commit()

                import_repo.delay(repo_id=repo.id)

        try:
            with db.session.begin_nested():
                db.session.add(
                    RepositoryAccess(
                        repository_id=repo.id,
                        user_id=user.id,
                    ))
                db.session.flush()
        except IntegrityError:
            pass

        db.session.commit()

        return self.respond_with_schema(repo_schema, repo, 201)
Ejemplo n.º 7
0
    def post(self):
        """
        Activate a GitHub repository.
        """
        repo_name = (request.get_json() or {}).get("name")
        if not repo_name:
            return self.error("missing repo_name parameter")

        owner_name, repo_name = repo_name.split("/", 1)

        user = auth.get_current_user()
        provider = GitHubRepositoryProvider(cache=False)
        try:
            repo_data = provider.get_repo(user=user,
                                          owner_name=owner_name,
                                          repo_name=repo_name)
        except IdentityNeedsUpgrade as exc:
            return self.respond(
                {
                    "provider": "github",
                    "error": "identity_needs_upgrade",
                    "url": exc.get_upgrade_url(),
                },
                401,
            )

        if Permission.admin not in repo_data["permission"]:
            return self.respond(
                {"message": "Insufficient permissions to activate repository"},
                403)

        lock_key = Repository.get_lock_key(RepositoryProvider.github,
                                           owner_name, repo_name)
        with redis.lock(lock_key):
            try:
                with db.session.begin_nested():
                    # bind various github specific attributes
                    repo = Repository(
                        backend=RepositoryBackend.git,
                        provider=RepositoryProvider.github,
                        status=RepositoryStatus.active,
                        external_id=str(repo_data["id"]),
                        owner_name=owner_name,
                        name=repo_name,
                        url=repo_data["url"],
                        data=repo_data["config"],
                    )
                    db.session.add(repo)
                    db.session.flush()
            except IntegrityError:
                repo = (Repository.query.unrestricted_unsafe().filter(
                    Repository.provider == RepositoryProvider.github,
                    Repository.external_id == str(repo_data["id"]),
                ).first())
                # it's possible to get here if the "full name" already exists
                assert repo
                needs_configured = repo.status == RepositoryStatus.inactive
                if needs_configured:
                    repo.status = RepositoryStatus.active
                    db.session.add(repo)
            else:
                needs_configured = True
            if needs_configured:
                # generate a new private key for use on github
                key = ssh.generate_key()
                db.session.add(
                    ItemOption(item_id=repo.id,
                               name="auth.private-key",
                               value=key.private_key))

                # register key with github
                # TODO(dcramer): we should store this key reference so we can delete it
                # when the user deactivates the repo
                provider.add_key(user=user,
                                 repo_name=repo_name,
                                 owner_name=owner_name,
                                 key=key)

                db.session.commit()

        try:
            with db.session.begin_nested():
                db.session.add(
                    RepositoryAccess(
                        repository_id=repo.id,
                        user_id=user.id,
                        permission=repo_data["permission"],
                    ))
                db.session.flush()
        except IntegrityError:
            pass

        db.session.commit()

        return self.respond_with_schema(repo_schema, repo, 201)
Ejemplo n.º 8
0
    def post(self, org: Organization):
        """
        Create a new repository.
        """
        provider = (request.get_json() or {}).get('provider', 'native')

        if provider == 'github':
            schema = github_repo_schema
        elif provider == 'native':
            schema = repo_schema
        else:
            raise NotImplementedError

        result = self.schema_from_request(schema, partial=True)
        if result.errors:
            return self.respond(result.errors, 403)
        data = result.data

        if provider == 'github':
            # get their credentials
            identity = Identity.query.filter(
                Identity.provider == 'github', Identity.user_id == auth.get_current_user().id
            ).first()
            if 'repo' not in identity.config['scopes']:
                return self.respond(
                    {
                        'needUpgrade': True,
                        'upgradeUrl': '/auth/github/upgrade'
                    }, 401
                )
            assert identity

            # fetch repository details using their credentials
            github = GitHubClient(token=identity.config['access_token'])
            repo_data = github.get('/repos/{}'.format(data['github_name']))

            repo, created = Repository.query.filter(
                Repository.provider == RepositoryProvider.github,
                Repository.external_id == str(repo_data['id']),
            ).first(), False
            if repo is None:
                # bind various github specific attributes
                repo, created = Repository(
                    organization=org,
                    backend=RepositoryBackend.git,
                    provider=RepositoryProvider.github,
                    status=RepositoryStatus.active,
                    external_id=str(repo_data['id']),
                    url=repo_data['clone_url'],
                    data={'github': {
                        'full_name': repo_data['full_name']
                    }},
                ), True
                db.session.add(repo)

                # generate a new private key for use on github
                key = ssh.generate_key()
                db.session.add(
                    ItemOption(
                        item_id=repo.id,
                        name='auth.private-key',
                        value=key.private_key,
                    )
                )

                # register key with github
                github.post(
                    '/repos/{}/keys'.format(repo.data['github']['full_name']),
                    json={
                        'title': 'zeus',
                        'key': key.public_key,
                        'read_only': True,
                    }
                )
        elif provider == 'native':
            repo, created = Repository(
                organization=org,
                status=RepositoryStatus.active,
                **data,
            ), True
            db.session.add(repo)

        db.session.flush()

        try:
            with db.session.begin_nested():
                db.session.add(
                    RepositoryAccess(
                        organization=org,
                        repository=repo,
                        user=auth.get_current_user(),
                    )
                )
                db.session.flush()
        except IntegrityError:
            raise
            pass

        db.session.commit()

        if created:
            import_repo.delay(repo_id=repo.id)

        return self.respond_with_schema(repo_schema, repo)