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 as 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
def __call__(self, user): """Perform the actual exporting""" if self.HTTP_POST != (request.method == 'POST'): raise HTTPAPIError( 'This action requires %s' % ('POST' if self.HTTP_POST else 'GET'), 405) if not self.GUEST_ALLOWED and not user: raise HTTPAPIError('Guest access to this resource is forbidden.', 403) method_name = self._getMethodName() func = getattr(self, method_name, None) extra_func = getattr(self, method_name + '_extra', None) if not func: raise NotImplementedError(method_name) if not self.COMMIT: is_response, resultList, complete, extra = self._perform( user, func, extra_func) db.session.rollback() else: try: init_email_queue() is_response, resultList, complete, extra = self._perform( user, func, extra_func) db.session.commit() flush_email_queue() except Exception: db.session.rollback() raise if is_response: return resultList return resultList, extra, complete, self.SERIALIZER_TYPE_MAP
def checkAK(apiKey, signature, timestamp, path, query): apiMode = api_settings.get('security_mode') if not apiKey: if apiMode in { APIMode.ONLYKEY, APIMode.ONLYKEY_SIGNED, APIMode.ALL_SIGNED }: raise HTTPAPIError('API key is missing', 403) return None, True try: UUID(hex=apiKey) except ValueError: raise HTTPAPIError('Malformed API key', 400) ak = APIKey.find_first(token=apiKey, is_active=True) if not ak: raise HTTPAPIError('Invalid API key', 403) if ak.is_blocked: raise HTTPAPIError('API key is blocked', 403) # Signature validation onlyPublic = False if signature: validateSignature(ak, signature, timestamp, path, query) elif apiMode == APIMode.ALL_SIGNED: raise HTTPAPIError('Signature missing', 403) elif apiMode in {APIMode.SIGNED, APIMode.ONLYKEY_SIGNED}: onlyPublic = True return ak, onlyPublic
def _getParams(self): super()._getParams() event = self._obj = Event.get(self._pathParams['event_id'], is_deleted=False) if event is None: raise HTTPAPIError('No such event', 404) session_id = self._pathParams.get('session_id') if session_id: self._obj = Session.query.with_parent(event).filter_by( id=session_id).first() if self._obj is None: raise HTTPAPIError("No such session", 404) contribution_id = self._pathParams.get('contribution_id') if contribution_id: contribution = self._obj = ( Contribution.query.with_parent(event).filter_by( id=contribution_id, is_deleted=False).first()) if contribution is None: raise HTTPAPIError("No such contribution", 404) subcontribution_id = self._pathParams.get('subcontribution_id') if subcontribution_id: self._obj = SubContribution.query.with_parent( contribution).filter_by(id=subcontribution_id, is_deleted=False).first() if self._obj is None: raise HTTPAPIError("No such subcontribution", 404) self._note = EventNote.get_for_linked_object(self._obj, preload_event=False) if self._note is None or self._note.is_deleted: raise HTTPAPIError("No such note", 404)
def _getParams(self): super(NoteExportHook, self)._getParams() event = self._obj = ConferenceHolder().getById( self._pathParams['event_id'], True) if event is None: raise HTTPAPIError('No such event', 404) session_id = self._pathParams.get('session_id') if session_id: session = self._obj = event.getSessionById(session_id) if session is None: raise HTTPAPIError("No such session", 404) contribution_id = self._pathParams.get('contribution_id') if contribution_id: contribution = self._obj = event.getContributionById( contribution_id) if contribution is None: raise HTTPAPIError("No such contribution", 404) subcontribution_id = self._pathParams.get('subcontribution_id') if subcontribution_id: subcontribution = self._obj = contribution.getSubContributionById( subcontribution_id) if subcontribution is None: raise HTTPAPIError("No such subcontribution", 404) self._note = EventNote.get_for_linked_object(self._obj) if self._note is None or self._note.is_deleted: raise HTTPAPIError("No such note", 404)
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 api_roomBooking(self, aw): resv = CrossLocationFactory.newReservation(location=self._params['location']) resv.room = self._room resv.startDT = self._fromDT.replace(tzinfo=None) resv.endDT = self._toDT.replace(tzinfo=None) # checking room availability for nbd in resv.room.getNonBookableDates(): if (doesPeriodOverlap(nbd.getStartDate(), nbd.getEndDate(), resv.startDT, resv.endDT)): raise HTTPAPIError('Failed to create the booking. You cannot book this room because it is unavailable during this time period.') roomBlocked = resv.room.getBlockedDay(resv.startDT) # checking room blocking if roomBlocked and not roomBlocked.block.canOverride(self._user): raise HTTPAPIError('Failed to create the booking. You cannot book this room because it is blocked during this time period.') resv.repeatability = None resv.reason = self._params['reason'] resv.createdDT = datetime.now() resv.createdBy = str(self._user.getId()) resv.bookedForName = self._params['userBookedFor'].getFullName() resv.contactEmail = self._params['userBookedFor'].getEmail() resv.contactPhone = self._params['userBookedFor'].getTelephone() resv.isRejected = False resv.isCancelled = False resv.isConfirmed = True if resv.getCollisions(): raise HTTPAPIError('Failed to create the booking. There is a collision with another booking.') resv.insert() return {'reservationID': resv.id}
def export_user(self, user): if not user: raise HTTPAPIError('You need to be logged in', 403) user = User.get(self._user_id, is_deleted=False) if not user: raise HTTPAPIError('Requested user not found', 404) if not user.can_be_modified(user): raise HTTPAPIError('You do not have access to that info', 403) return [user.as_avatar.fossilize()]
def validateSignature(ak, signature, timestamp, path, query): ttl = api_settings.get('signature_ttl') if not timestamp and not (ak.is_persistent_allowed and api_settings.get('allow_persistent')): raise HTTPAPIError('Signature invalid (no timestamp)', 403) elif timestamp and abs(timestamp - int(time.time())) > ttl: raise HTTPAPIError('Signature invalid (bad timestamp)', 403) digest = hmac.new(ak.secret, normalizeQuery(path, query), hashlib.sha1).hexdigest() if signature != digest: raise HTTPAPIError('Signature invalid', 403)
def validateSignature(ak, minfo, signature, timestamp, path, query): ttl = HelperMaKaCInfo.getMaKaCInfoInstance().getAPISignatureTTL() if not timestamp and not (ak.isPersistentAllowed() and minfo.isAPIPersistentAllowed()): raise HTTPAPIError('Signature invalid (no timestamp)', apache.HTTP_FORBIDDEN) elif timestamp and abs(timestamp - int(time.time())) > ttl: raise HTTPAPIError('Signature invalid (bad timestamp)', apache.HTTP_FORBIDDEN) digest = hmac.new(ak.getSignKey(), normalizeQuery(path, query), hashlib.sha1).hexdigest() if signature != digest: raise HTTPAPIError('Signature invalid', apache.HTTP_FORBIDDEN)
def _getParams(self): super(AgreementExportHook, self)._getParams() type_ = self._pathParams['agreement_type'] try: self._definition = get_agreement_definitions()[type_] except KeyError: raise HTTPAPIError('No such agreement type', 404) self.event = Event.get(self._pathParams['event_id'], is_deleted=False) if self.event is None: raise HTTPAPIError('No such event', 404)
def export_user(self, aw): requested_user = AvatarHolder().getById(self._user_id) user = aw.getUser() if not requested_user: raise HTTPAPIError('Requested user not found', 404) if user: if requested_user.canUserModify(user): return [requested_user.fossilize()] raise HTTPAPIError('You do not have access to that info', 403) raise HTTPAPIError('You need to be logged in', 403)
def _getParams(self): super(AgreementExportHook, self)._getParams() type_ = self._pathParams['agreement_type'] try: self._definition = get_agreement_definitions()[type_] except KeyError: raise HTTPAPIError('No such agreement type', 404) self._event = ConferenceHolder().getById(self._pathParams['event_id'], True) if self._event is None: raise HTTPAPIError('No such event', 404)
def export_user(self, user): from indico.modules.users.schemas import UserSchema if not user: raise HTTPAPIError('You need to be logged in', 403) user = User.get(self._user_id, is_deleted=False) if not user: raise HTTPAPIError('Requested user not found', 404) if not user.can_be_modified(user): raise HTTPAPIError('You do not have access to that info', 403) return [UserSchema().dump(user)]
def __call__(self, aw): """Perform the actual exporting""" if self.HTTP_POST != (request.method == 'POST'): raise HTTPAPIError( 'This action requires %s' % ('POST' if self.HTTP_POST else 'GET'), 405) if not self.GUEST_ALLOWED and not aw.getUser(): raise HTTPAPIError('Guest access to this resource is forbidden.', 403) method_name = self._getMethodName() func = getattr(self, method_name, None) extra_func = getattr(self, method_name + '_extra', None) if not func: raise NotImplementedError(method_name) if not self.COMMIT: is_response, resultList, complete, extra = self._perform( aw, func, extra_func) else: dbi = DBMgr.getInstance() try: for i, retry in enumerate(transaction.attempts(10)): with retry: if i > 0: dbi.abort() flush_after_commit_queue(False) GenericMailer.flushQueue(False) dbi.sync() try: is_response, resultList, complete, extra = self._perform( aw, func, extra_func) transaction.commit() flush_after_commit_queue(True) GenericMailer.flushQueue(True) break except ConflictError: transaction.abort() except ClientDisconnected: transaction.abort() time.sleep(i * 5) else: raise HTTPAPIError( 'An unresolvable database conflict has occured', 500) except Exception: transaction.abort() raise if is_response: return resultList return resultList, extra, complete, self.SERIALIZER_TYPE_MAP
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.query.join(User.identities).filter(~User.is_deleted, Identity.identifier == username).all() 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 api_recordingManager(self, aw): if not self._indicoID or not self._cdsID: raise HTTPAPIError('A required argument is missing.', apache.HTTP_BAD_REQUEST) success = createIndicoLink(self._indicoID, self._cdsID) return {'success': success}
def _process(self, iterator, filter=None, iface=None): if iface is None: iface = self.DETAIL_INTERFACES.get(self._detail) if iface is None: raise HTTPAPIError('Invalid detail level: %s' % self._detail, 400) for obj in self._iterateOver(iterator, self._offset, self._limit, self._orderBy, self._descending, filter): yield self._postprocess(obj, self._makeFossil(obj, iface), iface)
def _getParams(self): super(CollaborationExportHook, self)._getParams() self._conf = ConferenceHolder().getById(self._pathParams['confId'], True) if not self._conf: raise HTTPAPIError('Conference does not exist.', apache.HTTP_BAD_REQUEST)
def _getParams(self): super(FileHook, self)._getParams() self._event = self._pathParams['event'] self._session = self._pathParams['session'] self._contrib = self._pathParams['contrib'] self._subcontrib = self._pathParams['subcontrib'] self._material = self._pathParams['material'] self._res = self._pathParams['res'] self._params = { 'confId': self._event, 'sessionId': self._session, 'contribId': self._contrib, 'subContId': self._subcontrib, 'materialId': self._material, 'resId': self._res } import MaKaC.webinterface.locators as locators l = locators.WebLocator() try: l.setResource(self._params) self._file = l.getObject() except (KeyError, AttributeError): raise HTTPAPIError("File not found", 404)
def _getParams(self): super()._getParams() self._attachment = Attachment.get(int(self._pathParams['res'])) if not self._attachment: raise HTTPAPIError("File not found", 404)
def export_linked_events(self, aw): if not redis_client: raise HTTPAPIError('This API is only available when using Redis') self._checkProtection(aw) links = avatar_links.get_links(self._avatar.user, self._fromDT, self._toDT) for event_id in get_events_registered(self._avatar.user, self._fromDT, self._toDT): links.setdefault(str(event_id), set()).add('registration_registrant') for event_id in get_events_with_submitted_surveys( self._avatar.user, self._fromDT, self._toDT): links.setdefault(str(event_id), set()).add('survey_submitter') for event_id in get_events_managed_by(self._avatar.user, self._fromDT, self._toDT): links.setdefault(str(event_id), set()).add('conference_manager') for event_id in get_events_created_by(self._avatar.user, self._fromDT, self._toDT): links.setdefault(str(event_id), set()).add('conference_creator') for event_id, principal_roles in get_events_with_linked_sessions( self._avatar.user, self._fromDT, self._toDT).iteritems(): links.setdefault(str(event_id), set()).update(principal_roles) for event_id, principal_roles in get_events_with_linked_contributions( self._avatar.user, self._fromDT, self._toDT).iteritems(): links.setdefault(str(event_id), set()).update(principal_roles) for event_id in get_events_with_linked_event_persons( self._avatar.user, self._fromDT, self._toDT): links.setdefault(str(event_id), set()).add('conference_chair') return UserRelatedEventFetcher(aw, self, links).events(links.keys())
def _checkProtection(self, aw): if not self._avatar: # No avatar specified => use self. No need to check any permissinos. self._avatar = aw.getUser() return elif not self._avatar.canUserModify(aw.getUser()): raise HTTPAPIError('Access denied', 403)
def _perform(self, aw, func, extra_func): self._getParams() if not self._hasAccess(aw): raise HTTPAPIError('Access to this resource is restricted.', 403) resultList, complete = self._performCall(func, aw) extra = extra_func(aw, resultList) if extra_func else None return resultList, complete, extra
def _hasAccess(self, aw): if not Config.getInstance().getIsRoomBookingActive() or not rb_check_user_access(aw.getUser()): return False if self._room.can_be_booked(aw.getUser()): return True elif self._room.can_be_prebooked(aw.getUser()): raise HTTPAPIError('The API only supports direct bookings but this room only allows pre-bookings.') return False
def _has_access(self, user): if not config.ENABLE_ROOMBOOKING or not rb_check_user_access(user): return False if self._room.can_book(user): return True elif self._room.can_prebook(user): raise HTTPAPIError('The API only supports direct bookings but this room only allows pre-bookings.') return False
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 __call__(self, aw, req): """Perform the actual exporting""" if self.HTTP_POST != (req.method == 'POST'): raise HTTPAPIError( 'This action requires %s' % ('POST' if self.HTTP_POST else 'GET'), apache.HTTP_METHOD_NOT_ALLOWED) self._req = req self._getParams() req = self._req if not self.GUEST_ALLOWED and not aw.getUser(): raise HTTPAPIError('Guest access to this resource is forbidden.', apache.HTTP_FORBIDDEN) if not self._hasAccess(aw): raise HTTPAPIError('Access to this resource is restricted.', apache.HTTP_FORBIDDEN) func = getattr(self, self.PREFIX + '_' + self._type, None) if not func: raise NotImplementedError(self.PREFIX + '_' + self._type) if not self.COMMIT: # Just execute the function, we'll never have to repeat it resultList, complete = self._performCall(func, aw) else: # Try it a few times until commit succeeds dbi = DBMgr.getInstance() for _retry in xrange(10): dbi.sync() resultList, complete = self._performCall(func, aw) try: dbi.commit() except ConflictError: pass # retry else: break else: raise HTTPAPIError( 'An unresolvable database conflict has occured', apache.HTTP_INTERNAL_SERVER_ERROR) extraFunc = getattr(self, self.PREFIX + '_' + self._type + '_extra', None) extra = extraFunc(aw, resultList) if extraFunc else None return resultList, extra, complete, self.SERIALIZER_TYPE_MAP
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 _perform(self, user, func, extra_func): self._getParams() if not self._has_access(user): raise HTTPAPIError('Access to this resource is restricted.', 403) resultList, complete = self._performCall(func, user) if isinstance(resultList, current_app.response_class): return True, resultList, None, None extra = extra_func(user, resultList) if extra_func else None return False, resultList, complete, extra