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)
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')
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']))
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')
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)
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)
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')
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'])
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')
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)
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"])
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
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
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)
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)
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"
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)
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)
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)
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
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)
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')
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)
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)
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
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)
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
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'
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)
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)
def _getParams(self): super(VCAssistanceExportHook, self)._getParams() self._alarm = get_query_parameter(self._queryParams, ['alarms'], None, True)
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'
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'
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'])
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
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
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'
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'])
def _getParams(self): super(AVExportHook, self)._getParams() self._services = set(request.args.getlist('service')) self._alarm = get_query_parameter(self._queryParams, ['alarms'], None, True)
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'))
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