예제 #1
0
def create_users(user):
    values = v1_utils.common_values_dict(user)
    values.update(schemas.user.post(flask.request.json))

    if not (auth.is_admin(user)
            or auth.is_admin_user(user, values['team_id'])):
        raise auth.UNAUTHORIZED

    role_id = values.get('role_id', auth.get_role_id('USER'))
    if not auth.is_admin(user) and role_id == auth.get_role_id('SUPER_ADMIN'):
        raise auth.UNAUTHORIZED

    values.update({
        'password': auth.hash_password(values.get('password')),
        'role_id': role_id
    })

    query = _TABLE.insert().values(**values)

    try:
        flask.g.db_conn.execute(query)
    except sa_exc.IntegrityError:
        raise dci_exc.DCICreationConflict(_TABLE.name, 'name')

    # remove the password in the result for security reasons
    del values['password']

    return flask.Response(json.dumps({'user': values}),
                          201,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
예제 #2
0
def put_user(user, user_id):
    # get If-Match header
    if_match_etag = utils.check_and_get_etag(flask.request.headers)
    values = schemas.user.put(flask.request.json)

    puser = dict(_verify_existence_and_get_user(user_id))

    if puser['id'] != str(user_id):
        if not (auth.is_admin(user)
                or auth.is_admin_user(user, puser['team_id'])):
            raise auth.UNAUTHORIZED

    # TODO(yassine): if the user wants to change the team, then check its done
    # by a super admin. ie. team_name='admin'

    values['etag'] = utils.gen_etag()

    if 'password' in values:
        values['password'] = auth.hash_password(values.get('password'))

    where_clause = sql.and_(_TABLE.c.etag == if_match_etag,
                            _TABLE.c.id == user_id)
    query = _TABLE.update().where(where_clause).values(**values)

    result = flask.g.db_conn.execute(query)

    if not result.rowcount:
        raise dci_exc.DCIConflict('User', user_id)

    return flask.Response(None,
                          204,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
예제 #3
0
def get_all_tests(user, topic_id):
    args = schemas.args(flask.request.args.to_dict())
    if not (auth.is_admin(user)):
        v1_utils.verify_team_in_topic(user, topic_id)
    v1_utils.verify_existence_and_get(topic_id, _TABLE)

    query = sql.select([models.TESTS]).\
        select_from(models.JOIN_TOPICS_TESTS.join(models.TESTS)).\
        where(models.JOIN_TOPICS_TESTS.c.topic_id == topic_id)

    T_COLUMNS = v1_utils.get_columns_name_with_objects(models.TESTS)
    sort_list = v1_utils.sort_query(args['sort'], T_COLUMNS)
    where_list = v1_utils.where_query(args['where'], models.TESTS, T_COLUMNS)

    query = v1_utils.add_sort_to_query(query, sort_list)
    query = v1_utils.add_where_to_query(query, where_list)
    if args.get('limit', None):
        query = query.limit(args.get('limit'))
    if args.get('offset', None):
        query = query.offset(args.get('offset'))

    rows = flask.g.db_conn.execute(query).fetchall()

    query_nb_rows = sql.select([func.count(models.TESTS.c.id)]). \
        select_from(models.JOIN_TOPICS_TESTS.join(models.TESTS)). \
        where(models.JOIN_TOPICS_TESTS.c.topic_id == topic_id)
    nb_rows = flask.g.db_conn.execute(query_nb_rows).scalar()

    res = flask.jsonify({'tests': rows, '_meta': {'count': nb_rows}})
    res.status_code = 200
    return res
예제 #4
0
def get_resource_by_id(user, resource, table, embed_many, ignore_columns=None):
    args = schemas.args(flask.request.args.to_dict())
    resource_name = table.name[0:-1]
    resource_id = resource['id']
    columns = v1_utils.get_columns_name_with_objects(table)

    query = v1_utils.QueryBuilder(table, args, columns, ignore_columns)

    if not auth.is_admin(user) and 'team_id' in resource:
        query.add_extra_condition(table.c.team_id == user['team_id'])

    if 'state' in resource:
        query.add_extra_condition(table.c.state != 'archived')

    query.add_extra_condition(table.c.id == resource_id)

    rows = query.execute(fetchall=True)
    rows = v1_utils.format_result(rows, table.name, args['embed'], embed_many)

    if len(rows) < 1:
        raise dci_exc.DCINotFound(resource_name, resource_id)
    resource = rows[0]

    res = flask.jsonify({resource_name: resource})

    if 'etag' in resource:
        res.headers.add_header('ETag', resource['etag'])

    return res
예제 #5
0
def put_topic(user, topic_id):
    # get If-Match header
    if_match_etag = utils.check_and_get_etag(flask.request.headers)

    values = schemas.topic.put(flask.request.json)

    if not auth.is_admin(user):
        raise auth.UNAUTHORIZED

    def _verify_team_in_topic(user, topic_id):
        topic_id = v1_utils.verify_existence_and_get(topic_id,
                                                     _TABLE,
                                                     get_id=True)
        # verify user's team in the topic
        v1_utils.verify_team_in_topic(user, topic_id)
        return topic_id

    topic_id = _verify_team_in_topic(user, topic_id)

    if 'next_topic' in values and values['next_topic']:
        _verify_team_in_topic(user, values['next_topic'])

    values['etag'] = utils.gen_etag()
    where_clause = sql.and_(_TABLE.c.etag == if_match_etag,
                            _TABLE.c.id == topic_id)
    query = _TABLE.update().where(where_clause).values(**values)

    result = flask.g.db_conn.execute(query)
    if not result.rowcount:
        raise dci_exc.DCIConflict('Topic', topic_id)

    return flask.Response(None,
                          204,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
예제 #6
0
def create_remotecis(user):
    values = v1_utils.common_values_dict(user)
    values.update(schemas.remoteci.post(flask.request.json))

    # If it's not a super admin nor belongs to the same team_id
    if not (auth.is_admin(user)
            or auth.is_in_team(user, values.get('team_id'))):
        raise auth.UNAUTHORIZED

    values.update({
        'data': values.get('data', {}),
        # XXX(fc): this should be populated as a default value from the
        # model, but we don't return values from the database :(
        'api_secret': signature.gen_secret(),
    })

    query = _TABLE.insert().values(**values)

    try:
        flask.g.db_conn.execute(query)
    except sa_exc.IntegrityError:
        raise dci_exc.DCICreationConflict(_TABLE.name, 'name')

    return flask.Response(json.dumps({'remoteci': values}),
                          201,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
예제 #7
0
def put_api_secret(user, r_id):
    # get If-Match header
    if_match_etag = utils.check_and_get_etag(flask.request.headers)

    remoteci = v1_utils.verify_existence_and_get(r_id, _TABLE)

    if not (auth.is_admin(user) or auth.is_in_team(user, remoteci['team_id'])):
        raise auth.UNAUTHORIZED

    where_clause = sql.and_(
        _TABLE.c.etag == if_match_etag,
        _TABLE.c.id == r_id,
    )
    values = {'api_secret': signature.gen_secret(), 'etag': utils.gen_etag()}

    query = (_TABLE.update().where(where_clause).values(**values))

    result = flask.g.db_conn.execute(query)

    if not result.rowcount:
        raise dci_exc.DCIConflict('RemoteCI', r_id)

    res = flask.jsonify(({
        'id': r_id,
        'etag': values['etag'],
        'api_secret': values['api_secret']
    }))
    res.headers.add_header('ETag', values['etag'])
    return res
예제 #8
0
def delete_job_by_id(user, j_id):
    # get If-Match header
    if_match_etag = utils.check_and_get_etag(flask.request.headers)

    job = v1_utils.verify_existence_and_get(j_id, _TABLE)

    if not (auth.is_admin(user) or auth.is_in_team(user, job['team_id'])):
        raise auth.UNAUTHORIZED

    with flask.g.db_conn.begin():
        values = {'state': 'archived'}
        where_clause = sql.and_(_TABLE.c.id == j_id,
                                _TABLE.c.etag == if_match_etag)
        query = _TABLE.update().where(where_clause).values(**values)

        result = flask.g.db_conn.execute(query)

        if not result.rowcount:
            raise dci_exc.DCIDeleteConflict('Job', j_id)

        for model in [models.FILES]:
            query = model.update().where(model.c.job_id == j_id).values(
                **values
            )
            flask.g.db_conn.execute(query)

    return flask.Response(None, 204, content_type='application/json')
예제 #9
0
def get_all_results_from_jobs(user, j_id):
    """Get all results from job.
    """

    job = v1_utils.verify_existence_and_get(j_id, _TABLE)

    # If it's an admin or belongs to the same team
    if not(auth.is_admin(user) or auth.is_in_team(user, job['team_id'])):
        raise auth.UNAUTHORIZED

    swift = dci_config.get_store('files')
    job_files = json.loads(files.get_all_files(j_id).response[0])['files']
    r_files = [file for file in job_files
               if file['mime'] == 'application/junit']

    results = []
    for file in r_files:
        file_path = swift.build_file_path(file['team_id'],
                                          j_id,
                                          file['id'])
        content_file = swift.get_object(file_path)
        data = tsfm.junit2dict(content_file)
        results.append({'filename': file['name'],
                        'name': file['name'],
                        'total': data['total'],
                        'failures': data['failures'],
                        'errors': data['errors'],
                        'skips': data['skips'],
                        'time': data['time'],
                        'success': data['success'],
                        'testscases': data['testscases']})

    return flask.jsonify({'results': results,
                          '_meta': {'count': len(results)}})
예제 #10
0
def put_remoteci(user, r_id):
    # get If-Match header
    if_match_etag = utils.check_and_get_etag(flask.request.headers)

    values = schemas.remoteci.put(flask.request.json)

    remoteci = v1_utils.verify_existence_and_get(r_id, _TABLE)

    if 'data' in values:
        remoteci_data = get_remoteci_data_json(user, r_id)
        remoteci_data.update(values['data'])
        values['data'] = {k: v for k, v in remoteci_data.items() if v}

    if not (auth.is_admin(user) or auth.is_in_team(user, remoteci['team_id'])):
        raise auth.UNAUTHORIZED

    values['etag'] = utils.gen_etag()
    where_clause = sql.and_(_TABLE.c.etag == if_match_etag,
                            _TABLE.c.state != 'archived', _TABLE.c.id == r_id)

    query = (_TABLE.update().where(where_clause).values(**values))

    result = flask.g.db_conn.execute(query)

    if not result.rowcount:
        raise dci_exc.DCIConflict('RemoteCI', r_id)

    return flask.Response(None,
                          204,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
예제 #11
0
def delete_team_by_id(user, t_id):
    # get If-Match header
    if_match_etag = utils.check_and_get_etag(flask.request.headers)

    if not auth.is_admin(user):
        raise auth.UNAUTHORIZED

    v1_utils.verify_existence_and_get(t_id, _TABLE)

    with flask.g.db_conn.begin():
        values = {'state': 'archived'}
        where_clause = sql.and_(_TABLE.c.etag == if_match_etag,
                                _TABLE.c.id == t_id)
        query = _TABLE.update().where(where_clause).values(**values)
        result = flask.g.db_conn.execute(query)

        if not result.rowcount:
            raise dci_exc.DCIDeleteConflict('Team', t_id)

        for model in [
                models.FILES, models.TESTS, models.REMOTECIS, models.USERS,
                models.JOBS
        ]:
            query = model.update().where(model.c.team_id == t_id).values(
                **values)
            flask.g.db_conn.execute(query)

    return flask.Response(None, 204, content_type='application/json')
예제 #12
0
def get_all_jobs(user, jd_id=None):
    """Get all jobs.

    If jd_id is not None, then return all the jobs with a jobdefinition
    pointed by jd_id.
    """
    # get the diverse parameters
    args = schemas.args(flask.request.args.to_dict())

    # build the query thanks to the QueryBuilder class
    query = v1_utils.QueryBuilder(_TABLE, args, _JOBS_COLUMNS,
                                  ['configuration'])

    # add extra conditions for filtering

    # # If not admin then restrict the view to the team
    if not auth.is_admin(user):
        query.add_extra_condition(_TABLE.c.team_id == user['team_id'])

    # # If jd_id not None, then filter by jobdefinition_id
    if jd_id is not None:
        query.add_extra_condition(_TABLE.c.jobdefinition_id == jd_id)

    # # Get only the non archived jobs
    query.add_extra_condition(_TABLE.c.state != 'archived')

    nb_rows = query.get_number_of_rows()
    rows = query.execute(fetchall=True)
    rows = v1_utils.format_result(rows, _TABLE.name, args['embed'],
                                  _EMBED_MANY)

    return flask.jsonify({'jobs': rows, '_meta': {'count': nb_rows}})
예제 #13
0
def put_team(user, t_id):
    # get If-Match header
    if_match_etag = utils.check_and_get_etag(flask.request.headers)

    values = schemas.team.put(flask.request.json)

    if not (auth.is_admin(user) or auth.is_admin_user(user, t_id)):
        raise auth.UNAUTHORIZED

    v1_utils.verify_existence_and_get(t_id, _TABLE)

    values['etag'] = utils.gen_etag()
    where_clause = sql.and_(_TABLE.c.etag == if_match_etag,
                            _TABLE.c.id == t_id)
    query = _TABLE.update().where(where_clause).values(**values)

    result = flask.g.db_conn.execute(query)

    if not result.rowcount:
        raise dci_exc.DCIConflict('Team', t_id)

    return flask.Response(None,
                          204,
                          headers={'ETag': values['etag']},
                          content_type='application/json')
예제 #14
0
def upload_component_file(user, c_id):
    if not auth.is_admin(user):
        raise auth.UNAUTHORIZED

    COMPONENT_FILES = models.COMPONENT_FILES

    component = v1_utils.verify_existence_and_get(c_id, _TABLE)

    swift = dci_config.get_store('components')

    file_id = utils.gen_uuid()
    file_path = swift.build_file_path(component['topic_id'], c_id, file_id)

    swift = dci_config.get_store('components')
    swift.upload(file_path, flask.request.stream)
    s_file = swift.head(file_path)

    values = dict.fromkeys(['md5', 'mime', 'component_id', 'name'])

    values.update({
        'id': file_id,
        'component_id': c_id,
        'name': file_id,
        'created_at': datetime.datetime.utcnow().isoformat(),
        'md5': s_file['etag'],
        'mime': s_file['content-type'],
        'size': s_file['content-length']
    })

    query = COMPONENT_FILES.insert().values(**values)

    flask.g.db_conn.execute(query)
    result = json.dumps({'component_file': values})
    return flask.Response(result, 201, content_type='application/json')
예제 #15
0
def get_topic_by_id(user, topic_id):
    args = schemas.args(flask.request.args.to_dict())
    topic = v1_utils.verify_existence_and_get(topic_id, _TABLE)
    v1_utils.verify_team_in_topic(user, topic_id)
    if not auth.is_admin(user):
        if 'teams' in args['embed']:
            raise dci_exc.DCIException('embed=teams not authorized.',
                                       status_code=401)

    return base.get_resource_by_id(user, topic, _TABLE, _EMBED_MANY)
예제 #16
0
def verify_team_in_topic(user, topic_id):
    """Verify that the user's team does belongs to the given topic. If
    the user is an admin then it belongs to all topics.
    """
    if auth.is_admin(user):
        return
    if str(topic_id) not in user_topic_ids(user):
        raise dci_exc.DCIException('User team does not belongs to topic %s.' %
                                   topic_id,
                                   status_code=412)
예제 #17
0
def verify_user_in_team(user, team_id):
    """Verify that the user belongs to a given team. If the user is an
    admin then it belongs to all teams."""

    if auth.is_admin(user):
        return
    if not auth.is_in_team(user, team_id):
        raise dci_exc.DCIException('User\'s team does not belongs to '
                                   'team %s.' % team_id,
                                   status_code=412)
예제 #18
0
def get_role_by_id(user, role_id):
    role = v1_utils.verify_existence_and_get(role_id, _TABLE)

    if user['role_id'] != role_id and \
        user['role_id'] not in [auth.get_role_id('ADMIN'),
                                auth.get_role_id('SUPER_ADMIN')]:
        raise auth.UNAUTHORIZED
    if not auth.is_admin(user) and auth.get_role_id('SUPER_ADMIN') == role_id:
        raise auth.UNAUTHORIZED

    return base.get_resource_by_id(user, role, _TABLE, _EMBED_MANY)
예제 #19
0
def get_remoteci_data_json(user, r_id):
    query = v1_utils.QueryBuilder(_TABLE, {}, _R_COLUMNS)

    if not auth.is_admin(user):
        query.add_extra_condition(_TABLE.c.team_id == user['team_id'])

    query.add_extra_condition(_TABLE.c.id == r_id)
    row = query.execute(fetchone=True)

    if row is None:
        raise dci_exc.DCINotFound('RemoteCI', r_id)

    return row['remotecis_data']
예제 #20
0
def purge_archived_resources(user, table):
    """Remove the entries to be purged from the database. """

    if not auth.is_admin(user):
        raise auth.UNAUTHORIZED

    where_clause = sql.and_(
        table.c.state == 'archived'
    )
    query = table.delete().where(where_clause)
    flask.g.db_conn.execute(query)

    return flask.Response(None, 204, content_type='application/json')
예제 #21
0
def get_all_roles(user):
    args = schemas.args(flask.request.args.to_dict())
    query = v1_utils.QueryBuilder(_TABLE, args, _T_COLUMNS)

    query.add_extra_condition(_TABLE.c.state != 'archived')

    if not auth.is_admin(user):
        query.add_extra_condition(_TABLE.c.label != 'SUPER_ADMIN')

    if not (auth.is_admin(user)
            or user['role_id'] == auth.get_role_id('PRODUCT_OWNER')):
        query.add_extra_condition(_TABLE.c.label != 'PRODUCT_OWNER')

    if user['role_id'] == auth.get_role_id('USER'):
        query.add_extra_condition(_TABLE.c.id == user['role_id'])

    nb_rows = query.get_number_of_rows()
    rows = query.execute(fetchall=True)
    rows = v1_utils.format_result(rows, _TABLE.name, args['embed'],
                                  _EMBED_MANY)

    return flask.jsonify({'roles': rows, '_meta': {'count': nb_rows}})
예제 #22
0
def get_to_purge_archived_resources(user, table):
    """List the entries to be purged from the database. """
    if not auth.is_admin(user):
        raise auth.UNAUTHORIZED

    where_clause = sql.and_(
        table.c.state == 'archived'
    )
    query = sql.select([table]).where(where_clause)
    result = flask.g.db_conn.execute(query).fetchall()

    return flask.jsonify({table.name: result,
                          '_meta': {'count': len(result)}})
예제 #23
0
def delete_test_from_topic(user, t_id, test_id):
    if not auth.is_admin(user):
        v1_utils.verify_team_in_topic(user, t_id)
    v1_utils.verify_existence_and_get(test_id, _TABLE)

    JDC = models.JOIN_REMOTECIS_TESTS
    where_clause = sql.and_(JDC.c.topic_id == t_id, JDC.c.test_id == test_id)
    query = JDC.delete().where(where_clause)
    result = flask.g.db_conn.execute(query)

    if not result.rowcount:
        raise dci_exc.DCIConflict('Test', test_id)

    return flask.Response(None, 204, content_type='application/json')
예제 #24
0
def get_all_teams_from_topic(user, topic_id):
    if not auth.is_admin(user):
        raise auth.UNAUTHORIZED

    topic_id = v1_utils.verify_existence_and_get(topic_id, _TABLE, get_id=True)

    # Get all teams which belongs to a given topic
    JTT = models.JOINS_TOPICS_TEAMS
    query = (sql.select([models.TEAMS]).select_from(JTT.join(
        models.TEAMS)).where(JTT.c.topic_id == topic_id))
    rows = flask.g.db_conn.execute(query)

    res = flask.jsonify({'teams': rows, '_meta': {'count': rows.rowcount}})
    return res
예제 #25
0
def search(user):
    values = schemas.search.post(flask.request.json)

    if values['refresh']:
        flask.g.es_conn.refresh()

    if auth.is_admin(user):
        res = flask.g.es_conn.search_content(values['pattern'])
    else:
        res = flask.g.es_conn.search_content(values['pattern'],
                                             user['team_id'])

    result = json.jsonify({'logs': res['hits']})
    return result
예제 #26
0
def add_test_to_topic(user, topic_id):
    if not auth.is_admin(user):
        raise auth.UNAUTHORIZED
    data_json = flask.request.json
    values = {'topic_id': topic_id, 'test_id': data_json.get('test_id', None)}

    v1_utils.verify_existence_and_get(topic_id, _TABLE)

    query = models.JOIN_TOPICS_TESTS.insert().values(**values)
    try:
        flask.g.db_conn.execute(query)
    except sa_exc.IntegrityError:
        raise dci_exc.DCICreationConflict(_TABLE.name, 'topic_id, test_id')
    result = json.dumps(values)
    return flask.Response(result, 201, content_type='application/json')
예제 #27
0
def delete_jobstate_by_id(user, js_id):
    jobstate = v1_utils.verify_existence_and_get(js_id, _TABLE)

    if not(auth.is_admin(user) or auth.is_in_team(user, jobstate['team_id'])):
        raise auth.UNAUTHORIZED

    where_clause = _TABLE.c.id == js_id
    query = _TABLE.delete().where(where_clause)

    result = flask.g.db_conn.execute(query)

    if not result.rowcount:
        raise dci_exc.DCIDeleteConflict('Jobstate', js_id)

    return flask.Response(None, 204, content_type='application/json')
예제 #28
0
def delete_permission_from_role(user, role_id, permission_id):
    if not auth.is_admin(user):
        raise auth.UNAUTHORIZED
    v1_utils.verify_existence_and_get(role_id, _TABLE)

    JRP = models.JOIN_ROLES_PERMISSIONS
    where_clause = sql.and_(JRP.c.role_id == role_id,
                            JRP.c.permission_id == permission_id)
    query = JRP.delete().where(where_clause)
    result = flask.g.db_conn.execute(query)

    if not result.rowcount:
        raise dci_exc.DCIConflict('Role', role_id)

    return flask.Response(None, 204, content_type='application/json')
예제 #29
0
def update_job_by_id(user, job_id):
    """Update a job
    """
    # get If-Match header
    if_match_etag = utils.check_and_get_etag(flask.request.headers)

    # get the diverse parameters
    values = schemas.job.put(flask.request.json)

    job = v1_utils.verify_existence_and_get(job_id, _TABLE)

    # If it's an admin or belongs to the same team
    if not(auth.is_admin(user) or auth.is_in_team(user, job['team_id'])):
        raise auth.UNAUTHORIZED

    # Update jobstate if needed
    status = values.get('status')
    if status and job.status != status:
        jobstates.insert_jobstate(user, {
            'status': status,
            'job_id': job_id
        })

    where_clause = sql.and_(_TABLE.c.etag == if_match_etag,
                            _TABLE.c.id == job_id)

    values['etag'] = utils.gen_etag()
    query = _TABLE.update().where(where_clause).values(**values)

    result = flask.g.db_conn.execute(query)

    if not result.rowcount:
        raise dci_exc.DCIConflict('Job', job_id)
    if values.get('status') == "failure":
        _TEAMS = models.TEAMS
        where_clause = sql.expression.and_(
            _TEAMS.c.id == job['team_id']
        )
        query = (sql.select([_TEAMS]).where(where_clause))
        team_info = flask.g.db_conn.execute(query).fetchone()
        if team_info['notification'] is True:
            if team_info['email'] is not None:
                msg = {'event': 'notification',
                       'email': team_info['email'],
                       'job_id': str(job['id'])}
                flask.g.sender.send_json(msg)
    return flask.Response(None, 204, headers={'ETag': values['etag']},
                          content_type='application/json')
예제 #30
0
def get_all_teams(user):
    args = schemas.args(flask.request.args.to_dict())

    query = v1_utils.QueryBuilder(_TABLE, args, _T_COLUMNS)

    if not auth.is_admin(user):
        query.add_extra_condition(_TABLE.c.id == user['team_id'])

    query.add_extra_condition(_TABLE.c.state != 'archived')

    nb_rows = query.get_number_of_rows()
    rows = query.execute(fetchall=True)
    rows = v1_utils.format_result(rows, _TABLE.name, args['embed'],
                                  _EMBED_MANY)

    return flask.jsonify({'teams': rows, '_meta': {'count': nb_rows}})