Esempio n. 1
0
    def delete(self, project_id, user_id):
        '''
        Remove collaborator from project
        '''

        collaborator = g.db.execute_one(
            """
            SELECT role FROM collaborator
            WHERE user_id = %s
            AND project_id = %s
            LIMIT 1
        """, [str(user_id), project_id])

        # Give some warning if the specified user has been already removed
        # from the collaborators or has been never added there before
        if not collaborator:
            return OK('Specified user is not in collaborators list.')

        if collaborator[0] == 'Owner':
            abort(400, "It's not allowed to delete the owner of the project.")

        g.db.execute(
            """
            DELETE FROM collaborator
            WHERE user_id = %s
            AND project_id = %s
        """, [str(user_id), project_id])

        g.db.commit()

        opa_push_collaborator_data(g.db)

        return OK('Successfully removed user.')
Esempio n. 2
0
    def post(self, project_id):
        '''
        Add a collaborator
        '''
        b = request.get_json()
        username = b['username']
        userrole = b['role'] if 'role' in b else 'Developer'

        # Prevent for now a project owner change
        # (Because with GitHub Integration the project owner's GitHub Token will be used)
        if userrole == 'Owner':
            abort(403, "A project is limited to one owner.")

        user = g.db.execute_one_dict(
            """
            SELECT * FROM "user"
            WHERE username = %s
        """, [username])

        if not user:
            abort(400, "User not found.")

        roles = g.db.execute_many("""
            SELECT unnest(enum_range(NULL::user_role))
        """)

        if [userrole] not in roles:
            abort(400, "Role unknown.")

        num_collaborators = g.db.execute_one(
            """
            SELECT COUNT(*) FROM collaborator
            WHERE user_id = %s
            AND project_id = %s
        """, [user['id'], project_id])[0]

        if num_collaborators != 0:
            return OK('Specified user is already a collaborator.')

        g.db.execute(
            """
            INSERT INTO collaborator (project_id, user_id, role)
            VALUES(%s, %s, %s) ON CONFLICT DO NOTHING
        """, [project_id, user['id'], userrole])
        g.db.commit()

        opa_push_collaborator_data(g.db)

        return OK('Successfully added user.')
Esempio n. 3
0
    def put(self, project_id, user_id):

        collaborator = g.db.execute_one(
            """
                    SELECT role FROM collaborator
                    WHERE user_id = %s
                    AND project_id = %s
                    LIMIT 1
                """, [str(user_id), project_id])

        if not collaborator:
            abort(400, 'Specified user is not in collaborators list.')

        if collaborator[0] == 'Owner':
            if count_owner(project_id) <= 1:
                abort(400, 'The project must have an owner.')
            if not is_valid_admin(project_id, g.token['user']['id']):
                abort(400, 'Not authorized to change owner')

        b = request.get_json()
        userrole = b['role']

        # Ensure that role is valid
        roles = g.db.execute_many("""
            SELECT unnest(enum_range(NULL::user_role))
        """)
        if [userrole] not in roles:
            abort(400, "Role unknown.")

        # Do update
        g.db.execute(
            """
            UPDATE collaborator
            SET role = %s
            WHERE user_id = %s
            AND project_id = %s
        """, [userrole, str(user_id), project_id])

        g.db.commit()

        opa_push_collaborator_data(g.db)

        return OK('Successfully changed user role.')
Esempio n. 4
0
    def post(self):
        '''
        Create new project
        '''
        user_id = g.token['user']['id']

        b = request.get_json()
        name = b['name']
        typ = b['type']
        private = b['private']

        projects = g.db.execute_one_dict(
            '''
            SELECT COUNT(*) as cnt
            FROM project p
            INNER JOIN collaborator co
            ON p.id = co.project_id
            AND co.user_id = %s
        ''', [user_id])

        if projects['cnt'] > 50:
            abort(400, 'too many projects')

        project = g.db.execute_one_dict(
            '''
            SELECT *
            FROM project
            WHERE name = %s
        ''', [name])

        if project:
            abort(400, 'A project with this name already exists')

        if typ == 'github':
            github_repo_name = b.get('github_repo_name', None)

            if not github_repo_name:
                abort(400, 'github_repo_name not set')

            split = github_repo_name.split('/')
            owner = split[0]
            repo_name = split[1]

            user = g.db.execute_one_dict(
                '''
                SELECT github_api_token
                FROM "user"
                WHERE id = %s
            ''', [user_id])

            if not user:
                abort(404)

            api_token = user['github_api_token']

            headers = {
                "Authorization": "token " + api_token,
                "User-Agent": "InfraBox"
            }
            url = '%s/repos/%s/%s' % (os.environ['INFRABOX_GITHUB_API_URL'],
                                      owner, repo_name)

            # TODO(ib-steffen): allow custom ca bundles
            r = requests.get(url, headers=headers, verify=False)

            if r.status_code != 200:
                abort(400, 'Failed to get github repo')

            repo = r.json()

            if not repo['permissions']['admin']:
                abort(400, 'You are not allowed to connect this repo')

            r = g.db.execute_one_dict(
                '''
                SELECT *
                FROM repository
                WHERE github_id = %s
            ''', [repo['id']])

            if r:
                abort('Repo already connected')

        project = g.db.execute_one_dict(
            '''
            INSERT INTO project (name, type, public)
            VALUES (%s, %s, %s) RETURNING id
        ''', [name, typ, not private])
        project_id = project['id']

        g.db.execute(
            '''
            INSERT INTO collaborator (user_id, project_id, role)
            VALUES (%s, %s, 'Owner')
        ''', [user_id, project_id])

        if typ == 'github':
            split = github_repo_name.split('/')
            owner = split[0]
            repo_name = split[1]

            clone_url = repo['clone_url']
            if repo['private']:
                clone_url = repo['ssh_url']

            g.db.execute(
                '''
                INSERT INTO repository (name, html_url, clone_url, github_id,
                                        private, project_id, github_owner)
                VALUES (%s, %s, %s, %s, %s, %s, %s)
            ''', [
                    repo['name'], repo['html_url'], clone_url, repo['id'],
                    repo['private'], project_id, repo['owner']['login']
                ])

            insecure_ssl = "0"
            if os.environ[
                    'INFRABOX_GENERAL_DONT_CHECK_CERTIFICATES'] == 'true':
                insecure_ssl = "1"

            webhook_config = {
                'name': "web",
                'active': True,
                'events':
                ["create", "delete", "public", "pull_request", "push"],
                'config': {
                    'url': get_root_url('global') + '/github/hook',
                    'content_type': "json",
                    'secret': os.environ['INFRABOX_GITHUB_WEBHOOK_SECRET'],
                    'insecure_ssl': insecure_ssl
                }
            }

            headers = {
                "Authorization": "token " + api_token,
                "User-Agent": "InfraBox"
            }
            url = '%s/repos/%s/%s/hooks' % (
                os.environ['INFRABOX_GITHUB_API_URL'], owner, repo_name)

            # TODO(ib-steffen): allow custom ca bundles
            r = requests.post(url,
                              headers=headers,
                              json=webhook_config,
                              verify=False)

            if r.status_code != 201:
                abort(400, 'Failed to create github webhook')

            hook = r.json()

            g.db.execute(
                '''
                UPDATE repository SET github_hook_id = %s
                WHERE github_id = %s
            ''', [hook['id'], repo['id']])

            # deploy key
            key = RSA.generate(2048)
            private_key = key.exportKey('PEM')
            public_key = key.publickey().exportKey('OpenSSH')
            deploy_key_config = {
                'title': "InfraBox",
                'key': public_key,
                'read_only': True
            }

            url = '%s/repos/%s/%s/keys' % (
                os.environ['INFRABOX_GITHUB_API_URL'], owner, repo_name)

            # TODO(ib-steffen): allow custom ca bundles
            r = requests.post(url,
                              headers=headers,
                              json=deploy_key_config,
                              verify=False)

            if r.status_code != 201:
                abort(400, 'Failed to create deploy key')

            g.db.execute(
                '''
                UPDATE repository SET private_key = %s
                WHERE github_id = %s
            ''', [private_key, repo['id']])

        elif typ == 'gerrit':
            g.db.execute(
                '''
                INSERT INTO repository (name, private, project_id, html_url, clone_url, github_id)
                VALUES (%s, false, %s, '', '', 0)
            ''', [name, project_id])

        g.db.commit()

        # Push updated collaborator and project data to Open Policy Agent
        opa_push_project_data(g.db)
        opa_push_collaborator_data(g.db)

        return OK('Project added')