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)
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)