Esempio n. 1
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)
Esempio n. 2
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)
    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)