예제 #1
0
파일: registration.py 프로젝트: NIIF/indico
 def _getParams(self):
     super(CheckInHook, self)._getParams()
     self._check_in = get_query_parameter(self._queryParams, ["checked_in"]) == "yes"
     self._secret = get_query_parameter(self._queryParams, ["secret"])
     registrant_id = self._pathParams["registrant_id"]
     self._conf = ConferenceHolder().getById(self._pathParams['event'])
     self._registrant = self._conf.getRegistrantById(registrant_id)
예제 #2
0
파일: api.py 프로젝트: OmeGak/indico
    def _getParams(self):
        super(BookRoomHook, self)._getParams()
        self._fromDT = utc_to_server(self._fromDT.astimezone(pytz.utc)).replace(tzinfo=None) if self._fromDT else None
        self._toDT = utc_to_server(self._toDT.astimezone(pytz.utc)).replace(tzinfo=None) if self._toDT else None
        if not self._fromDT or not self._toDT or self._fromDT.date() != self._toDT.date():
            raise HTTPAPIError('from/to must be on the same day')
        elif self._fromDT >= self._toDT:
            raise HTTPAPIError('to must be after from')
        elif self._fromDT < datetime.now():
            raise HTTPAPIError('You cannot make bookings in the past')

        username = get_query_parameter(self._queryParams, 'username')
        if not username:
            raise HTTPAPIError('No username provided')
        users = User.find_all(~User.is_deleted, Identity.identifier == username)
        if not users:
            raise HTTPAPIError('Username does not exist')
        elif len(users) != 1:
            raise HTTPAPIError('Ambiguous username ({} users found)'.format(len(users)))
        user = users[0]

        self._params = {
            'room_id': get_query_parameter(self._queryParams, 'roomid'),
            'reason': get_query_parameter(self._queryParams, 'reason'),
            'booked_for': user,
            'from': self._fromDT,
            'to': self._toDT
        }
        missing = [key for key, val in self._params.iteritems() if not val]
        if missing:
            raise HTTPAPIError('Required params missing: {}'.format(', '.join(missing)))
        self._room = Room.get(self._params['room_id'])
        if not self._room:
            raise HTTPAPIError('A room with this ID does not exist')
예제 #3
0
    def _getParams(self):
        super(BookRoomHook, self)._getParams()

        username = get_query_parameter(self._queryParams, ['username'])
        booked_for = AuthenticatorMgr().getAvatarByLogin(username).values()

        if not booked_for:
            raise HTTPAPIError('Username does not exist.')

        self._params = {
            'roomid': get_query_parameter(self._queryParams, ['roomid']),
            'location': get_query_parameter(self._queryParams, ['location']),
            'username': username,
            'reason': get_query_parameter(self._queryParams, ['reason']),
            'userBookedFor': booked_for[0],
            'from': self._fromDT,
            'to': self._toDT
            }

        # calculate missing arguments
        missing = list(name for (name, value) in (self._params.iteritems()) if not value)

        if missing:
            raise HTTPAPIError('Argument(s) missing: {0}'.format(', '.join(missing)), apache.HTTP_BAD_REQUEST)

        self._room = CrossLocationQueries.getRooms(location=self._params['location'], roomID=int(self._params['roomid']))
예제 #4
0
    def _getParams(self):
        super(BookRoomHook, self)._getParams()
        self._fromDT = utc_to_server(self._fromDT.astimezone(pytz.utc)).replace(tzinfo=None) if self._fromDT else None
        self._toDT = utc_to_server(self._toDT.astimezone(pytz.utc)).replace(tzinfo=None) if self._toDT else None
        if not self._fromDT or not self._toDT or self._fromDT.date() != self._toDT.date():
            raise HTTPAPIError('from/to must be on the same day')
        elif self._fromDT >= self._toDT:
            raise HTTPAPIError('to must be after from')
        elif self._fromDT < datetime.now():
            raise HTTPAPIError('You cannot make bookings in the past')

        username = get_query_parameter(self._queryParams, 'username')
        avatars = username and filter(None, AuthenticatorMgr().getAvatarByLogin(username).itervalues())
        if not avatars:
            raise HTTPAPIError('Username does not exist')
        elif len(avatars) != 1:
            raise HTTPAPIError('Ambiguous username ({} users found)'.format(len(avatars)))
        avatar = avatars[0]

        self._params = {
            'room_id': get_query_parameter(self._queryParams, 'roomid'),
            'reason': get_query_parameter(self._queryParams, 'reason'),
            'booked_for': avatar,
            'from': self._fromDT,
            'to': self._toDT
        }
        missing = [key for key, val in self._params.iteritems() if not val]
        if missing:
            raise HTTPAPIError('Required params missing: {}'.format(', '.join(missing)))
        self._room = Room.get(self._params['room_id'])
        if not self._room:
            raise HTTPAPIError('A room with this ID does not exist')
예제 #5
0
 def _getParams(self):
     super(UpdatePictureHook, self)._getParams()
     self._picture_payload = get_query_parameter(self._queryParams, ["picture_uri"])
     self._secret = get_query_parameter(self._queryParams, ["secret"])
     registrant_id = self._pathParams["registrant_id"]
     self._conf = ConferenceHolder().getById(self._pathParams['event'])
     self._registrant = self._conf.getRegistrantById(registrant_id)
예제 #6
0
 def _getParams(self):
     super(UpdatePassportHook, self)._getParams()
     raw_passport_info = str(get_query_parameter(self._queryParams, ["passport_info"]))
     self._passport_info = json.loads(raw_passport_info,object_hook=ascii_encode_dict)
     self._secret = get_query_parameter(self._queryParams, ["secret"])
     registrant_id = self._pathParams["registrant_id"]
     self._conf = ConferenceHolder().getById(self._pathParams['event'])
     self._registrant = self._conf.getRegistrantById(registrant_id)
예제 #7
0
파일: api.py 프로젝트: svdoever/indico
 def _getParams(self):
     super(SetPaidHook, self)._getParams()
     self.auth_key = get_query_parameter(self._queryParams, ["auth_key"])
     self.is_paid = get_query_parameter(self._queryParams, ["is_paid"]) == "yes"
     registrant_id = self._pathParams["registrant_id"]
     self._conf = ConferenceHolder().getById(self._pathParams['event'])
     self._registrant = self._conf.getRegistrantById(registrant_id)
     if not payment_event_settings.get(self._conf, 'enabled'):
         raise HTTPAPIError('E-payment is not enabled')
예제 #8
0
파일: api.py 프로젝트: bubbas/indico
 def _getParams(self):
     super(CategoryEventHook, self)._getParams()
     self._idList = self._pathParams['idlist'].split('-')
     self._eventType = get_query_parameter(self._queryParams, ['T', 'type'])
     if self._eventType == 'lecture':
         self._eventType = 'simple_event'
     self._occurrences = get_query_parameter(self._queryParams, ['occ', 'occurrences'], 'no') == 'yes'
     self._location = get_query_parameter(self._queryParams, ['l', 'location'])
     self._room = get_query_parameter(self._queryParams, ['r', 'room'])
예제 #9
0
 def _getParams(self):
     super(SetPaidHook, self)._getParams()
     self.auth_key = get_query_parameter(self._queryParams, ["auth_key"])
     self.is_paid = get_query_parameter(self._queryParams, ["is_paid"]) == "yes"
     registrant_id = self._pathParams["registrant_id"]
     self._conf = ConferenceHolder().getById(self._pathParams['event'])
     self._registrant = self._conf.getRegistrantById(registrant_id)
     self._type = "pay"
     if not self._conf.getModPay().isActivated():
         raise HTTPAPIError('E-payment is not enabled')
예제 #10
0
    def _getParams(self):
        super(VideoEventHook, self)._getParams()

        """ In this case, idlist refers to the different indices which can
            be called, e.g: vidyo, evo, mcu etc.
        """
        self._idList = self._pathParams['idlist'].split('-')
        self._categ_id = get_query_parameter(self._queryParams, 'categ')

        if not self._queryParams.has_key('alarms'):
            self._alarms = None
        else:
            self._alarms = get_query_parameter(self._queryParams, ['alarms'], 0, True)
예제 #11
0
파일: api.py 프로젝트: OmeGak/indico
 def _getParams(self):
     super(CategoryEventHook, self)._getParams()
     self._idList = self._pathParams["idlist"].split("-")
     self._wantFavorites = False
     if "favorites" in self._idList:
         self._idList.remove("favorites")
         self._wantFavorites = True
     self._eventType = get_query_parameter(self._queryParams, ["T", "type"])
     if self._eventType == "lecture":
         self._eventType = "simple_event"
     self._occurrences = get_query_parameter(self._queryParams, ["occ", "occurrences"], "no") == "yes"
     self._location = get_query_parameter(self._queryParams, ["l", "location"])
     self._room = get_query_parameter(self._queryParams, ["r", "room"])
예제 #12
0
def getResvStateFilter(queryParams):
    cancelled = get_query_parameter(queryParams, ["cxl", "cancelled"])
    rejected = get_query_parameter(queryParams, ["rej", "rejected"])
    confirmed = get_query_parameter(queryParams, ["confirmed"], -1)
    archival = get_query_parameter(queryParams, ["arch", "archival"])
    repeating = get_query_parameter(queryParams, ["rec", "recurring", "rep", "repeating"])
    avc = get_query_parameter(queryParams, ["avc"])
    avcSupport = get_query_parameter(queryParams, ["avcs", "avcsupport"])
    startupSupport = get_query_parameter(queryParams, ["sts", "startupsupport"])
    bookedFor = get_query_parameter(queryParams, ["bf", "bookedfor"])
    if not any((cancelled, rejected, confirmed != -1, archival, repeating, avc, avcSupport, startupSupport, bookedFor)):
        return None
    if cancelled is not None:
        cancelled = cancelled == "yes"
    if rejected is not None:
        rejected = rejected == "yes"
    if confirmed != -1:
        if confirmed == "pending":
            confirmed = None
        else:
            confirmed = confirmed == "yes"
    if archival is not None:
        archival = archival == "yes"
    if repeating is not None:
        repeating = repeating == "yes"
    if avc is not None:
        avc = avc == "yes"
    if avcSupport is not None:
        avcSupport = avcSupport == "yes"
    if startupSupport is not None:
        startupSupport = startupSupport == "yes"

    def _filter(obj):
        if cancelled is not None and obj.isCancelled != cancelled:
            return False
        if rejected is not None and obj.isRejected != rejected:
            return False
        if confirmed != -1 and obj.isConfirmed != confirmed:
            return False
        if archival is not None and obj.isArchival != archival:
            return False
        if repeating is not None and repeating == (obj.repeatability is None):
            return False
        if avc is not None and obj.usesAVC != avc:
            return False
        if avcSupport is not None and obj.needsAVCSupport != avcSupport:
            return False
        if startupSupport is not None and obj.needsAssistance != startupSupport:
            return False
        if bookedFor and not fnmatch.fnmatch(obj.bookedForName.lower(), bookedFor.lower()):
            return False
        return True

    return _filter
예제 #13
0
파일: api.py 프로젝트: OmeGak/indico
    def _update_query(self, query):
        order = get_query_parameter(request.args.to_dict(), ["o", "order"])
        desc = get_query_parameter(request.args.to_dict(), ["c", "descending"]) == "yes"
        limit = get_query_parameter(request.args.to_dict(), ["n", "limit"])
        offset = get_query_parameter(request.args.to_dict(), ["O", "offset"])

        col = {"start": Event.start_dt, "end": Event.end_dt, "id": Event.id, "title": Event.title}.get(order)
        if col:
            query = query.order_by(col.desc() if desc else col)
        if limit:
            query = query.limit(limit)
        if offset:
            query = query.offset(offset)

        return query
예제 #14
0
파일: base.py 프로젝트: DirkHoffmann/indico
    def _getParams(self):
        self._offset = get_query_parameter(self._queryParams, ['O', 'offset'], 0, integer=True)
        if self._offset < 0:
            raise HTTPAPIError('Offset must be a positive number', 400)
        self._orderBy = get_query_parameter(self._queryParams, ['o', 'order'])
        self._descending = get_query_parameter(self._queryParams, ['c', 'descending'], 'no') == 'yes'
        self._detail = get_query_parameter(self._queryParams, ['d', 'detail'], self.DEFAULT_DETAIL)
        tzName = get_query_parameter(self._queryParams, ['tz'], None)

        if tzName is None:
            tzName = config.DEFAULT_TIMEZONE
        try:
            self._tz = pytz.timezone(tzName)
        except pytz.UnknownTimeZoneError, e:
            raise HTTPAPIError("Bad timezone: '%s'" % e.message, 400)
예제 #15
0
    def _getParams(self):
        super(RoomBookingHook, self)._getParams()

        self._fromDT = utcdate(self._fromDT) if self._fromDT else None
        self._toDT = utcdate(self._toDT) if self._toDT else None
        self._occurrences = get_query_parameter(self._queryParams, ["occ", "occurrences"], "no") == "yes"
        self._resvFilter = getResvStateFilter(self._queryParams)
예제 #16
0
파일: registration.py 프로젝트: Ictp/indico
 def _getParams(self):
     super(RegistrantHook, self)._getParams()
     self._secret = get_query_parameter(self._queryParams, ["secret"])
     self._conf = ConferenceHolder().getById(self._pathParams['event'])
     registrant_id = self._pathParams["registrant_id"]
     self._registrant = self._conf.getRegistrantById(registrant_id)
     self._type = "registrant"
예제 #17
0
파일: api.py 프로젝트: jbenito3/indico
    def _getParams(self):
        self._offset = get_query_parameter(self._queryParams, ['O', 'offset'], 0, integer=True)
        self._orderBy = get_query_parameter(self._queryParams, ['o', 'order'])
        self._descending = get_query_parameter(self._queryParams, ['c', 'descending'], 'no') == 'yes'
        self._detail = get_query_parameter(self._queryParams, ['d', 'detail'], self.DEFAULT_DETAIL)
        tzName = get_query_parameter(self._queryParams, ['tz'], None)

        info = HelperMaKaCInfo.getMaKaCInfoInstance()
        self._serverTZ = info.getTimezone()

        if tzName is None:
            tzName = self._serverTZ
        try:
            self._tz = pytz.timezone(tzName)
        except pytz.UnknownTimeZoneError, e:
            raise HTTPAPIError("Bad timezone: '%s'" % e.message, 400)
예제 #18
0
    def _getParams(self):
        super(RoomBookingHook, self)._getParams()

        self._fromDT = utcdate(self._fromDT) if self._fromDT else None
        self._toDT = utcdate(self._toDT) if self._toDT else None
        self._occurrences = get_query_parameter(self._queryParams, ['occ', 'occurrences'], 'no') == 'yes'
        self._resvFilter = getResvStateFilter(self._queryParams)
예제 #19
0
파일: api.py 프로젝트: OmeGak/indico
def _export_reservations(hook, limit_per_room, include_rooms, extra_filters=None):
    """Exports reservations.

    :param hook: The HTTPAPIHook instance
    :param limit_per_room: Should the limit/offset be applied per room
    :param include_rooms: Should reservations include room information
    """
    filters = list(extra_filters) if extra_filters else []
    if hook._fromDT and hook._toDT:
        filters.append(cast(Reservation.start_dt, Date) <= hook._toDT.date())
        filters.append(cast(Reservation.end_dt, Date) >= hook._fromDT.date())
        filters.append(cast(Reservation.start_dt, Time) <= hook._toDT.time())
        filters.append(cast(Reservation.end_dt, Time) >= hook._fromDT.time())
    elif hook._toDT:
        filters.append(cast(Reservation.end_dt, Date) <= hook._toDT.date())
        filters.append(cast(Reservation.end_dt, Time) <= hook._toDT.time())
    elif hook._fromDT:
        filters.append(cast(Reservation.start_dt, Date) >= hook._fromDT.date())
        filters.append(cast(Reservation.start_dt, Time) >= hook._fromDT.time())
    filters += _get_reservation_state_filter(hook._queryParams)
    occurs = [datetime.strptime(x, '%Y-%m-%d').date()
              for x in filter(None, get_query_parameter(hook._queryParams, ['occurs'], '').split(','))]
    data = ['vc_equipment']
    if hook._occurrences:
        data.append('occurrences')
    order = {
        'start': Reservation.start_dt,
        'end': Reservation.end_dt
    }.get(hook._orderBy, Reservation.start_dt)
    if hook._descending:
        order = order.desc()
    reservations_data = Reservation.get_with_data(*data, filters=filters, limit=hook._limit, offset=hook._offset,
                                                  order=order, limit_per_room=limit_per_room, occurs_on=occurs)
    for result in reservations_data:
        yield result['reservation'].room_id, _serializable_reservation(result, include_rooms)
예제 #20
0
def getResvStateFilter(queryParams):
    cancelled = get_query_parameter(queryParams, ['cxl', 'cancelled'])
    rejected = get_query_parameter(queryParams, ['rej', 'rejected'])
    confirmed = get_query_parameter(queryParams, ['confirmed'], -1)
    archival = get_query_parameter(queryParams, ['arch', 'archival'])
    repeating = get_query_parameter(queryParams, ['rec', 'recurring', 'rep', 'repeating'])
    avc = get_query_parameter(queryParams, ['avc'])
    avcSupport = get_query_parameter(queryParams, ['avcs', 'avcsupport'])
    startupSupport = get_query_parameter(queryParams, ['sts', 'startupsupport'])
    bookedFor = get_query_parameter(queryParams, ['bf', 'bookedfor'])
    if not any((cancelled, rejected, confirmed != -1, archival, repeating, avc, avcSupport, startupSupport, bookedFor)):
        return None
    if cancelled is not None:
        cancelled = (cancelled == 'yes')
    if rejected is not None:
        rejected = (rejected == 'yes')
    if confirmed != -1:
        if confirmed == 'pending':
            confirmed = None
        else:
            confirmed = (confirmed == 'yes')
    if archival is not None:
        archival = (archival == 'yes')
    if repeating is not None:
        repeating = (repeating == 'yes')
    if avc is not None:
        avc = (avc == 'yes')
    if avcSupport is not None:
        avcSupport = (avcSupport == 'yes')
    if startupSupport is not None:
        startupSupport = (startupSupport == 'yes')
    def _filter(obj):
        if cancelled is not None and obj.isCancelled != cancelled:
            return False
        if rejected is not None and obj.isRejected != rejected:
            return False
        if confirmed != -1 and obj.isConfirmed != confirmed:
            return False
        if archival is not None and obj.isArchival != archival:
            return False
        if repeating is not None and repeating == (obj.repeatability is None):
            return False
        if avc is not None and obj.usesAVC != avc:
            return False
        if avcSupport is not None and obj.needsAVCSupport != avcSupport:
            return False
        if startupSupport is not None and obj.needsAssistance != startupSupport:
            return False
        if bookedFor and not fnmatch.fnmatch(obj.bookedForName.lower(), bookedFor.lower()):
            return False
        return True
    return _filter
예제 #21
0
파일: base.py 프로젝트: k3njiy/indico
    def _getParams(self):
        self._offset = get_query_parameter(self._queryParams, ["O", "offset"], 0, integer=True)
        if self._offset < 0:
            raise HTTPAPIError("Offset must be a positive number", 400)
        self._orderBy = get_query_parameter(self._queryParams, ["o", "order"])
        self._descending = get_query_parameter(self._queryParams, ["c", "descending"], "no") == "yes"
        self._detail = get_query_parameter(self._queryParams, ["d", "detail"], self.DEFAULT_DETAIL)
        tzName = get_query_parameter(self._queryParams, ["tz"], None)

        self._serverTZ = Config.getInstance().getDefaultTimezone()

        if tzName is None:
            tzName = self._serverTZ
        try:
            self._tz = pytz.timezone(tzName)
        except pytz.UnknownTimeZoneError, e:
            raise HTTPAPIError("Bad timezone: '%s'" % e.message, 400)
예제 #22
0
파일: api.py 프로젝트: belokop/indico_bare
 def _getParams(self):
     super(UserEventHook, self)._getParams()
     self._avatar = None
     # User-specified avatar
     userId = get_query_parameter(self._queryParams, ['uid', 'userid'])
     if userId is not None:
         self._avatar = AvatarHolder().getById(userId)
         if not self._avatar:
             raise HTTPAPIError('Avatar does not exist')
예제 #23
0
 def __init__(self, aw, hook):
     super(CategoryEventFetcher, self).__init__(aw, hook)
     self._eventType = hook._eventType
     self._occurrences = hook._occurrences
     self._location = hook._location
     self._room = hook._room
     self.user = getattr(aw.getUser(), 'user', None)
     self._detail_level = get_query_parameter(request.args.to_dict(), ['d', 'detail'], 'events')
     if self._detail_level not in ('events', 'contributions', 'subcontributions', 'sessions'):
         raise HTTPAPIError('Invalid detail level: {}'.format(self._detail_level), 400)
예제 #24
0
파일: api.py 프로젝트: OmeGak/indico
 def __init__(self, aw, hook):
     super(CategoryEventFetcher, self).__init__(aw, hook)
     self._eventType = hook._eventType
     self._occurrences = hook._occurrences
     self._location = hook._location
     self._room = hook._room
     self.user = getattr(aw.getUser(), "user", None)
     self._detail_level = get_query_parameter(request.args.to_dict(), ["d", "detail"], "events")
     if self._detail_level not in ("events", "contributions", "subcontributions", "sessions"):
         raise HTTPAPIError("Invalid detail level: {}".format(self._detail_level), 400)
예제 #25
0
    def _update_query(self, query):
        order = get_query_parameter(request.args.to_dict(), ['o', 'order'])
        desc = get_query_parameter(request.args.to_dict(), ['c', 'descending']) == 'yes'
        limit = get_query_parameter(request.args.to_dict(), ['n', 'limit'])
        offset = get_query_parameter(request.args.to_dict(), ['O', 'offset'])

        col = {
            'start': Event.start_dt,
            'end': Event.end_dt,
            'id': Event.id,
            'title': Event.title
        }.get(order)
        if col:
            query = query.order_by(col.desc() if desc else col)
        if limit:
            query = query.limit(limit)
        if offset:
            query = query.offset(offset)

        return query
예제 #26
0
파일: http_api.py 프로젝트: bubbas/indico
    def _getParams(self):
        super(VideoEventHook, self)._getParams()

        """ In this case, idlist refers to the different indicies which can
            be called, e.g: vidyo, evo, mcu etc.
        """
        self._idList = self._pathParams["idlist"].split("-")

        if not self._queryParams.has_key("alarms"):
            self._alarms = None
        else:
            self._alarms = get_query_parameter(self._queryParams, ["alarms"], 0, True)
예제 #27
0
파일: api.py 프로젝트: indico/indico
def _get_reservation_state_filter(params):
    cancelled = get_query_parameter(params, ['cxl', 'cancelled'])
    rejected = get_query_parameter(params, ['rej', 'rejected'])
    confirmed = get_query_parameter(params, ['confirmed'])
    archived = get_query_parameter(params, ['arch', 'archived', 'archival'])
    repeating = get_query_parameter(params, ['rec', 'recurring', 'rep', 'repeating'])
    booked_for = get_query_parameter(params, ['bf', 'bookedfor'])

    filters = []
    if cancelled is not None:
        filters.append(Reservation.is_cancelled == _yesno(cancelled))
    if rejected is not None:
        filters.append(Reservation.is_rejected == _yesno(rejected))
    if confirmed is not None:
        if confirmed == 'pending':
            filters.append(Reservation.is_pending)
        elif _yesno(confirmed):
            filters.append(Reservation.is_accepted)
        else:
            filters.append(~Reservation.is_accepted)
            filters.append(Reservation.is_rejected | Reservation.is_cancelled)
    if archived is not None:
        filters.append(Reservation.is_archived == _yesno(archived))
    if repeating is not None:
        if _yesno(repeating):
            filters.append(Reservation.repeat_frequency != 0)
        else:
            filters.append(Reservation.repeat_frequency == 0)
    if booked_for:
        like_str = '%{}%'.format(booked_for.replace('?', '_').replace('*', '%'))
        filters.append(Reservation.booked_for_name.ilike(like_str))
    return filters
예제 #28
0
파일: handlers.py 프로젝트: jt1/indico
def handler(req, **params):
    ContextManager.destroy()
    logger = Logger.get('httpapi')
    path, query = req.URLFields['PATH_INFO'], req.URLFields['QUERY_STRING']
    if req.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict(req.form)
        for key, value in queryParams.iteritems():
            queryParams[key] = [str(value)]
        query = urllib.urlencode(remove_lists(queryParams))
    else:
        # Parse the actual query string
        queryParams = parse_qs(query)

    dbi = DBMgr.getInstance()
    dbi.startRequest()
    minfo = HelperMaKaCInfo.getMaKaCInfoInstance()
    if minfo.getRoomBookingModuleActive():
        Factory.getDALManager().connect()

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    cookieAuth = get_query_parameter(queryParams, ['ca', 'cookieauth'], 'no') == 'yes'
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'], 0, integer=True)
    noCache = get_query_parameter(queryParams, ['nc', 'nocache'], 'no') == 'yes'
    pretty = get_query_parameter(queryParams, ['p', 'pretty'], 'no') == 'yes'
    onlyPublic = get_query_parameter(queryParams, ['op', 'onlypublic'], 'no') == 'yes'
    onlyAuthed = get_query_parameter(queryParams, ['oa', 'onlyauthed'], 'no') == 'yes'

    # Get our handler function and its argument and response type
    hook, dformat = HTTPAPIHook.parseRequest(path, queryParams)
    if hook is None or dformat is None:
        raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND

    # Disable caching if we are not just retrieving data (or the hook requires it)
    if req.method == 'POST' or hook.NO_CACHE:
        noCache = True

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    try:
        session = None
        if cookieAuth:
            session = getSessionForReq(req)
            if not session.getUser():  # ignore guest sessions
                session = None

        if apiKey or not session:
            # Validate the API key (and its signature)
            ak, enforceOnlyPublic = checkAK(apiKey, signature, timestamp, path, query)
            if enforceOnlyPublic:
                onlyPublic = True
            # Create an access wrapper for the API key's user
            aw = buildAW(ak, req, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() is None:
                cacheKey = normalizeQuery(path, query,
                                          remove=('ak', 'apiKey', 'signature', 'timestamp', 'nc', 'nocache',
                                                  'oa', 'onlyauthed'))
            else:
                cacheKey = normalizeQuery(path, query,
                                          remove=('signature', 'timestamp', 'nc', 'nocache', 'oa', 'onlyauthed'))
                if signature:
                    # in case the request was signed, store the result under a different key
                    cacheKey = 'signed_' + cacheKey
        else:
            # We authenticated using a session cookie.
            if Config.getInstance().getCSRFLevel() >= 2:
                token = req.headers_in.get('X-CSRF-Token', get_query_parameter(queryParams, ['csrftoken']))
                if session.csrf_token != token:
                    raise HTTPAPIError('Invalid CSRF token', apache.HTTP_FORBIDDEN)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(session.getUser())
            userPrefix = 'user-' + session.getUser().getId() + '_'
            cacheKey = userPrefix + normalizeQuery(path, query,
                                                   remove=('nc', 'nocache', 'ca', 'cookieauth', 'oa', 'onlyauthed',
                                                           'csrftoken'))

        # Bail out if the user requires authentication but is not authenticated
        if onlyAuthed and not aw.getUser():
            raise HTTPAPIError('Not authenticated', apache.HTTP_FORBIDDEN)

        obj = None
        addToCache = not hook.NO_CACHE
        cache = GenericCache('HTTPAPI')
        cacheKey = RE_REMOVE_EXTENSION.sub('', cacheKey)
        if not noCache:
            obj = cache.get(cacheKey)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            # Perform the actual exporting
            res = hook(aw, req)
            if isinstance(res, tuple) and len(res) == 4:
                result, extra, complete, typeMap = res
            else:
                result, extra, complete, typeMap = res, {}, True, {}
        if result is not None and addToCache:
            ttl = HelperMaKaCInfo.getMaKaCInfoInstance().getAPICacheTTL()
            cache.set(cacheKey, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError, e:
        error = e
        if e.getCode():
            req.status = e.getCode()
            if req.status == apache.HTTP_METHOD_NOT_ALLOWED:
                req.headers_out['Allow'] = 'GET' if req.method == 'POST' else 'POST'
예제 #29
0
 def _getParams(self):
     super(MLZExportBase, self)._getParams()
     self.event_id = self._pathParams['event']
     self.event = Event.get(self.event_id, is_deleted=False)
     self.flat = get_query_parameter(self._queryParams, ['flat'], False)
예제 #30
0
 def _getParams(self):
     super(RegistrantHook, self)._getParams()
     self.auth_key = get_query_parameter(self._queryParams, ["auth_key"])
     self._conf = ConferenceHolder().getById(self._pathParams['event'])
     registrant_id = self._pathParams["registrant_id"]
     self._registrant = self._conf.getRegistrantById(registrant_id)
예제 #31
0
 def _getParams(self):
     super(VCAssistanceExportHook, self)._getParams()
     self._alarm = get_query_parameter(self._queryParams, ['alarms'], None,
                                       True)
예제 #32
0
파일: handlers.py 프로젝트: jbenito3/indico
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    ContextManager.destroy()
    clearCache()  # init fossil cache
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict((key, value.encode('utf-8')) for key, value in request.form.iteritems())
        query = urllib.urlencode(queryParams)
    else:
        # Parse the actual query string
        queryParams = dict((key, value.encode('utf-8')) for key, value in request.args.iteritems())
        query = request.query_string

    dbi = DBMgr.getInstance()
    dbi.startRequest()
    minfo = HelperMaKaCInfo.getMaKaCInfoInstance()
    if minfo.getRoomBookingModuleActive():
        Factory.getDALManager().connect()

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    cookieAuth = get_query_parameter(queryParams, ['ca', 'cookieauth'], 'no') == 'yes'
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'], 0, integer=True)
    noCache = get_query_parameter(queryParams, ['nc', 'nocache'], 'no') == 'yes'
    pretty = get_query_parameter(queryParams, ['p', 'pretty'], 'no') == 'yes'
    onlyPublic = get_query_parameter(queryParams, ['op', 'onlypublic'], 'no') == 'yes'
    onlyAuthed = get_query_parameter(queryParams, ['oa', 'onlyauthed'], 'no') == 'yes'
    oauthToken = 'oauth_token' in queryParams

    # Get our handler function and its argument and response type
    hook, dformat = HTTPAPIHook.parseRequest(path, queryParams)
    if hook is None or dformat is None:
        raise NotFound

    # Disable caching if we are not just retrieving data (or the hook requires it)
    if request.method == 'POST' or hook.NO_CACHE:
        noCache = True

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    responseUtil = ResponseUtil()
    try:
        used_session = None
        if cookieAuth:
            used_session = session
            if not used_session.user:  # ignore guest sessions
                used_session = None

        if apiKey or oauthToken or not used_session:
            if not oauthToken:
                # Validate the API key (and its signature)
                ak, enforceOnlyPublic = checkAK(apiKey, signature, timestamp, path, query)
                if enforceOnlyPublic:
                    onlyPublic = True
                # Create an access wrapper for the API key's user
                aw = buildAW(ak, onlyPublic)
            else: # Access Token (OAuth)
                at = OAuthUtils.OAuthCheckAccessResource()
                aw = buildAW(at, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() is None:
                cacheKey = normalizeQuery(path, query,
                                          remove=('_', 'ak', 'apiKey', 'signature', 'timestamp', 'nc', 'nocache',
                                                  'oa', 'onlyauthed'))
            else:
                cacheKey = normalizeQuery(path, query,
                                          remove=('_', 'signature', 'timestamp', 'nc', 'nocache', 'oa', 'onlyauthed'))
                if signature:
                    # in case the request was signed, store the result under a different key
                    cacheKey = 'signed_' + cacheKey
        else:
            # We authenticated using a session cookie.
            if Config.getInstance().getCSRFLevel() >= 2:
                token = request.headers.get('X-CSRF-Token', get_query_parameter(queryParams, ['csrftoken']))
                if used_session.csrf_protected and used_session.csrf_token != token:
                    raise HTTPAPIError('Invalid CSRF token', 403)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(used_session.user)
            userPrefix = 'user-' + used_session.user.getId() + '_'
            cacheKey = userPrefix + normalizeQuery(path, query,
                                                   remove=('_', 'nc', 'nocache', 'ca', 'cookieauth', 'oa', 'onlyauthed',
                                                           'csrftoken'))

        # Bail out if the user requires authentication but is not authenticated
        if onlyAuthed and not aw.getUser():
            raise HTTPAPIError('Not authenticated', 403)

        addToCache = not hook.NO_CACHE
        cache = GenericCache('HTTPAPI')
        cacheKey = RE_REMOVE_EXTENSION.sub('', cacheKey)
        if not noCache:
            obj = cache.get(cacheKey)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            # Perform the actual exporting
            res = hook(aw)
            if isinstance(res, tuple) and len(res) == 4:
                result, extra, complete, typeMap = res
            else:
                result, extra, complete, typeMap = res, {}, True, {}
        if result is not None and addToCache:
            ttl = HelperMaKaCInfo.getMaKaCInfoInstance().getAPICacheTTL()
            cache.set(cacheKey, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError, e:
        error = e
        if e.getCode():
            responseUtil.status = e.getCode()
            if responseUtil.status == 405:
                responseUtil.headers['Allow'] = 'GET' if request.method == 'POST' else 'POST'
예제 #33
0
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    ContextManager.destroy()
    clearCache()  # init fossil cache
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict((key, value.encode('utf-8'))
                           for key, value in request.form.iteritems())
        query = urllib.urlencode(queryParams)
    else:
        # Parse the actual query string
        queryParams = dict((key, value.encode('utf-8'))
                           for key, value in request.args.iteritems())
        query = request.query_string

    dbi = DBMgr.getInstance()
    dbi.startRequest()

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    cookieAuth = get_query_parameter(queryParams, ['ca', 'cookieauth'],
                                     'no') == 'yes'
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'],
                                    0,
                                    integer=True)
    noCache = get_query_parameter(queryParams, ['nc', 'nocache'],
                                  'no') == 'yes'
    pretty = get_query_parameter(queryParams, ['p', 'pretty'], 'no') == 'yes'
    onlyPublic = get_query_parameter(queryParams, ['op', 'onlypublic'],
                                     'no') == 'yes'
    onlyAuthed = get_query_parameter(queryParams, ['oa', 'onlyauthed'],
                                     'no') == 'yes'
    oauthToken = 'oauth_token' in queryParams
    # Check if OAuth data is supplied in the Authorization header
    if not oauthToken and request.headers.get('Authorization') is not None:
        oauthToken = 'oauth_token' in request.headers.get('Authorization')

    # Get our handler function and its argument and response type
    hook, dformat = HTTPAPIHook.parseRequest(path, queryParams)
    if hook is None or dformat is None:
        raise NotFound

    # Disable caching if we are not just retrieving data (or the hook requires it)
    if request.method == 'POST' or hook.NO_CACHE:
        noCache = True

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    responseUtil = ResponseUtil()
    try:
        used_session = None
        if cookieAuth:
            used_session = session
            if not used_session.user:  # ignore guest sessions
                used_session = None

        if apiKey or oauthToken or not used_session:
            if not oauthToken:
                # Validate the API key (and its signature)
                ak, enforceOnlyPublic = checkAK(apiKey, signature, timestamp,
                                                path, query)
                if enforceOnlyPublic:
                    onlyPublic = True
                # Create an access wrapper for the API key's user
                aw = buildAW(ak, onlyPublic)
            else:  # Access Token (OAuth)
                at = OAuthUtils.OAuthCheckAccessResource()
                aw = buildAW(at, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() is None:
                cacheKey = normalizeQuery(
                    path,
                    query,
                    remove=('_', 'ak', 'apiKey', 'signature', 'timestamp',
                            'nc', 'nocache', 'oa', 'onlyauthed'))
            else:
                cacheKey = normalizeQuery(path,
                                          query,
                                          remove=('_', 'signature',
                                                  'timestamp', 'nc', 'nocache',
                                                  'oa', 'onlyauthed'))
                if signature:
                    # in case the request was signed, store the result under a different key
                    cacheKey = 'signed_' + cacheKey
        else:
            # We authenticated using a session cookie.
            if Config.getInstance().getCSRFLevel() >= 2:
                token = request.headers.get(
                    'X-CSRF-Token',
                    get_query_parameter(queryParams, ['csrftoken']))
                if used_session.csrf_protected and used_session.csrf_token != token:
                    raise HTTPAPIError('Invalid CSRF token', 403)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(used_session.user)
            userPrefix = 'user-' + used_session.user.getId() + '_'
            cacheKey = userPrefix + normalizeQuery(
                path,
                query,
                remove=('_', 'nc', 'nocache', 'ca', 'cookieauth', 'oa',
                        'onlyauthed', 'csrftoken'))

        # Bail out if the user requires authentication but is not authenticated
        if onlyAuthed and not aw.getUser():
            raise HTTPAPIError('Not authenticated', 403)

        addToCache = not hook.NO_CACHE
        cache = GenericCache('HTTPAPI')
        cacheKey = RE_REMOVE_EXTENSION.sub('', cacheKey)
        if not noCache:
            obj = cache.get(cacheKey)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            ContextManager.set("currentAW", aw)
            # Perform the actual exporting
            res = hook(aw)
            if isinstance(res, tuple) and len(res) == 4:
                result, extra, complete, typeMap = res
            else:
                result, extra, complete, typeMap = res, {}, True, {}
        if result is not None and addToCache:
            ttl = HelperMaKaCInfo.getMaKaCInfoInstance().getAPICacheTTL()
            cache.set(cacheKey, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError, e:
        error = e
        if e.getCode():
            responseUtil.status = e.getCode()
            if responseUtil.status == 405:
                responseUtil.headers[
                    'Allow'] = 'GET' if request.method == 'POST' else 'POST'
예제 #34
0
 def _getParams(self):
     super(RecordingLinkAPI, self)._getParams()
     self._indico_id = get_query_parameter(self._queryParams,
                                           ['iid', 'indicoID'])
     self._cds_id = get_query_parameter(self._queryParams, ['cid', 'cdsID'])
예제 #35
0
파일: handlers.py 프로젝트: vintas/indico
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    clearCache()  # init fossil cache
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = [(key, [x.encode('utf-8') for x in values])
                       for key, values in request.form.iterlists()]
        query = urllib.urlencode(queryParams, doseq=1)
        # we only need/keep multiple values so we can properly validate the signature.
        # the legacy code below expects a dict with just the first value.
        # if you write a new api endpoint that needs multiple values get them from
        # ``request.values.getlist()`` directly
        queryParams = {key: values[0] for key, values in queryParams}
    else:
        # Parse the actual query string
        queryParams = dict((key, value.encode('utf-8'))
                           for key, value in request.args.iteritems())
        query = request.query_string

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    cookieAuth = get_query_parameter(queryParams, ['ca', 'cookieauth'],
                                     'no') == 'yes'
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'],
                                    0,
                                    integer=True)
    noCache = get_query_parameter(queryParams, ['nc', 'nocache'],
                                  'no') == 'yes'
    pretty = get_query_parameter(queryParams, ['p', 'pretty'], 'no') == 'yes'
    onlyPublic = get_query_parameter(queryParams, ['op', 'onlypublic'],
                                     'no') == 'yes'
    onlyAuthed = get_query_parameter(queryParams, ['oa', 'onlyauthed'],
                                     'no') == 'yes'
    scope = 'read:legacy_api' if request.method == 'GET' else 'write:legacy_api'

    if not request.headers.get('Authorization',
                               '').lower().startswith('basic '):
        try:
            oauth_valid, oauth_request = oauth.verify_request([scope])
            if not oauth_valid and oauth_request and oauth_request.error_message != 'Bearer token not found.':
                raise BadRequest('OAuth error: {}'.format(
                    oauth_request.error_message))
            elif g.get(
                    'received_oauth_token'
            ) and oauth_request.error_message == 'Bearer token not found.':
                raise BadRequest('OAuth error: Invalid token')
        except ValueError:
            # XXX: Dirty hack to workaround a bug in flask-oauthlib that causes it
            #      not to properly urlencode request query strings
            #      Related issue (https://github.com/lepture/flask-oauthlib/issues/213)
            oauth_valid = False
    else:
        oauth_valid = False

    # Get our handler function and its argument and response type
    hook, dformat = HTTPAPIHook.parseRequest(path, queryParams)
    if hook is None or dformat is None:
        raise NotFound

    # Disable caching if we are not just retrieving data (or the hook requires it)
    if request.method == 'POST' or hook.NO_CACHE:
        noCache = True

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    status_code = None
    is_response = False
    try:
        used_session = None
        if cookieAuth:
            used_session = session
            if not used_session.user:  # ignore guest sessions
                used_session = None

        if apiKey or oauth_valid or not used_session:
            if not oauth_valid:
                # Validate the API key (and its signature)
                ak, enforceOnlyPublic = checkAK(apiKey, signature, timestamp,
                                                path, query)
                if enforceOnlyPublic:
                    onlyPublic = True
                # Create an access wrapper for the API key's user
                user = ak.user if ak and not onlyPublic else None
            else:  # Access Token (OAuth)
                at = load_token(oauth_request.access_token.access_token)
                user = at.user if at and not onlyPublic else None
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and user is None:
                cacheKey = normalizeQuery(
                    path,
                    query,
                    remove=('_', 'ak', 'apiKey', 'signature', 'timestamp',
                            'nc', 'nocache', 'oa', 'onlyauthed'))
            else:
                cacheKey = normalizeQuery(path,
                                          query,
                                          remove=('_', 'signature',
                                                  'timestamp', 'nc', 'nocache',
                                                  'oa', 'onlyauthed'))
                if signature:
                    # in case the request was signed, store the result under a different key
                    cacheKey = 'signed_' + cacheKey
        else:
            # We authenticated using a session cookie.
            token = request.headers.get(
                'X-CSRF-Token', get_query_parameter(queryParams,
                                                    ['csrftoken']))
            if used_session.csrf_protected and used_session.csrf_token != token:
                raise HTTPAPIError('Invalid CSRF token', 403)
            user = used_session.user if not onlyPublic else None
            userPrefix = 'user-{}_'.format(used_session.user.id)
            cacheKey = userPrefix + normalizeQuery(
                path,
                query,
                remove=('_', 'nc', 'nocache', 'ca', 'cookieauth', 'oa',
                        'onlyauthed', 'csrftoken'))

        # Bail out if the user requires authentication but is not authenticated
        if onlyAuthed and not user:
            raise HTTPAPIError('Not authenticated', 403)

        addToCache = not hook.NO_CACHE
        cache = GenericCache('HTTPAPI')
        cacheKey = RE_REMOVE_EXTENSION.sub('', cacheKey)
        if not noCache:
            obj = cache.get(cacheKey)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            g.current_api_user = user
            # Perform the actual exporting
            res = hook(user)
            if isinstance(res, current_app.response_class):
                addToCache = False
                is_response = True
                result, extra, complete, typeMap = res, {}, True, {}
            elif isinstance(res, tuple) and len(res) == 4:
                result, extra, complete, typeMap = res
            else:
                result, extra, complete, typeMap = res, {}, True, {}
        if result is not None and addToCache:
            ttl = api_settings.get('cache_ttl')
            if ttl > 0:
                cache.set(cacheKey, (result, extra, ts, complete, typeMap),
                          ttl)
    except HTTPAPIError as e:
        error = e
        if e.getCode():
            status_code = e.getCode()

    if result is None and error is None:
        # TODO: usage page
        raise NotFound
    else:
        if ak and error is None:
            # Commit only if there was an API key and no error
            norm_path, norm_query = normalizeQuery(path,
                                                   query,
                                                   remove=('signature',
                                                           'timestamp'),
                                                   separate=True)
            uri = to_unicode('?'.join(filter(None, (norm_path, norm_query))))
            ak.register_used(request.remote_addr, uri, not onlyPublic)
            db.session.commit()
        else:
            # No need to commit stuff if we didn't use an API key (nothing was written)
            # XXX do we even need this?
            db.session.rollback()

        # Log successful POST api requests
        if error is None and request.method == 'POST':
            logger.info('API request: %s?%s', path, query)
        if is_response:
            return result
        serializer = Serializer.create(dformat,
                                       query_params=queryParams,
                                       pretty=pretty,
                                       typeMap=typeMap,
                                       **hook.serializer_args)
        if error:
            if not serializer.schemaless:
                # if our serializer has a specific schema (HTML, ICAL, etc...)
                # use JSON, since it is universal
                serializer = Serializer.create('json')

            result = fossilize(error)
        else:
            if serializer.encapsulate:
                result = fossilize(
                    HTTPAPIResult(result, path, query, ts, complete, extra),
                    IHTTPAPIExportResultFossil)
                del result['_fossil']

        try:
            data = serializer(result)
            response = current_app.make_response(data)
            content_type = serializer.get_response_content_type()
            if content_type:
                response.content_type = content_type
            if status_code:
                response.status_code = status_code
            return response
        except Exception:
            logger.exception('Serialization error in request %s?%s', path,
                             query)
            raise
예제 #36
0
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = list(request.form.lists())
        query = urlencode(queryParams, doseq=1)
        # we only need/keep multiple values so we can properly validate the signature.
        # the legacy code below expects a dict with just the first value.
        # if you write a new api endpoint that needs multiple values get them from
        # ``request.values.getlist()`` directly
        queryParams = {key: values[0] for key, values in queryParams}
    else:
        # Parse the actual query string
        queryParams = {key: value for key, value in request.args.items()}
        query = request.query_string.decode()

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    cookieAuth = get_query_parameter(queryParams, ['ca', 'cookieauth'], 'no') == 'yes'
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'], 0, integer=True)
    noCache = get_query_parameter(queryParams, ['nc', 'nocache'], 'no') == 'yes'
    pretty = get_query_parameter(queryParams, ['p', 'pretty'], 'no') == 'yes'
    onlyPublic = get_query_parameter(queryParams, ['op', 'onlypublic'], 'no') == 'yes'
    onlyAuthed = get_query_parameter(queryParams, ['oa', 'onlyauthed'], 'no') == 'yes'
    scope = 'read:legacy_api' if request.method == 'GET' else 'write:legacy_api'

    oauth_token = None
    if request.headers.get('Authorization', '').lower().startswith('bearer '):
        try:
            oauth_token = require_oauth.acquire_token([scope])
        except OAuth2Error as exc:
            raise BadRequest(f'OAuth error: {exc}')

    # Get our handler function and its argument and response type
    hook, dformat = HTTPAPIHook.parseRequest(path, queryParams)
    if hook is None or dformat is None:
        raise NotFound

    # Disable caching if we are not just retrieving data (or the hook requires it)
    if request.method == 'POST' or hook.NO_CACHE:
        noCache = True

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    status_code = None
    is_response = False
    try:
        used_session = None
        if cookieAuth:
            used_session = session
            if not used_session.user:  # ignore guest sessions
                used_session = None

        if apiKey or oauth_token or not used_session:
            auth_token = None
            if not oauth_token:
                # Validate the API key (and its signature)
                ak, enforceOnlyPublic = checkAK(apiKey, signature, timestamp, path, query)
                if enforceOnlyPublic:
                    onlyPublic = True
                # Create an access wrapper for the API key's user
                user = ak.user if ak and not onlyPublic else None
            else:  # Access Token (OAuth)
                user = oauth_token.user if not onlyPublic else None
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and user is None:
                cacheKey = normalizeQuery(path, query,
                                          remove=('_', 'ak', 'apiKey', 'signature', 'timestamp', 'nc', 'nocache',
                                                  'oa', 'onlyauthed', 'access_token'))
            else:
                cacheKey = normalizeQuery(path, query,
                                          remove=('_', 'signature', 'timestamp', 'nc', 'nocache', 'oa', 'onlyauthed',
                                                  'access_token'))
                if signature:
                    # in case the request was signed, store the result under a different key
                    cacheKey = 'signed_' + cacheKey
                if auth_token:
                    # if oauth was used, we also make the cache key unique
                    cacheKey = f'oauth-{auth_token.id}_{cacheKey}'
        else:
            # We authenticated using a session cookie.
            # XXX: This is not used anymore within indico and should be removed whenever we rewrite
            # the code here.
            token = request.headers.get('X-CSRF-Token', get_query_parameter(queryParams, ['csrftoken']))
            if used_session.csrf_protected and used_session.csrf_token != token:
                raise HTTPAPIError('Invalid CSRF token', 403)
            user = used_session.user if not onlyPublic else None
            cacheKey = normalizeQuery(path, query,
                                      remove=('_', 'nc', 'nocache', 'ca', 'cookieauth', 'oa', 'onlyauthed',
                                              'csrftoken'))

        if user is not None:
            # We *always* prefix the cache key with the user ID so we never get an overlap between
            # authenticated and unauthenticated requests
            cacheKey = f'user-{user.id}_{cacheKey}'
            sentry_sdk.set_user({
                'id': user.id,
                'email': user.email,
                'name': user.full_name,
                'source': 'http_api'
            })
        else:
            cacheKey = f'public_{cacheKey}'

        # Bail out if the user requires authentication but is not authenticated
        if onlyAuthed and not user:
            raise HTTPAPIError('Not authenticated', 403)

        addToCache = not hook.NO_CACHE
        cacheKey = RE_REMOVE_EXTENSION.sub('', cacheKey)
        if not noCache:
            obj = API_CACHE.get(cacheKey)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            g.current_api_user = user
            # Perform the actual exporting
            res = hook(user)
            if isinstance(res, current_app.response_class):
                addToCache = False
                is_response = True
                result, extra, complete, typeMap = res, {}, True, {}
            elif isinstance(res, tuple) and len(res) == 4:
                result, extra, complete, typeMap = res
            else:
                result, extra, complete, typeMap = res, {}, True, {}
        if result is not None and addToCache:
            ttl = api_settings.get('cache_ttl')
            if ttl > 0:
                API_CACHE.set(cacheKey, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError as e:
        error = e
        if e.code:
            status_code = e.code

    if result is None and error is None:
        raise NotFound
    else:
        if ak and error is None:
            # Commit only if there was an API key and no error
            norm_path, norm_query = normalizeQuery(path, query, remove=('signature', 'timestamp'), separate=True)
            uri = '?'.join([_f for _f in (norm_path, norm_query) if _f])
            ak.register_used(request.remote_addr, uri, not onlyPublic)
            db.session.commit()
        else:
            # No need to commit stuff if we didn't use an API key (nothing was written)
            # XXX do we even need this?
            db.session.rollback()

        # Log successful POST api requests
        if error is None and request.method == 'POST':
            logger.info('API request: %s?%s', path, query)
        if is_response:
            return result
        serializer = Serializer.create(dformat, query_params=queryParams, pretty=pretty, typeMap=typeMap,
                                       **hook.serializer_args)
        if error:
            if not serializer.schemaless:
                # if our serializer has a specific schema (HTML, ICAL, etc...)
                # use JSON, since it is universal
                serializer = Serializer.create('json')

            result = {'message': error.message}
        elif serializer.encapsulate:
            result = HTTPAPIResultSchema().dump(HTTPAPIResult(result, path, query, ts, extra))

        try:
            data = serializer(result)
            response = current_app.make_response(data)
            content_type = serializer.get_response_content_type()
            if content_type:
                response.content_type = content_type
            if status_code:
                response.status_code = status_code
            return response
        except Exception:
            logger.exception('Serialization error in request %s?%s', path, query)
            raise
예제 #37
0
def handler(prefix, path):
    path = posixpath.join('/', prefix, path)
    ContextManager.destroy()
    clearCache()  # init fossil cache
    logger = Logger.get('httpapi')
    if request.method == 'POST':
        # Convert POST data to a query string
        queryParams = dict((key, value.encode('utf-8'))
                           for key, value in request.form.iteritems())
        query = urllib.urlencode(queryParams)
    else:
        # Parse the actual query string
        queryParams = dict((key, value.encode('utf-8'))
                           for key, value in request.args.iteritems())
        query = request.query_string

    dbi = DBMgr.getInstance()
    dbi.startRequest()

    apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None)
    cookieAuth = get_query_parameter(queryParams, ['ca', 'cookieauth'],
                                     'no') == 'yes'
    signature = get_query_parameter(queryParams, ['signature'])
    timestamp = get_query_parameter(queryParams, ['timestamp'],
                                    0,
                                    integer=True)
    noCache = get_query_parameter(queryParams, ['nc', 'nocache'],
                                  'no') == 'yes'
    pretty = get_query_parameter(queryParams, ['p', 'pretty'], 'no') == 'yes'
    onlyPublic = get_query_parameter(queryParams, ['op', 'onlypublic'],
                                     'no') == 'yes'
    onlyAuthed = get_query_parameter(queryParams, ['oa', 'onlyauthed'],
                                     'no') == 'yes'
    scope = 'read:legacy_api' if request.method == 'GET' else 'write:legacy_api'
    try:
        oauth_valid, oauth_request = oauth.verify_request([scope])
        if not oauth_valid and oauth_request and oauth_request.error_message != 'Bearer token not found.':
            raise BadRequest('OAuth error: {}'.format(
                oauth_request.error_message))
        elif g.get(
                'received_oauth_token'
        ) and oauth_request.error_message == 'Bearer token not found.':
            raise BadRequest('OAuth error: Invalid token')
    except ValueError:
        # XXX: Dirty hack to workaround a bug in flask-oauthlib that causes it
        #      not to properly urlencode request query strings
        #      Related issue (https://github.com/lepture/flask-oauthlib/issues/213)
        oauth_valid = False

    # Get our handler function and its argument and response type
    hook, dformat = HTTPAPIHook.parseRequest(path, queryParams)
    if hook is None or dformat is None:
        raise NotFound

    # Disable caching if we are not just retrieving data (or the hook requires it)
    if request.method == 'POST' or hook.NO_CACHE:
        noCache = True

    ak = error = result = None
    ts = int(time.time())
    typeMap = {}
    responseUtil = ResponseUtil()
    try:
        used_session = None
        if cookieAuth:
            used_session = session
            if not used_session.user:  # ignore guest sessions
                used_session = None

        if apiKey or oauth_valid or not used_session:
            if not oauth_valid:
                # Validate the API key (and its signature)
                ak, enforceOnlyPublic = checkAK(apiKey, signature, timestamp,
                                                path, query)
                if enforceOnlyPublic:
                    onlyPublic = True
                # Create an access wrapper for the API key's user
                aw = buildAW(ak, onlyPublic)
            else:  # Access Token (OAuth)
                at = load_token(oauth_request.access_token.access_token)
                aw = buildAW(at, onlyPublic)
            # Get rid of API key in cache key if we did not impersonate a user
            if ak and aw.getUser() is None:
                cacheKey = normalizeQuery(
                    path,
                    query,
                    remove=('_', 'ak', 'apiKey', 'signature', 'timestamp',
                            'nc', 'nocache', 'oa', 'onlyauthed'))
            else:
                cacheKey = normalizeQuery(path,
                                          query,
                                          remove=('_', 'signature',
                                                  'timestamp', 'nc', 'nocache',
                                                  'oa', 'onlyauthed'))
                if signature:
                    # in case the request was signed, store the result under a different key
                    cacheKey = 'signed_' + cacheKey
        else:
            # We authenticated using a session cookie.
            if Config.getInstance().getCSRFLevel() >= 2:
                token = request.headers.get(
                    'X-CSRF-Token',
                    get_query_parameter(queryParams, ['csrftoken']))
                if used_session.csrf_protected and used_session.csrf_token != token:
                    raise HTTPAPIError('Invalid CSRF token', 403)
            aw = AccessWrapper()
            if not onlyPublic:
                aw.setUser(used_session.avatar)
            userPrefix = 'user-{}_'.format(used_session.user.id)
            cacheKey = userPrefix + normalizeQuery(
                path,
                query,
                remove=('_', 'nc', 'nocache', 'ca', 'cookieauth', 'oa',
                        'onlyauthed', 'csrftoken'))

        # Bail out if the user requires authentication but is not authenticated
        if onlyAuthed and not aw.getUser():
            raise HTTPAPIError('Not authenticated', 403)

        addToCache = not hook.NO_CACHE
        cache = GenericCache('HTTPAPI')
        cacheKey = RE_REMOVE_EXTENSION.sub('', cacheKey)
        if not noCache:
            obj = cache.get(cacheKey)
            if obj is not None:
                result, extra, ts, complete, typeMap = obj
                addToCache = False
        if result is None:
            ContextManager.set("currentAW", aw)
            # Perform the actual exporting
            res = hook(aw)
            if isinstance(res, tuple) and len(res) == 4:
                result, extra, complete, typeMap = res
            else:
                result, extra, complete, typeMap = res, {}, True, {}
        if result is not None and addToCache:
            ttl = api_settings.get('cache_ttl')
            cache.set(cacheKey, (result, extra, ts, complete, typeMap), ttl)
    except HTTPAPIError, e:
        error = e
        if e.getCode():
            responseUtil.status = e.getCode()
            if responseUtil.status == 405:
                responseUtil.headers[
                    'Allow'] = 'GET' if request.method == 'POST' else 'POST'
예제 #38
0
    def _getParams(self):

        super(CollaborationAPIHook, self)._getParams()
        self._indicoID = get_query_parameter(self._queryParams, ['iid', 'indicoID'])
        self._cdsID = get_query_parameter(self._queryParams, ['cid', 'cdsID'])
예제 #39
0
 def _getParams(self):
     super(AVExportHook, self)._getParams()
     self._services = set(request.args.getlist('service'))
     self._alarm = get_query_parameter(self._queryParams, ['alarms'], None,
                                       True)
예제 #40
0
 def _getParams(self):
     super(RoomBookingHookBase, self)._getParams()
     self._fromDT = utc_to_server(self._fromDT.astimezone(pytz.utc)).replace(tzinfo=None) if self._fromDT else None
     self._toDT = utc_to_server(self._toDT.astimezone(pytz.utc)).replace(tzinfo=None) if self._toDT else None
     self._occurrences = _yesno(get_query_parameter(self._queryParams, ['occ', 'occurrences'], 'no'))
예제 #41
0
class HTTPAPIHook(object):
    """This class is the hook between the query (path+params) and the generator of the results (fossil).
       It is also in charge of checking the parameters and the access rights.
    """

    HOOK_LIST = []
    TYPES = None  # abstract
    PREFIX = 'export'  # url prefix. must exist in indico.web.flask.blueprints.api, too! also used as function prefix
    RE = None  # abstract
    METHOD_NAME = None  # overrides method name derived from prefix+type
    DEFAULT_DETAIL = None  # abstract
    MAX_RECORDS = {}
    SERIALIZER_TYPE_MAP = {
    }  # maps fossil type names to friendly names (useful for plugins e.g. RoomCERN --> Room)
    VALID_FORMATS = None  # None = all formats
    GUEST_ALLOWED = True  # When False, it forces authentication
    COMMIT = False  # commit database changes
    HTTP_POST = False  # require (and allow) HTTP POST
    NO_CACHE = False

    @classmethod
    def parseRequest(cls, path, queryParams):
        """Parse a request path and return a hook and the requested data type."""
        path = urllib.unquote(path)
        hooks = itertools.chain(cls.HOOK_LIST, cls._getPluginHooks())
        for expCls in hooks:
            Logger.get('HTTPAPIHook.parseRequest').debug(expCls)
            m = expCls._matchPath(path)
            if m:
                gd = m.groupdict()
                g = m.groups()
                type = g[0]
                format = g[-1]
                if format not in DataFetcher.getAllowedFormats():
                    return None, None
                elif expCls.VALID_FORMATS and format not in expCls.VALID_FORMATS:
                    return None, None
                return expCls(queryParams, type, gd), format
        return None, None

    @staticmethod
    def register(cls):
        """Register a hook that is not part of a plugin.

        To use it, simply decorate the hook class with this method."""
        assert cls.RE is not None
        HTTPAPIHook.HOOK_LIST.append(cls)
        return cls

    @classmethod
    def _matchPath(cls, path):
        if not hasattr(cls, '_RE'):
            types = '|'.join(cls.TYPES)
            cls._RE = re.compile(r'/' + cls.PREFIX + '/(' + types + r')/' +
                                 cls.RE + r'\.(\w+)$')
        return cls._RE.match(path)

    @classmethod
    def _getPluginHooks(cls):
        for plugin in PluginsHolder().getPluginTypes():
            for expClsName in plugin.getHTTPAPIHookList():
                yield getattr(plugin.getModule().http_api, expClsName)

    def __init__(self, queryParams, type, pathParams):
        self._queryParams = queryParams
        self._type = type
        self._pathParams = pathParams

    def _getParams(self):
        self._offset = get_query_parameter(self._queryParams, ['O', 'offset'],
                                           0,
                                           integer=True)
        self._orderBy = get_query_parameter(self._queryParams, ['o', 'order'])
        self._descending = get_query_parameter(self._queryParams,
                                               ['c', 'descending'],
                                               'no') == 'yes'
        self._detail = get_query_parameter(self._queryParams, ['d', 'detail'],
                                           self.DEFAULT_DETAIL)
        tzName = get_query_parameter(self._queryParams, ['tz'], None)

        info = HelperMaKaCInfo.getMaKaCInfoInstance()
        self._serverTZ = info.getTimezone()

        if tzName is None:
            tzName = self._serverTZ
        try:
            self._tz = pytz.timezone(tzName)
        except pytz.UnknownTimeZoneError, e:
            raise HTTPAPIError("Bad timezone: '%s'" % e.message, 400)
        max = self.MAX_RECORDS.get(self._detail, 1000)
        self._userLimit = get_query_parameter(self._queryParams,
                                              ['n', 'limit'],
                                              0,
                                              integer=True)
        if self._userLimit > max:
            raise HTTPAPIError(
                "You can only request up to %d records per request with the detail level '%s'"
                % (max, self._detail), 400)
        self._limit = self._userLimit if self._userLimit > 0 else max

        fromDT = get_query_parameter(self._queryParams, ['f', 'from'])
        toDT = get_query_parameter(self._queryParams, ['t', 'to'])
        dayDT = get_query_parameter(self._queryParams, ['day'])

        if (fromDT or toDT) and dayDT:
            raise HTTPAPIError(
                "'day' can only be used without 'from' and 'to'", 400)
        elif dayDT:
            fromDT = toDT = dayDT

        self._fromDT = DataFetcher._getDateTime('from', fromDT,
                                                self._tz) if fromDT else None
        self._toDT = DataFetcher._getDateTime(
            'to', toDT, self._tz, aux=self._fromDT) if toDT else None
예제 #42
0
    def _getParams(self):

        super(CollaborationAPIHook, self)._getParams()
        self._indicoID = get_query_parameter(self._queryParams,
                                             ['iid', 'indicoID'])
        self._cdsID = get_query_parameter(self._queryParams, ['cid', 'cdsID'])