def _to_python(self, itemId, state): itemType = self.itemType if self.itemType else 'item' if not itemId or not itemId[0]: raise MissingParam('%s-id' % (itemType), itemId, state) itemId = itemId[0] columns = set(['meta']).update(self.columns) item = yield db.get_slice(itemId, "items", columns) if not item: raise InvalidItem(itemType, itemId, state) item = utils.supercolumnsToDict(item) meta = item["meta"] if self.itemType and meta["type"] != self.itemType: raise InvalidItem(itemType, itemId, state) parentId = meta.get("parent", None) if parentId: parent = yield db.get_slice(parentId, "items", ["meta"]) parent = utils.supercolumnsToDict(parent) else: parent = item acl = parent["meta"]["acl"] owner = parent["meta"]["owner"] #parent is deleted deleted = parent['meta'].get('state', None) == 'deleted' #item is deleted deleted = deleted or meta.get('state', None) == 'deleted' if deleted: raise InvalidItem(itemType, itemId, state) if self.source != 'api': request = state.request authInfo = request.getSession(IAuthInfo) myId = authInfo.username orgId = authInfo.organization isOrgAdmin = authInfo.isAdmin isOrgAdmin = self.checkAdmin and isOrgAdmin relation = Relation(myId, []) yield relation.initGroupsList() if not utils.checkAcl(myId, orgId, isOrgAdmin, relation, parent['meta']): raise ItemAccessDenied(itemType, itemId, state) defer.returnValue((itemId, item))
def _getKeywordMatches(self, request, keyword, start='', count=10): args = {} authinfo = request.getSession(IAuthInfo) myId = authinfo.username orgId = authinfo.organization items = {} itemIds = [] itemIdKeyMap = {} allFetchedItems = set() deleted = set() fetchStart = utils.decodeKey(start) fetchCount = count + 2 while len(itemIds) < count: fetchedItemIds = [] toFetchItems = set() results = yield db.get_slice(orgId + ":" + keyword, "keywordItems", count=fetchCount, start=fetchStart, reverse=True) for col in results: fetchStart = col.column.name itemAndParentIds = col.column.value.split(':') itemIdKeyMap[itemAndParentIds[0]] = fetchStart fetchedItemIds.append(itemAndParentIds[0]) for itemId in itemAndParentIds: if itemId not in allFetchedItems: toFetchItems.add(itemId) allFetchedItems.add(itemId) if toFetchItems: fetchedItems = yield db.multiget_slice(toFetchItems, "items", ["meta", "attachments"]) fetchedItems = utils.multiSuperColumnsToDict(fetchedItems) items.update(fetchedItems) for itemId in fetchedItemIds: item = items[itemId] if not 'meta' in item: continue state = item['meta'].get('state', 'published') if state == 'deleted': deleted.add(itemIdKeyMap[itemId]) elif utils.checkAcl(myId, orgId, True, None, item['meta']): itemIds.append(itemId) if len(results) < fetchCount: break if len(itemIds) > count: nextPageStart = utils.encodeKey(itemIdKeyMap[itemIds[-1]]) itemIds = itemIds[:-1] else: nextPageStart = None dd = db.batch_remove({'keywordItems': [orgId + ':' + keyword]}, names=deleted) if deleted else defer.succeed([]) args.update({'items': items, 'myId': myId}) toFetchEntities = set() extraDataDeferreds = [] for itemId in itemIds: item = items[itemId] itemMeta = item['meta'] toFetchEntities.add(itemMeta['owner']) if 'target' in itemMeta: toFetchEntities.update(itemMeta['target'].split(',')) if 'parent' in itemMeta: parentId = itemMeta['parent'] if parentId in items: toFetchEntities.add(items[parentId]['meta']['owner']) itemType = itemMeta.get('type', 'status') if itemType in plugins: d = plugins[itemType].fetchData(args, itemId) extraDataDeferreds.append(d) result = yield defer.DeferredList(extraDataDeferreds) for success, ret in result: if success: toFetchEntities.update(ret) fetchedEntities = {} if toFetchEntities: fetchedEntities = base.EntitySet(toFetchEntities) yield fetchedEntities.fetchData() yield dd args.update({'entities': fetchedEntities, 'matches': itemIds, 'nextPageStart': nextPageStart}) defer.returnValue(args)
def _invite(self, request, convId=None): (appchange, script, args, myId) = yield self._getBasicArgs(request) landing = not self._ajax myOrgId = args['orgId'] convId, conv = yield utils.getValidItemId(request, "id", columns=["invitees"]) # Parse invitees from the tag edit plugin values arg_keys = request.args.keys() invitees, new_invitees = [], [] for arg in arg_keys: if arg.startswith("invitee[") and arg.endswith("-a]"): rcpt = arg.replace("invitee[", "").replace("-a]", "") if rcpt != "": invitees.append(rcpt) if myId not in conv["invitees"].keys(): raise errors.invalidRequest(_("Only those who are invited can invite others")) res = base.EntitySet(invitees) yield res.fetchData() invitees = [x for x in res.keys() if res[x].basic["org"] == myOrgId] invitees = [x for x in invitees if x not in conv["invitees"].keys()] relation = Relation(myId, []) updateConv = {"meta":{}, "invitees":{}} if myId == conv["meta"]["owner"]: #If invited by owner, add the invitees to the ACL acl = conv["meta"]["acl"] acl = pickle.loads(acl) acl.setdefault("accept", {}).setdefault("users", []) acl["accept"]["users"].extend(invitees) updateConv["meta"]["acl"] = pickle.dumps(acl) new_invitees.extend(invitees) else: for invitee in invitees: relation = Relation(invitee, []) yield relation.initGroupsList() withinAcl = utils.checkAcl(invitee, myOrgId, False, relation, conv["meta"]) if withinAcl: new_invitees.append(invitee) if new_invitees: convMeta = conv["meta"] starttime = int(convMeta["event_startTime"]) starttimeUUID = utils.uuid1(timestamp=starttime) starttimeUUID = starttimeUUID.bytes endtime = int(convMeta["event_endTime"]) endtimeUUID = utils.uuid1(timestamp=endtime) endtimeUUID = endtimeUUID.bytes updateConv["invitees"] = dict([(x, myId) for x in new_invitees]) d = yield db.batch_insert(convId, "items", updateConv) yield event.inviteUsers(request, starttimeUUID, endtimeUUID, convId, conv["meta"], myId, myOrgId, new_invitees) request.write("""$$.alerts.info('%s');""" \ %("%d people invited to this event" %len(new_invitees))) else: if not invitees: request.write("""$$.alerts.info('%s');""" \ %("Invited persons are already on the invitation list")) else: request.write("""$$.alerts.info('%s');""" \ %("Invited persons do not have access to this event")) request.write("$('#item-subactions .tagedit-listelement-old').remove();")
def userFiles(myId, entityId, myOrgId, start='', end='', fromFeed=True): allItems = {} hasPrevPage = False # Do we have another page before the current one. nextPageStart = '' # Start item for the next page accessibleFiles = [] accessibleItems = [] toFetchEntities = set() count = constants.FILES_PER_PAGE toFetchCount = count + 1 relation = Relation(myId, []) yield relation.initGroupsList() # Fetching files owned by entityId or files that were part of entityId's feed. cf = 'entityFeed_files' if fromFeed else 'user_files' # End is actually the start item of next page. # If @end is set, we have to display @count items before @end. For that # we fetch @count + 2 items before (and including) @end. Of the extra items # fetched, one item helps us determine if there is another page before this # and the other one is the start of next page. if end: start = end reverse = False toFetchCount += 1 else: reverse = True while 1: files = yield db.get_slice(entityId, cf, count=toFetchCount, start=start, reverse=reverse) files = utils.columnsToDict(files, True) toFetchItems = [] for tuuid in files: if len(files[tuuid].split(':')) == 4: fid, name, itemId, attachmentId = files[tuuid].split(':') toFetchItems.append(itemId) toFetchItems = [itemId for itemId in toFetchItems if itemId not in accessibleItems] if toFetchItems: items = yield db.multiget_slice(toFetchItems, "items", ["meta"]) items = utils.multiSuperColumnsToDict(items) toFetchConvIds = [items[itemId]['meta']['parent'] for itemId in items if 'parent' in items[itemId]['meta'] and items[itemId]['meta']['parent'] not in allItems] if toFetchConvIds: convs = yield db.multiget_slice(toFetchConvIds, "items", ["meta"]) convs = utils.multiSuperColumnsToDict(convs) allItems.update(convs) allItems.update(items) for itemId in items: if 'parent' in items[itemId]['meta']: convId = items[itemId]['meta']['parent'] acl = allItems[convId]['meta']['acl'] else: acl = items[itemId]['meta']['acl'] convId = itemId if utils.checkAcl(myId, myOrgId, False, relation, allItems[convId]['meta']): accessibleItems.append(itemId) for tuuid in files: if len(files[tuuid].split(':')) == 4: fid, name, itemId, ownerId = files[tuuid].split(':') if itemId in accessibleItems: accessibleFiles.append((tuuid, (fid, urlsafe_b64decode(name), itemId, ownerId, allItems[itemId]))) toFetchEntities.add(ownerId) if len(files) < toFetchCount or len(accessibleFiles) > count: break else: start = files.keys()[-1] if end: # We have enough items to have another page before this. if len(accessibleFiles) > count + 1: hasPrevPage = True accessibleFiles = accessibleFiles[:count + 1] # Revert the list to get most recent items first. accessibleFiles.reverse() # The last item is actually the first item of next page. nextPageStart = accessibleFiles[-1][0] accessibleFiles = accessibleFiles[:-1] elif start: hasPrevPage = True # XXX: may not always be true, but the edge case is OK if len(accessibleFiles) > count: nextPageStart = accessibleFiles[count][0] accessibleFiles = accessibleFiles[:count] defer.returnValue((accessibleFiles, hasPrevPage, nextPageStart, toFetchEntities))