Ejemplo n.º 1
0
 def wrapper(context, request):
     qs = QueryString(request)
     type_filters = qs.get_type_filters()
     if len(type_filters) != 1:
         raise HTTPBadRequest(
             explanation='URL requires one type parameter.'
         )
     if type_filters[0][1] not in types:
         raise HTTPBadRequest(
             explanation=f'{type_filters[0][1]} not a valid type for endpoint.'
         )
     return func(context, request)
Ejemplo n.º 2
0
def popup_toggle(request):
    """
    Toggle whether the user is configured to receive fedmsg popups in the web UI.

    Args:
        request (pyramid.util.Request): The current request.
    Returns:
        pyramid.httpexceptions.HTTPFound: A redirect to the "next" field of the request, or the home
            page if "next" is not defined.
    Raises:
        pyramid.exceptions.HTTPForbidden: If the user is not logged in.
        pyramid.httpexceptions.HTTPBadRequest: If the user is not found. It is unknown under which
            circumstances this could happen.
    """
    # Get the user
    userid = request.authenticated_userid
    if userid is None:
        raise HTTPForbidden("You must be logged in.")
    user = request.db.query(
        models.User).filter_by(name=unicode(userid)).first()
    if user is None:
        raise HTTPBadRequest("For some reason, user does not exist.")

    # Toggle the value.
    user.show_popups = not user.show_popups

    # And send the user back
    return_to = request.params.get('next', request.route_url('home'))
    return HTTPFound(location=return_to)
Ejemplo n.º 3
0
def table_item_save(request):
    person_id = None
    if ('person_id' in request.POST) and request.POST['person_id'].isdigit():
        person_id = int(request.POST['person_id'])

    user_login = request.POST[
        'user_login'] if 'user_login' in request.POST else None
    if not user_login:
        raise HTTPBadRequest('"user_login" is required parameter')

    if not person_id:
        users = DBSession.query(User).filter(User.login == user_login).all()
        if len(users) > 0:
            return {
                'Result': 'Error',
                'Message': u'Такой логин уже присутствует в системе'
            }

    with transaction.manager:
        if person_id:
            person = DBSession.query(Person) \
                .options(joinedload('user')) \
                .filter(Person.id == person_id) \
                .all()[0]
            user = person.user
        else:
            person = Person()
            DBSession.add(person)
            user = User()
            DBSession.add(user)
            person.user = user

        for attr in request.POST:
            table_name, field = attr.split('_')
            if field == 'id':
                continue
            if table_name == 'person':
                setattr(person, field, request.POST[attr])
            if table_name == 'user':
                setattr(user, field, request.POST[attr])

        if 'user_active' in request.POST and request.POST['user_active']:
            user.active = True
        else:
            user.active = False

        if 'user_password' in request.POST and request.POST['user_password']:
            user.password = User.password_hash(request.POST['user_password'])

        DBSession.flush()

        DBSession.refresh(user)
        DBSession.refresh(person)

        person_json = person.as_json_dict('person_')
        user_json = user.as_json_dict('user_')
        item_json = person_json.copy()
        item_json.update(user_json)

    return {'Result': 'OK', 'Record': item_json}
Ejemplo n.º 4
0
def receive_events(request):
    json_body = request.json_body
    parsed_events_set = EventsSetSchema().loads(json_body)
    if len(parsed_events_set.errors.keys()) > 0:
        raise HTTPBadRequest()
    last_update_ts = int(parsed_events_set.data['stop'])

    events = []
    if 'data' in parsed_events_set.data:
        events = parsed_events_set.data['data']

    events_to_insert = []
    for event in events:
        existed = DBSession.query(exists().where(Event.event_id==event.event_id)).scalar()
        exists_in_inserted_list = any(ev.event_id == event.event_id for ev in events_to_insert)
        if not existed and not exists_in_inserted_list:
            events_to_insert.append(event)

    with transaction.manager:
        Meta.filter_by(key=LAST_UPDATE_KEY).update({
            'value': last_update_ts
        })
        for event in events_to_insert:
            DBSession.add(event)
    return response_ok(dict(
        count=len(events),
        start=parsed_events_set.data['start'],
        stop=parsed_events_set.data['stop'],
        lastUpdateTs=last_update_ts
    ))
Ejemplo n.º 5
0
    def __init__(self, req: "CamcopsRequest") -> None:
        # Check the basics
        if req.method != RequestMethod.POST:
            raise HTTPBadRequest("Must use POST method")
            # ... this is for humans to view, so it has a pretty error

        # Read key things
        self.req = req
        self.operation = req.get_str_param(TabletParam.OPERATION)
        self.device_name = req.get_str_param(TabletParam.DEVICE)
        self.username = req.get_str_param(TabletParam.USER)
        self.password = req.get_str_param(TabletParam.PASSWORD)
        self.session_id = req.get_int_param(TabletParam.SESSION_ID)
        self.session_token = req.get_str_param(TabletParam.SESSION_TOKEN)
        self.tablet_version_str = req.get_str_param(TabletParam.CAMCOPS_VERSION)  # noqa
        try:
            self.tablet_version_ver = make_version(self.tablet_version_str)
        except ValueError:
            fail_user_error("CamCOPS tablet version nonsensical: {!r}".format(
                self.tablet_version_str))

        # Basic security check: no pretending to be the server
        if self.device_name == DEVICE_NAME_FOR_SERVER:
            fail_user_error("Tablets cannot use the device name {!r}".format(
                DEVICE_NAME_FOR_SERVER))
        if self.username == USER_NAME_FOR_SYSTEM:
            fail_user_error("Tablets cannot use the username {!r}".format(
                USER_NAME_FOR_SYSTEM))

        self._device_obj = None  # type: Device

        # Ensure table version is OK
        if self.tablet_version_ver < MINIMUM_TABLET_VERSION:
            fail_user_error(
                "Tablet CamCOPS version too old: is {v}, need {r}".format(
                    v=self.tablet_version_str,
                    r=MINIMUM_TABLET_VERSION))
        # Other version things are done via properties

        # Upload efficiency
        self._dirty_table_names = set()  # type: Set[str]

        # Report
        log.info("Incoming client API connection from IP={i}, port={p}, "
                 "device_name={dn!r}, "
                 # "device_id={di}, "
                 "camcops_version={v}, "
                 "username={u}, operation={o}",
                 i=req.remote_addr,
                 p=req.remote_port,
                 dn=self.device_name,
                 # di=self.device_id,
                 v=self.tablet_version_str,
                 u=self.username,
                 o=self.operation)
Ejemplo n.º 6
0
    def view_manage(self):
        post = self.request.POST
        action = post.get('action')
        if action == 'move':
            _from = post.get('from')
            _to = post.get('to')
            if _from is None or _to is None:
                # return Response(body='"from" and "to" request params are missing',
                #                 content_type='text/plain',
                #                 status_int=400)
                return HTTPBadRequest('"from" and "to" request params are missing')
            from_path = get_abs_path(_from)
            to_path = get_abs_path(_to)
            if os.path.isdir(to_path):
                return HTTPBadRequest('The "to" path is directory. Full end path of file must be specified')
            if not os.path.isfile(from_path):
                return HTTPBadRequest('There no file at the path passed with "to" parameter')
            try:
                os.rename(from_path, to_path)
            except Exception:
                # TODO log exception?
                return HTTPBadRequest('error during file moving')

            rel_to_path = get_rel_path(to_path)
            return rel_to_path
        elif action == 'delete':
            _path = post.get('path')
            if _path is None:
                return HTTPBadRequest('"path" request param is missing')
            delete_path = get_abs_path(_path)
            if os.path.isdir(delete_path):
                return HTTPBadRequest('The "to" path is directory. Full end path of file must be specified')
            if not os.path.isfile(delete_path):
                return HTTPBadRequest('There no file at the path passed with "path" parameter')
            try:
                os.remove(delete_path)
            except Exception:
                return HTTPBadRequest('error during file deletion')

            rel_delete_path = get_rel_path(delete_path)
            return rel_delete_path
        else:
            # return Response(body='"action" request param is missing',
            #                 content_type='text/plain',
            #                 status_int=400)
            return HTTPBadRequest('"action" request param is missing')
Ejemplo n.º 7
0
def on_update_record(event):
    if getattr(event.request, '_attachment_auto_save', False):
        # Record attributes are being by the plugin itself.
        return

    # A user is changing the record, make sure attachment metadata is not
    # altered manually.
    for change in event.impacted_records:
        attachment_before = change['old'].get('attachment')
        attachment_after = change['new'].get('attachment')
        if attachment_before and attachment_after:
            if attachment_before != attachment_after:
                error_msg = "Attachment metadata cannot be modified."
                raise http_error(HTTPBadRequest(), message=error_msg)
Ejemplo n.º 8
0
def latest_builds_in_tag(request):
    """
    Return a list of the latest builds for a given tag.

    Args:
        request (pyramid.request.Request): The current request. The request's "tag" parameter is
            used to pass the koji tagname being queried.
    Returns:
        dict: A dictionary of the release dist tag to the latest build.
    """
    koji = request.koji
    tag = request.params.get('tag')
    if not tag:
        raise HTTPBadRequest("tag parameter is required")
    else:
        return koji.listTagged(tag, latest=True)
Ejemplo n.º 9
0
def popup_toggle(request):
    # Get the user
    from bodhi.models import User
    userid = authenticated_userid(request)
    if userid is None:
        raise HTTPForbidden("You must be logged in.")
    user = request.db.query(User).filter_by(name=unicode(userid)).first()
    if user is None:
        raise HTTPBadRequest("For some reason, user does not exist.")

    # Toggle the value.
    user.show_popups = not user.show_popups

    # And send the user back
    return_to = request.params.get('next', request.route_url('home'))
    return HTTPFound(location=return_to)
Ejemplo n.º 10
0
def put_some_bacon(request):
    raise HTTPBadRequest()
Ejemplo n.º 11
0
    def render(data, system):
        """
        Render the given data as an RSS view.

        If the request's content type is set to the default, this function will change it to
        application/rss+xml.

        Args:
            data (dict): A dictionary describing the information to be rendered. The information can
                be different types of objects, such as updates, users, comments, or overrides.
            system (pyramid.events.BeforeRender): Used to get the current request.
        Returns:
            str: An RSS document representing the given data.
        """
        request = system.get('request')
        if request is not None:
            response = request.response
            ct = response.content_type
            if ct == response.default_content_type:
                response.content_type = 'application/rss+xml'

        if 'updates' in data:
            key = 'updates'
            feed_title = 'Released updates'
        elif 'users' in data:
            key = 'users'
            feed_title = 'Bodhi users'
        elif 'comments' in data:
            key = 'comments'
            feed_title = 'User comments'
        elif 'overrides' in data:
            key = 'overrides'
            feed_title = 'Update overrides'
        else:
            # This is a request we don't know how to render. Let's return BadRequest and log.
            log.debug('Unable to render RSS feed for data: %s', data)
            # See if we have a request so we can set a code without raising an Exception
            if request is not None:
                response.status = HTTPBadRequest.code
                return 'Invalid RSS feed request'
            else:
                raise HTTPBadRequest('Invalid RSS feed request')

        feed_description_list = []
        for k in request.GET.keys():
            feed_description_list.append('%s(%s)' % (k, request.GET[k]))
        if feed_description_list:
            feed_description = 'Filtered on: ' + ', '.join(
                feed_description_list)
        else:
            feed_description = "All %s" % (key)

        feed = FeedGenerator()
        feed.title(feed_title)
        feed.link(href=request.url, rel='self')
        feed.description(feed_description)
        feed.language('en')

        def linker(route, param, key):
            def link_dict(obj):
                return dict(href=request.route_url(route, **{param: obj[key]}))

            return link_dict

        def describe_update(alias, notes, builds):
            """
            Wrap calls to operator.itemgetter to retrieve notes and builds list.

            Methods are used to fill feed entry values, so we must use a wrapper
            to get an HTML formatted description from the `notes` and the `builds`
            properties of the update.

            For example:
            getter = describe_update(operator.itemgetter('notes'),operator.itemgetter('builds'))
            description_value = getter(update_data)

            Args:
                alias (operator.itemgetter): A callable object which returns update alias
                    as string.
                notes (operator.itemgetter): A callable object which returns update notes
                    as string.
                builds (operator.itemgetter): A callable object which returns a list of builds
                    associated to the update.
            Returns:
                function: A function which accepts a dict representing an update as parameter.
            """
            def describe(*args, **kwargs):
                text = f'# {alias(*args, **kwargs)}\n'
                text += f'## Packages in this update:\n'
                for p in builds(*args, **kwargs):
                    text += f'* {p.nvr}\n'
                text += f'## Update description:\n{notes(*args, **kwargs)}'
                return markup(None, text)

            return describe

        getters = {
            'updates': {
                'title':
                operator.itemgetter('title'),
                'link':
                linker('update', 'id', 'alias'),
                'description':
                describe_update(operator.itemgetter('alias'),
                                operator.itemgetter('notes'),
                                operator.itemgetter('builds')),
                'pubDate':
                lambda obj: utc.localize(obj['date_submitted']),
            },
            'users': {
                'title': operator.itemgetter('name'),
                'link': linker('user', 'name', 'name'),
                'description': operator.itemgetter('name'),
            },
            'comments': {
                'title': operator.itemgetter('rss_title'),
                'link': linker('comment', 'id', 'id'),
                'description': operator.itemgetter('text'),
                'pubDate': lambda obj: utc.localize(obj['timestamp']),
            },
            'overrides': {
                'title': operator.itemgetter('nvr'),
                'link': linker('override', 'nvr', 'nvr'),
                'description': operator.itemgetter('notes'),
                'pubDate': lambda obj: utc.localize(obj['submission_date']),
            },
        }

        for value in reversed(data[key]):
            feed_item = feed.add_item()
            for name, getter in getters[key].items():
                # Because we have to use methods to fill feed entry attributes,
                # it's done by getting methods by name and calling them
                # on the same line.
                getattr(feed_item, name)(getter(value))

        return feed.rss_str()
Ejemplo n.º 12
0
    def render(data, system):
        """
        Render the given data as an RSS view.

        If the request's content type is set to the default, this function will change it to
        application/rss+xml.

        Args:
            data (dict): A dictionary describing the information to be rendered. The information can
                be different types of objects, such as updates, users, comments, or overrides.
            system (pyramid.events.BeforeRender): Used to get the current request.
        Returns:
            str: An RSS document representing the given data.
        """
        request = system.get('request')
        if request is not None:
            response = request.response
            ct = response.content_type
            if ct == response.default_content_type:
                response.content_type = 'application/rss+xml'

        if 'updates' in data:
            key = 'updates'
            feed_title = 'Released updates'
        elif 'users' in data:
            key = 'users'
            feed_title = 'Bodhi users'
        elif 'comments' in data:
            key = 'comments'
            feed_title = 'User comments'
        elif 'overrides' in data:
            key = 'overrides'
            feed_title = 'Update overrides'
        else:
            # This is a request we don't know how to render. Let's return BadRequest and log.
            log.debug('Unable to render RSS feed for data: %s', data)
            # See if we have a request so we can set a code without raising an Exception
            if request is not None:
                response.status = HTTPBadRequest.code
                return 'Invalid RSS feed request'
            else:
                raise HTTPBadRequest('Invalid RSS feed request')

        feed_description_list = []
        for k in request.GET.keys():
            feed_description_list.append('%s(%s)' % (k, request.GET[k]))
        if feed_description_list:
            feed_description = 'Filtered on: ' + ', '.join(
                feed_description_list)
        else:
            feed_description = "All %s" % (key)

        feed = FeedGenerator()
        feed.title(feed_title)
        feed.link(href=request.url, rel='self')
        feed.description(feed_description)
        feed.language('en')

        def linker(route, param, key):
            def link_dict(obj):
                return dict(href=request.route_url(route, **{param: obj[key]}))

            return link_dict

        getters = {
            'updates': {
                'title': operator.itemgetter('alias'),
                'link': linker('update', 'id', 'alias'),
                'description': operator.itemgetter('notes'),
                'pubdate': lambda obj: utc.localize(obj['date_submitted']),
            },
            'users': {
                'title': operator.itemgetter('name'),
                'link': linker('user', 'name', 'name'),
                'description': operator.itemgetter('name'),
            },
            'comments': {
                'title': operator.itemgetter('rss_title'),
                'link': linker('comment', 'id', 'id'),
                'description': operator.itemgetter('text'),
                'pubdate': lambda obj: utc.localize(obj['timestamp']),
            },
            'overrides': {
                'title': operator.itemgetter('nvr'),
                'link': linker('override', 'nvr', 'nvr'),
                'description': operator.itemgetter('notes'),
                'pubdate': lambda obj: utc.localize(obj['submission_date']),
            },
        }

        for value in data[key]:
            feed_item = feed.add_item()
            for name, getter in getters[key].items():
                # Because we have to use methods to fill feed entry attributes,
                # it's done by getting methods by name and calling them
                # on the same line.
                getattr(feed_item, name)(getter(value))

        return feed.rss_str()