def on_get(self, req, resp, userid=None, method=None): server, store = _server_store(req, userid if userid != 'delta' else None, self.options) if not userid and req.path.split('/')[-1] != 'users': userid = kopano.Store(server=server, mapiobj = GetDefaultStore(server.mapisession)).user.userid if method and not store: raise falcon.HTTPNotFound(description="The user store has no store") if not method: if userid: if userid == 'delta': req.context['deltaid'] = '{userid}' self.delta(req, resp, server) return else: data = server.user(userid=userid) else: args = self.parse_qs(req) userid = kopano.Store(server=server, mapiobj = GetDefaultStore(server.mapisession)).user.userid company = server.user(userid=userid).company query = None if '$search' in args: query = args['$search'][0] def yielder(**kwargs): yield from company.users(hidden=False, inactive=False, query=query, **kwargs) data = self.generator(req, yielder) self.respond(req, resp, data) elif method == 'mailFolders': data = self.generator(req, store.mail_folders, 0) self.respond(req, resp, data, MailFolderResource.fields) elif method == 'contactFolders': data = self.generator(req, store.contact_folders, 0) self.respond(req, resp, data, ContactFolderResource.fields) elif method == 'messages': # TODO store-wide? data = self.folder_gen(req, store.inbox) self.respond(req, resp, data, MessageResource.fields) elif method == 'contacts': data = self.folder_gen(req, store.contacts) self.respond(req, resp, data, ContactResource.fields) elif method == 'calendars': data = self.generator(req, store.calendars, 0) self.respond(req, resp, data, CalendarResource.fields) elif method == 'events': # TODO multiple calendars? calendar = store.calendar data = self.generator(req, calendar.items, calendar.count) self.respond(req, resp, data, EventResource.fields) elif method == 'calendarView': # TODO multiple calendars? merge code with calendar.py start, end = _start_end(req) def yielder(**kwargs): for occ in store.calendar.occurrences(start, end, **kwargs): yield occ data = self.generator(req, yielder) self.respond(req, resp, data, EventResource.fields) elif method == 'reminderView': # TODO multiple calendars? # TODO use restriction in pyko: calendar.reminders(start, end)? start, end = _start_end(req) def yielder(**kwargs): for occ in store.calendar.occurrences(start, end): if occ.reminder: yield occ data = self.generator(req, yielder) self.respond(req, resp, data, ReminderResource.fields) elif method == 'memberOf': user = server.user(userid=userid) data = (user.groups(), DEFAULT_TOP, 0, 0) self.respond(req, resp, data, GroupResource.fields) elif method == 'photos': # TODO multiple photos? user = server.user(userid=userid) def yielder(**kwargs): photo = user.photo if photo: yield photo data = self.generator(req, yielder) self.respond(req, resp, data, ProfilePhotoResource.fields) elif method: raise HTTPBadRequest("Unsupported segment '%s'" % method)
def _store(server, userid): if userid: return server.user(userid=userid).store else: return kopano.Store(server=server, mapiobj=GetDefaultStore(server.mapisession))
def convertaction(action, user,server): action_message = '' movetype = {1: 'Move', 2: 'Copy',} try: countact = len(action.Value.lpAction) except AttributeError: return 'Unknown action' num = 0 for act in action.Value.lpAction: if not act.actobj: if act.acttype == 11: action_message += 'Mark item as read' if isinstance(act.actobj, actDeferAction): action_message += 'Deferred action (client side rule)' if isinstance(act.actobj, actMoveCopy): folderid = binascii.hexlify(act.actobj.FldEntryId) storeid = act.actobj.StoreEntryId try: try: foldername = user.store.folder(entryid=folderid).name except TypeError: foldername = user.store.folder(folderid).name except kopano.NotFoundError: try: mapistore = server.mapisession.OpenMsgStore(0, storeid, IID_IMsgStore, MDB_WRITE) newstore = kopano.Store(mapiobj=mapistore, server=server) try: foldername = '%s (%s)' % (newstore.folder(entryid=folderid).name, newstore.user.name) except TypeError: foldername = '%s (%s)' % (newstore.folder(folderid).name, newstore.user.name) except AttributeError: foldername = 'Folder not available' except MAPI.Struct.MAPIErrorNotFound: foldername = 'unknown' if act.acttype == 1: if folderid == binascii.hexlify(user.store.prop(PR_IPM_WASTEBASKET_ENTRYID).value): action_message += 'Delete message' else: action_message += "%s message to folder '%s'" % (movetype[act.acttype], foldername) else: action_message += "%s message to folder '%s'" % (movetype[act.acttype], foldername) if isinstance(act.actobj, actFwdDelegate): sendstype = {0: 'Forward message to ', 3: 'Redirect message to ', 4: 'Forward the message as attachment to '} countaddress = len(act.actobj.lpadrlist) addnum = 0 action_message += sendstype[act.ulActionFlavor] for addresses in act.actobj.lpadrlist: action_message += addresses[5].Value addnum += 1 if addnum != countaddress and countaddress != 1: action_message += "," num += 1 if num != countact and countact != 1: action_message += "\n" return action_message
def on_get(self, req, resp, userid=None, method=None): if not method: handler = self.handle_get elif method == 'mailFolders': handler = MailFolderResource.get_all elif method == 'notebooks': handler = NotebookResource.get_all elif method == 'todolists': handler = TodoListResource.get_all elif method == 'contactFolders': handler = ContactFolderResource.get_all elif method == 'calendars': handler = CalendarResource.get_all elif method == 'messages': # TODO store-wide? handler = MessageResource.get_all elif method == 'notes': # TODO store-wide? handler = NoteResource.get_all elif method == 'tasks': # TODO store-wide? handler = TaskResource.get_all elif method == 'contacts': handler = ContactResource.get_all elif method == 'events': # TODO multiple calendars? handler = EventResource.get_all elif method == 'calendarView': # TODO multiple calendars? handler = CalendarResource.get_calendar_view elif method == 'reminderView': # TODO multiple calendars? # TODO use restriction in pyko: calendar.reminders(start, end)? handler = self.handle_get_reminderView elif method == 'memberOf': handler = self.handle_get_memberOf elif method == 'photos': # TODO multiple photos? handler = self.handle_get_photos elif method: raise HTTPBadRequest("Unsupported user segment '%s'" % method) else: raise HTTPBadRequest("Unsupported in user") try: server, store, userid = _server_store(req, userid, self.options) except MAPIErrorInvalidEntryid: raise HTTPBadRequest("Invalid entryid provided") if not userid and req.path.split('/')[-1] != 'users': userid = kopano.Store(server=server, mapiobj=server.mapistore).user.userid handler(req, resp, store=store, server=server, userid=userid)
def _server(req, options, forceReconnect=False): global TOKEN_SESSION global TOKEN_SESSION_PURGE_TIME global PASSTHROUGH_SESSION global DANGLE_INDEX auth = _auth(req, options) if not auth: raise falcon.HTTPForbidden(title='Unauthorized', description=None) now = time.monotonic() if auth['method'] == 'bearer': token = auth['token'] userid = req.context.userid = auth['userid'] cacheid = token # NOTE(longsleep): We cache per user even if that means that from time to time, the connection # breaks because the token has expired. with threadLock: sessiondata = TOKEN_SESSION.get(cacheid) if sessiondata: record = sessiondata[0] if not forceReconnect: server = record.server try: server.user(userid=userid) except Exception: logging.exception( 'network or session (%s) error while reusing bearer token user %s session, reconnect automatically', id(server), userid) forceReconnect = True if forceReconnect: with threadLock: oldSessiondata = TOKEN_SESSION.pop(cacheid) DANGLE_INDEX += 1 TOKEN_SESSION['{}_dangle_{}'.format( cacheid, DANGLE_INDEX)] = oldSessiondata sessiondata = None if options and options.with_metrics: DANGLING_COUNT.inc() else: sessiondata[ 1] = now # NOTE(longsleep): Mutate is threadsafe in CPython - we do not care who wins here. if options and options.with_metrics: SESSION_RESUME_COUNT.inc() if not sessiondata: logging.debug('creating session for bearer token user %s', userid) server = kopano.Server(auth_user=userid, auth_pass=token, parse_args=False, store_cache=False, oidc=True, config={}) store = kopano.Store(server=server, mapiobj=server.mapistore) record = Record(server=server, store=store) sessiondata = [record, now] with threadLock: if cacheid: TOKEN_SESSION[cacheid] = sessiondata else: DANGLE_INDEX += 1 TOKEN_SESSION['_dangle_{}'.format( DANGLE_INDEX)] = sessiondata if options and options.with_metrics: SESSION_CREATE_COUNT.inc() TOKEN_SESSION_ACTIVE.inc() return record elif auth['method'] == 'basic': logging.debug('creating session for basic auth user %s', auth['user']) server = kopano.Server(auth_user=auth['user'], auth_pass=auth['password'], parse_args=False, store_cache=False, config={}) store = kopano.Store(server=server, mapiobj=server.mapistore) if options and options.with_metrics: SESSION_CREATE_COUNT.inc() return Record(server=server, store=store) # TODO(longsleep): Add expiration for PASSTHROUGH_SESSION contents. elif auth['method'] == 'passthrough': userid = req.context.userid = auth['userid'] cacheid = userid # NOTE(longsleep): We cache per user id. with threadLock: sessiondata = PASSTHROUGH_SESSION.get(cacheid) if sessiondata: record = sessiondata[0] if not forceReconnect: server = record.server try: server.user(userid=userid) except Exception: logging.exception( 'network or session (%s) error while reusing passthrough user session user %s, reconnect automatically', id(server), userid) forceReconnect = True if forceReconnect: with threadLock: oldSessiondata = PASSTHROUGH_SESSION.pop(cacheid) DANGLE_INDEX += 1 PASSTHROUGH_SESSION['_dangle_{}'.format( DANGLE_INDEX)] = oldSessiondata sessiondata = None if options and options.with_metrics: DANGLING_COUNT.inc() else: sessiondata[1] = time.monotonic( ) # NOTE(longsleep): Array mutate is threadsafe in CPython - we do not care who wins here. if options and options.with_metrics: SESSION_RESUME_COUNT.inc() if not sessiondata: logging.debug('creating session for passthrough user %s', userid) server = kopano.Server(userid=userid, auth_pass='', parse_args=False, store_cache=False, config={}) store = kopano.Store(server=server, mapiobj=server.mapistore) record = Record(server=server, store=store) sessiondata = [record, now] with threadLock: PASSTHROUGH_SESSION[cacheid] = sessiondata if options and options.with_metrics: SESSION_CREATE_COUNT.inc() PASSTHROUGH_SESSIONS_ACTIVE.inc() return record