def _registerClient(self, request): (appchange, script, args, myId) = yield self._getBasicArgs(request) landing = not self._ajax myOrgId = args["orgId"] name = utils.getRequestArg(request, "name") desc = utils.getRequestArg(request, "desc") scope = utils.getRequestArg(request, "scope", multiValued=True) category = utils.getRequestArg(request, "category") redirect = utils.getRequestArg(request, "redirect", sanitize=False) if not name: raise errors.MissingParams(["Name"]) if not scope: raise errors.MissingParams(["Permissions"]) if category != "apikey" and not redirect: raise errors.MissingParams(["Redirect URL"]) knownScopes = globals().get("scopes") unknownScopes = [x for x in scope if x not in knownScopes.keys()] if category not in ["webapp", "native", "apikey"] or unknownScopes: raise errors.BaseError("Invalid value sent for Type/Permissions") clientId = utils.getUniqueKey() clientSecret = utils.getRandomKey() meta = { "author": myId, "name": name, "org": myOrgId, "secret": utils.hashpass(clientSecret), "scope": " ".join(scope), "category": category, } if category != "apikey": meta["redirect"] = b64encode(redirect) meta["desc"] = desc yield db.batch_insert(clientId, "apps", {"meta": meta}) yield db.insert(myId, "appsByOwner", "", clientId) yield db.insert(myOrgId, "appsByOwner", "", clientId) else: yield db.batch_insert(clientId, "apps", {"meta": meta}) yield db.insert(myId, "entities", "", clientId, "apikeys") self.setTitle(request, name) args["clientId"] = clientId args["client"] = meta args["client"]["secret"] = clientSecret t.renderScriptBlock(request, "apps.mako", "registrationResults", landing, "#apps-contents", "set", **args)
def _vote(self, request): convId, conv = yield utils.getValidItemId(request, 'id', 'poll', ['options']) vote = utils.getRequestArg(request, 'option') if not vote or vote not in conv.get("options", {}): raise errors.MissingParams(["Option"]) optionCounts = {} myId = request.getSession(IAuthInfo).username prevVote = yield db.get_slice(myId, "userVotes", [convId]) prevVote = prevVote[0].column.value if prevVote else False if prevVote == vote: yield self._results(request) return if prevVote: yield db.remove(convId, "votes", myId, prevVote) prevOptionCount = yield db.get_count(convId, "votes", prevVote) optionCounts[prevVote] = str(prevOptionCount) yield db.insert(myId, "userVotes", vote, convId) yield db.insert(convId, "votes", '', myId, vote) voteCount = yield db.get_count(convId, "votes", vote) optionCounts[vote] = str(voteCount) yield db.batch_insert(convId, "items", {"counts": optionCounts}) yield self._results(request)
def addUser(emailId, displayName, passwd, orgId, jobTitle=None, timezone=None): userId = getUniqueKey() userInfo = {"basic": {"name": displayName, "org": orgId, "type": "user", "emailId": emailId}} userAuthInfo = {"passwordHash": hashpass(passwd), "org": orgId, "user": userId} if jobTitle: userInfo["basic"]["jobTitle"] = jobTitle if timezone: userInfo["basic"]["timezone"] = timezone yield db.insert(orgId, "orgUsers", "", userId) yield db.batch_insert(userId, "entities", userInfo) yield db.batch_insert(emailId, "userAuth", userAuthInfo) yield updateDisplayNameIndex(userId, [orgId], displayName, None) yield updateNameIndex(userId, [orgId], displayName, None) yield updateNameIndex(userId, [orgId], emailId, None) defer.returnValue(userId)
def _addMembers(self, request): """This method add a new user to this conversation. Keyword Arguments: newMembers: A list of members who will be added to this conversation. convId: The id of the conversation to which these new members will be added as participants. CF Changes: mConversations """ myId = request.getSession(IAuthInfo).username orgId = request.getSession(IAuthInfo).organization newMembers, body, subject, convId = self._parseComposerArgs(request) if not (convId and newMembers): raise errors.MissingParams(['Recipient']) conv = yield db.get_slice(convId, "mConversations") conv = utils.supercolumnsToDict(conv) subject = conv['meta'].get('subject', None) participants = set(conv.get('participants', {}).keys()) if not conv: raise errors.InvalidMessage(convId) if myId not in participants: raise errors.MessageAccessDenied(convId) #cols = yield db.multiget_slice(newMembers, "entities", ['basic']) #people = utils.multiSuperColumnsToDict(cols) people = base.EntitySet(newMembers) yield people.fetchData() newMembers = set([userId for userId in people.keys() \ if people[userId].basic and \ people[userId].basic["org"] == orgId]) newMembers = newMembers - participants mailNotificants = participants - set([myId]) toFetchEntities = mailNotificants.union([myId, orgId]).union(newMembers) entities = base.EntitySet(toFetchEntities) yield entities.fetchData() data = {"entities": entities} data["orgId"] = orgId data["convId"] = convId data["subject"] = subject data["_fromName"] = entities[myId].basic['name'] if newMembers: data["message"] = conv["meta"]["snippet"] newMembers = dict([(userId, '') for userId in newMembers]) yield db.batch_insert(convId, "mConversations", {'participants': newMembers}) yield self._deliverMessage(convId, newMembers, conv['meta']['uuid'], conv['meta']['owner']) yield notifications.notify(newMembers, ":NM", myId, **data) if mailNotificants and newMembers: data["addedMembers"] = newMembers yield notifications.notify(mailNotificants, ":MA", myId, **data)
def updateData(): convIds = set() rows = yield db.get_range_slice('item_files', count=1000) for row in rows: convId = row.key convIds.add(convId) attachments = utils.supercolumnsToDict(row.columns) for attachmentId in attachments: for timeuuid in attachments[attachmentId]: encodedTimeUUID, aid, name, size, ftype = attachments[attachmentId][timeuuid].split(':') yield db.insert(attachmentId, "attachmentVersions", "%s:%s:%s:%s" %(aid, name, size, ftype), timeuuid) rows = yield db.get_range_slice('items', count=10000) for row in rows: itemId = row.key item = utils.supercolumnsToDict(row.columns) attachments = {} for attachmentId in item.get('attachments', {}): if len(item['attachments'][attachmentId].split(':')) == 4: x,name, size, ftype = item['attachments'][attachmentId].split(':') attachments[attachmentId] = "%s:%s:%s" %(name, size, ftype) if attachments: yield db.remove(itemId, 'items', super_column='attachments') yield db.batch_insert(itemId, "items", {"attachments": attachments}) rows = yield db.get_range_slice('mConversations', count=10000) for row in rows: messageId = row.key message = utils.supercolumnsToDict(row.columns) attachments = {} print messageId for attachmentId in message.get('attachments', {}): if len(message['attachments'][attachmentId].split(':')) == 4: x,name, size, ftype = message['attachments'][attachmentId].split(':') attachments[attachmentId] = "%s:%s:%s" %(name, size, ftype) if attachments: yield db.remove(messageId, 'mConversations', super_column='attachments') yield db.batch_insert(messageId, "mConversations", {"attachments": attachments})
def edit(me, group, name, access, desc, displayPic): """update group meta info. Only group-admin can edit group meta info. Keyword params: @me: @group: @name: name of the group. @access: group access type (open/closed). @desc: description of the group. @displayPic: profile pic of the group. """ if me.id not in group.admins: raise errors.PermissionDenied('Only administrator can edit group meta data') if name: start = name.lower() + ':' cols = yield db.get_slice(me.basic['org'], "entityGroupsMap", start=start, count=1) for col in cols: name_, groupId_ = col.column.name.split(':') if name_ == name.lower() and groupId_ != group.id: raise errors.InvalidGroupName(name) meta = {'basic': {}} if name and name != group.basic['name']: meta['basic']['name'] = name if desc and desc != group.basic.get('desc', ''): meta['basic']['desc'] = desc if access in ['closed', 'open'] and access != group.basic['access']: meta['basic']['access'] = access if displayPic: avatar = yield saveAvatarItem(group.id, me.basic['org'], displayPic) meta['basic']['avatar'] = avatar if name and name != group.basic["name"]: members = yield db.get_slice(group.id, "groupMembers") members = utils.columnsToDict(members).keys() entities = members + [me.basic['org']] oldColName = "%s:%s" % (group.basic["name"].lower(), group.id) colname = '%s:%s' % (name.lower(), group.id) mutations = {} for entity in entities: mutations[entity] = {'entityGroupsMap': {colname: '', oldColName: None}} #XXX:notify group-members about the change in name yield db.batch_mutate(mutations) if meta['basic']: yield db.batch_insert(group.id, 'entities', meta) if not desc and group.basic.get('desc', ''): yield db.remove(group.id, "entities", 'desc', 'basic') if (not desc and group.basic.get('desc', '')) or meta['basic']: defer.returnValue(True)
def unsubscribe(request, group, user): """Unsubscribe @user from @group. Remove the user from group-followers, group from user-groups, create a group-leave activity item and push item to group-followers and group feed. Remove the group from user display name indices. Raises an error if user is not member of group or when user is the only administrator of the group. keyword params: @user: entity object of user @group: entity object of the group @request: """ try: yield db.get(group.id, "groupMembers", user.id) except ttypes.NotFoundException: raise errors.InvalidRequest(_("You are not a member of the group")) if len(getattr(group, 'admins', {}).keys()) == 1 \ and user.id in group.admins: raise errors.InvalidRequest(_("You are the only administrator of this group")) colname = _entityGroupMapColName(group) itemType = "activity" responseType = "I" itemId = utils.getUniqueKey() acl = {"accept": {"groups": [group.id]}} _acl = pickle.dumps(acl) item = yield utils.createNewItem(request, itemType, user, acl, "groupLeave") item["meta"]["target"] = group.id d1 = db.remove(group.id, "followers", user.id) d2 = db.remove(user.id, "entityGroupsMap", colname) d3 = db.batch_insert(itemId, 'items', item) d4 = db.remove(group.id, "groupMembers", user.id) d5 = feed.pushToOthersFeed(user.id, user.basic['org'], item["meta"]["uuid"], itemId, itemId, _acl, responseType, itemType, user.id, promoteActor=False) d6 = utils.updateDisplayNameIndex(user.id, [group.id], None, user.basic['name']) deferreds = [d1, d2, d3, d4, d5, d6] if user.id in group.admins: d7 = db.remove(group.id, "entities", user.id, "admins") d8 = db.remove(user.id, "entities", group.id, "adminOfGroups") deferreds.extend([d7, d8]) yield defer.DeferredList(deferreds)
def _newConversation(self, ownerId, participants, meta, attachments): """Commit the meta information about a new conversation. Returns the conversation id of the newly created conversation. CF Changes: mConversations """ participants = dict([(userId, '') for userId in participants]) convId = utils.getUniqueKey() attach_meta = self._formatAttachMeta(attachments) yield db.batch_insert(convId, "mConversations", {"meta": meta, "participants": participants, "attachments": attach_meta}) defer.returnValue(convId)
def _upload_files(owner, tmp_fileIds): attachments = {} if tmp_fileIds: cols = yield db.multiget_slice(tmp_fileIds, "tmp_files", ["fileId"]) cols = multiColumnsToDict(cols) for tmpFileId in cols: attachmentId = getUniqueKey() timeuuid = uuid.uuid1().bytes val = cols[tmpFileId]["fileId"] fileId, name, size, ftype = val.split(":") meta = {"meta": {"uri": tmpFileId, "name": name, "fileType": ftype, "owner": owner}} yield db.batch_insert(tmpFileId, "files", meta) yield db.remove(tmpFileId, "tmp_files") yield db.insert(attachmentId, "attachmentVersions", val, timeuuid) attachments[attachmentId] = (fileId, name, size, ftype) defer.returnValue(attachments)
def _newMessage(self, ownerId, timeUUID, body, epoch): """Commit the meta information of a message. A message is a reply to a an existing conversation or the first message of a new conversation. CF Changes: messages """ messageId = utils.getUniqueKey() meta = {"owner": ownerId, "timestamp": str(int(time.time())), 'date_epoch': str(epoch), "body": body, "uuid": timeUUID} yield db.batch_insert(messageId, "messages", {'meta': meta}) defer.returnValue(messageId)
def createUser(emailId, displayName, jobTitle, timezone, passwd): localpart, domain = emailId.split("@") existingUser = yield db.get_count(emailId, "userAuth") if not existingUser: orgId = yield getOrgKey(domain) if not orgId: orgId = utils.getUniqueKey() domains = {domain:''} basic = {"name":domain, "type":"org"} yield db.batch_insert(orgId, "entities", {"basic":basic,"domains":domains}) yield db.insert(domain, "domainOrgMap", '', orgId) userId = yield utils.addUser(emailId, displayName, passwd, orgId, jobTitle, timezone) else: raise Exception("User already exists for " + emailId)
def _editWorkInfo(self, request): # Contact information at work. myId = request.getSession(IAuthInfo).username orgId = request.getSession(IAuthInfo).organization me = base.Entity(myId) yield me.fetchData([]) data = {} to_remove = [] for field in ["phone", "mobile"]: val = utils.getRequestArg(request, field) if val: data[field] = val else: to_remove.append(field) if 'phone' in data and not re.match('^\+?[0-9x\- ]{5,20}$', data['phone']): raise errors.InvalidRequest(_('Phone numbers can only have numerals, hyphens, spaces and a plus sign')) if 'mobile' in data and not re.match('^\+?[0-9x\- ]{5,20}$', data['mobile']): raise errors.InvalidRequest(_('Phone numbers can only have numerals, hyphens, spaces and a plus sign')) if data: yield db.batch_insert(myId, "entities", {"contact": data}) if to_remove: yield db.batch_remove({"entities":[myId]}, names=to_remove, supercolumn='contact') contactInfo = me.get('contact', {}) if any([contactInfo.get(x, None) != data.get(x, None) for x in ["phone", "mobile"]]): request.write('$$.alerts.info("%s");' % _('Profile updated')) args = {"detail": "", "me": me} suggestedSections = yield self._checkProfileCompleteness(request, myId, args) tmp_suggested_sections = {} for section, items in suggestedSections.iteritems(): if len(suggestedSections[section]) > 0: tmp_suggested_sections[section] = items args.update({'suggested_sections':tmp_suggested_sections}) t.renderScriptBlock(request, "settings.mako", "right", False, ".right-contents", "set", **args) me.update({'contact':data}) yield search.solr.updatePeopleIndex(myId, me, orgId)
def _addMember(request, group, user): """Add a new member to the group. Add user to group followers, create a group-join activity item and push item to group, group-followers feed. Update user groups with new group. Keyword params: @group: entity object of the group @user: entity object of the user @request: """ deferreds = [] itemType = "activity" relation = Relation(user.id, []) if not getattr(user, 'basic', []): yield user.fetchData(['basic']) responseType = "I" acl = {"accept": {"groups": [group.id]}} _acl = pickle.dumps(acl) itemId = utils.getUniqueKey() colname = _entityGroupMapColName(group) yield db.insert(user.id, "entityGroupsMap", "", colname) yield db.insert(group.id, "groupMembers", itemId, user.id) item = yield utils.createNewItem(request, "activity", user, acl, "groupJoin") item["meta"]["target"] = group.id d1 = db.insert(group.id, "followers", "", user.id) d2 = db.batch_insert(itemId, 'items', item) d3 = feed.pushToFeed(group.id, item["meta"]["uuid"], itemId, itemId, responseType, itemType, user.id) d4 = feed.pushToOthersFeed(user.id, user.basic['org'], item["meta"]["uuid"], itemId, itemId, _acl, responseType, itemType, user.id, promoteActor=False) d5 = utils.updateDisplayNameIndex(user.id, [group.id], user.basic['name'], None) deferreds = [d1, d2, d3, d4, d5] yield defer.DeferredList(deferreds)
def makeAdmin(request, group, user, me): """make user admin of the group. Only an group-administrator can make an group-member and administrator. Keyword params: @request: @me: @user: user object @group: group object """ if me.id not in group.admins: raise errors.PermissionDenied(_('You are not an administrator of the group')) cols = yield db.get_slice(group.id, "groupMembers", [user.id]) if not cols: raise errors.InvalidRequest(_('Only group member can become administrator')) if user.id in group.admins: defer.returnValue(None) yield db.insert(group.id, "entities", '', user.id, 'admins') yield db.insert(user.id, "entities", group.basic['name'], group.id, "adminOfGroups") itemType = "activity" responseType = "I" acl = {"accept": {"groups": [group.id]}} _acl = pickle.dumps(acl) itemId = utils.getUniqueKey() item = yield utils.createNewItem(request, "activity", user, acl, "groupAdmin") item["meta"]["target"] = group.id d1 = db.batch_insert(itemId, 'items', item) d2 = feed.pushToFeed(group.id, item["meta"]["uuid"], itemId, itemId, responseType, itemType, user.id) d3 = feed.pushToOthersFeed(user.id, user.basic['org'], item["meta"]["uuid"], itemId, itemId, _acl, responseType, itemType, user.id, promoteActor=False) yield defer.DeferredList([d1, d2, d3])
def _updateOrgInfo(self, request): (appchange, script, args, myId) = yield self._getBasicArgs(request) orgId = args["orgId"] org = args['org'] name = utils.getRequestArg(request, "name") dp = utils.getRequestArg(request, "dp", sanitize=False) orgInfo, orgDetails = {}, {} if dp: avatar = yield saveAvatarItem(orgId, orgId, dp, isLogo=True) orgInfo["basic"] = {} orgInfo["basic"]["logo"] = avatar org.basic['logo'] = avatar orgDetails["logo"] = utils.companyLogo(org) if name: if "basic" not in orgInfo: orgInfo["basic"] = {} orgInfo["basic"]["name"] = name args['org'].basic['name'] = name orgDetails["name"] = name if orgInfo: yield db.batch_insert(orgId, "entities", orgInfo) response = """ <script> var data = %s; if (data.logo){ var imageUrl = data.logo; parent.$('#sitelogo-img').attr('src', imageUrl); } if (data.name){ parent.$('#sitelogo-link').attr('title', data.name); parent.$('#sitelogo-img').attr('alt', data.name); } parent.$$.alerts.info("%s"); </script> """ % (json.dumps(orgDetails), _("Company details updated")) request.write(response)
def saveAvatarItem(entityId, orgId, data, isLogo=False): imageFormat = _getImageFileFormat(data) if imageFormat not in constants.SUPPORTED_IMAGE_TYPES: raise errors.InvalidFileFormat("The image format is not supported") try: original = PythonMagick.Blob(data) image = PythonMagick.Image(original) except Exception as e: raise errors.InvalidFileFormat("Invalid image format") medium = PythonMagick.Blob() small = PythonMagick.Blob() large = PythonMagick.Blob() largesize = constants.LOGO_SIZE_LARGE if isLogo else constants.AVATAR_SIZE_LARGE mediumsize = constants.LOGO_SIZE_MEDIUM if isLogo else constants.AVATAR_SIZE_MEDIUM smallsize = constants.LOGO_SIZE_SMALL if isLogo else constants.AVATAR_SIZE_SMALL image.scale(largesize) image.write(large) image.scale(mediumsize) image.write(medium) image.scale(smallsize) image.write(small) itemId = utils.getUniqueKey() acl = pickle.dumps({"accept":{"orgs":[orgId]}}) item = { "meta": {"owner": entityId, "acl": acl, "type": "image"}, "avatar": { "format": imageFormat, "small": small.data, "medium": medium.data, "large": large.data, "original": original.data }} yield db.batch_insert(itemId, "items", item) #delete older image if any; yield deleteAvatarItem(entityId, isLogo) defer.returnValue("%s:%s" % (imageFormat, itemId))
def _receiveUserAccess(self, request): authinfo = request.getSession(IAuthInfo) myId = authinfo.username myOrgId = authinfo.organization allow = utils.getRequestArg(request, 'allow') == "true" state = utils.getRequestArg(request, 'state') scopes = utils.getRequestArg(request, 'scope') clientId = utils.getRequestArg(request, 'client_id') redirectUri = utils.getRequestArg(request, 'redirect_uri', sanitize=False) signature = utils.getRequestArg(request, 'signature') # Check if signature is valid message = "%s:%s:%s:%s:%s" % \ (myId, clientId, scopes, redirectUri, state) checksum = hmac.new(myOrgId, message, hashlib.sha256) if signature != checksum.hexdigest(): self._error(request, self.SIGNATURE_MISMATCH) return client = yield db.get_slice(clientId, "apps") client = utils.supercolumnsToDict(client) if not client: self._error(request, self.CLIENT_GONE) return if allow: # Authcode must expire shortly after it is issued # We expire the authcode in 5 minutes? authCode = utils.getRandomKey() authMap = {"user_id": myId, "org_id": myOrgId, "client_id": clientId, "redirect_uri": b64encode(redirectUri), "scope": scopes, "type": "auth"} yield db.batch_insert(authCode, "oAuthData", authMap, ttl=120) yield db.insert(myId, "entities", authCode, clientId, "apps", ttl=120) self._redirectOnSuccess(request, redirectUri, authCode, state) else: self._redirectOnError(request, redirectUri, "access_denied", state)
def _tokenForClientCredentials(self, request): clientId = utils.getRequestArg(request, 'client_id') clientSecret = utils.getRequestArg(request, 'client_secret') client = yield db.get_slice(clientId, "apps") client = utils.supercolumnsToDict(client) if not client or not utils.checkpass(clientSecret, client['meta']['secret']): self._error(request, "invalid_client") return # The client is valid. Issue auth token. # We don't issue a refresh token and everytime the client will have # to authenticate using it's credentials scopes = client["meta"]["scope"].split(' ') userId = client["meta"]["author"] orgId = client["meta"]["org"] accessToken = utils.getRandomKey() accessTokenData = {"user_id": userId, "type": "access", "org_id": orgId, "client_id": clientId, "scope": " ".join(scopes)} yield db.batch_insert(accessToken, "oAuthData", accessTokenData, ttl=self._accessTokenExpiry) self._success(request, accessToken)
def _ensureTag(tagName, myId, orgId, presetTag=False): try: tagName = tagName.lower() c = yield db.get(orgId, "orgTagsByName", tagName) tagId = c.column.value c = yield db.get_slice(orgId, "orgTags", super_column=tagId) tag = utils.columnsToDict(c) if presetTag and not tag.get('isPreset', '') == 'True': yield db.insert(orgId, "orgPresetTags", tagId, tagName) yield db.insert(orgId, "orgTags", 'True', 'isPreset', tagId) tag['isPreset'] = 'True' except ttypes.NotFoundException: tagId = utils.getUniqueKey() tag = {"title": tagName, 'createdBy': myId} if presetTag: tag['isPreset'] = 'True' tagName = tagName.lower() yield db.batch_insert(orgId, "orgTags", {tagId: tag}) yield db.insert(orgId, "orgTagsByName", tagId, tagName) if presetTag: yield db.insert(orgId, "orgPresetTags", tagId, tagName) defer.returnValue((tagId, tag))
def save(self): yield db.batch_insert(self.id, 'entities', self._data)
def _reply(self, request): """Commit a new message in reply to an existing conversation. Creates a new message, uploads any attachments, updates the conversation meta info and finally renders the message for the user. Keyword Arguments: convId: conversation id to which this user is replying to. body: The content of the reply. CF Changes: mConversations mConvMessages attachmentVersions """ (appchange, script, args, myId) = yield self._getBasicArgs(request) landing = not self._ajax myOrgId = args['orgId'] convId = utils.getRequestArg(request, 'id') recipients, body, subject, convId = self._parseComposerArgs(request) epoch = int(time.time()) if not convId: raise errors.MissingParams([]) cols = yield db.get_slice(convId, "mConversations", ['meta', 'participants']) cols = utils.supercolumnsToDict(cols) subject = cols['meta'].get('subject', None) participants = cols.get('participants', {}).keys() if not cols: raise errors.InvalidMessage(convId) if myId not in participants: raise errors.MessageAccessDenied(convId) timeUUID = uuid.uuid1().bytes snippet = self._fetchSnippet(body) meta = {'uuid': timeUUID, 'date_epoch': str(epoch), "snippet": snippet} attachments = yield self._handleAttachments(request) attach_meta = self._formatAttachMeta(attachments) messageId = yield self._newMessage(myId, timeUUID, body, epoch) yield self._deliverMessage(convId, participants, timeUUID, myId) yield db.insert(convId, "mConvMessages", messageId, timeUUID) yield db.batch_insert(convId, "mConversations", {'meta': meta, 'attachments': attach_meta}) # Currently, we don't support searching for private messages # self._indexMessage(convId, messageId, myOrgId, meta, attachments, body) #XXX:We currently only fetch the message we inserted. Later we may fetch # all messages delivered since we last rendered the conversation cols = yield db.get_slice(convId, "mConversations") conv = utils.supercolumnsToDict(cols) participants = set(conv['participants']) mids = [messageId] messages = yield db.multiget_slice(mids, "messages", ["meta"]) messages = utils.multiSuperColumnsToDict(messages) participants.update([messages[mid]['meta']['owner'] for mid in messages]) people = base.EntitySet(participants) yield people.fetchData() value = myId data = {"entities": people} data["entities"].update({args['orgId']: args["org"]}) data["orgId"] = args["orgId"] data["convId"] = convId data["message"] = body data["subject"] = subject data["_fromName"] = people[value].basic['name'] users = participants - set([myId]) if users: yield notifications.notify(users, ":MR", value, timeUUID, **data) args.update({"people": people}) args.update({"messageIds": mids}) args.update({'messages': messages}) if script: onload = """ $('.conversation-reply').attr('value', ''); $('#msgreply-attach-uploaded').empty(); """ t.renderScriptBlock(request, "message.mako", "render_conversation_messages", landing, ".conversation-messages-wrapper", "append", True, handlers={"onload": onload}, **args) #Update the right side bar with any attachments the user uploaded args.update({"conv": conv}) people = base.EntitySet(set(conv['participants'])) yield people.fetchData() args.update({"people": people}) args.update({"conv": conv}) args.update({"id": convId}) args.update({"view": "message"}) if script: onload = """ $('#conversation_add_member').autocomplete({ source: '/auto/users', minLength: 2, select: function( event, ui ) { $('#conversation_recipients').attr('value', ui.item.uid) } }); """ t.renderScriptBlock(request, "message.mako", "right", landing, ".right-contents", "set", True, handlers={"onload": onload}, **args) else: request.redirect('/messages') request.finish()
def new(request, authInfo, convType, richText=False): if convType not in plugins: raise errors.BaseError('Unsupported item type', 400) myId = authInfo.username orgId = authInfo.organization entities = base.EntitySet([myId, orgId]) yield entities.fetchData(['basic', 'admins']) plugin = plugins[convType] convId = utils.getUniqueKey() conv = yield plugin.create(request, entities[myId], convId, richText) orgAdminIds = entities[orgId].admins.keys() if orgAdminIds: text = '' monitoredFields = getattr(plugin, 'monitoredFields', {}) for superColumnName in monitoredFields: for columnName in monitoredFields[superColumnName]: if columnName in conv[superColumnName]: text = " ".join([text, conv[superColumnName][columnName]]) matchedKeywords = yield utils.watchForKeywords(orgId, text) if matchedKeywords: reviewOK = utils.getRequestArg(request, "_review") == "1" if reviewOK: # Add conv to list of items that matched this keyword # and notify the administrators about it. orgAdmins = base.EntitySet(orgAdminIds) yield orgAdmins.fetchData() entities.update(orgAdmins) for keyword in matchedKeywords: yield db.insert(orgId + ":" + keyword, "keywordItems", convId, conv['meta']['uuid']) yield notifications.notify(orgAdminIds, ':KW:' + keyword, myId, entities=entities) else: # This item contains a few keywords that are being monitored # by the admin and cannot be posted unless reviewOK is set. defer.returnValue((None, None, matchedKeywords)) # # Save the new item to database and index it. # yield db.batch_insert(convId, "items", conv) yield files.pushfileinfo(myId, orgId, convId, conv) search.solr.updateItemIndex(convId, conv, orgId) # # Push item to feeds and userItems # timeUUID = conv["meta"]["uuid"] convACL = conv["meta"]["acl"] deferreds = [] responseType = 'I' # Push to feeds feedUpdateVal = "I:%s:%s" % (myId, convId) d = Feed.push(myId, orgId, convId, conv, timeUUID, feedUpdateVal, promoteActor=True) deferreds.append(d) # Save in user items. userItemValue = ":".join([responseType, convId, convId, convType, myId, '']) d = db.insert(myId, "userItems", userItemValue, timeUUID) deferreds.append(d) if plugins[convType].hasIndex: d = db.insert(myId, "userItems_%s" % (convType), userItemValue, timeUUID) deferreds.append(d) yield defer.DeferredList(deferreds) defer.returnValue((convId, conv, None))
def removeUser(request, userId, orgAdminId, user=None, orgAdminInfo=None): import base if not user: user = base.Entity(userId) yield user.fetchData() if not orgAdminInfo: orgAdmin = base.Entity(orgAdminId) yield orgAdmin.fetchData() emailId = user.basic.get("emailId", None) displayName = user.basic.get("name", None) firstname = user.basic.get("firstname", None) lastname = user.basic.get("lastname", None) orgId = user.basic["org"] org = base.Entity(orgId) yield org.fetchData() cols = yield db.get_slice(userId, "entities", ["apikeys", "apps"]) apps_apiKeys = supercolumnsToDict(cols) apiKeys = apps_apiKeys.get("apikeys", {}) apps = apps_apiKeys.get("apps", {}) for clientId in apiKeys: yield db.remove(clientId, "apps") yield db.remove(userId, "entities", super_column="apikeys") for clientId in apps: yield db.remove(apps[clientId], "oAuthData") cols = yield db.get_slice(userId, "appsByOwner") cols = columnsToDict(cols) for clientId in cols: yield db.remove(orgId, "appsByOwner", clientId) yield db.remove(userId, "appsByOwner") yield db.remove(userId, "entities", super_column="apps") sessionIds = yield db.get_slice(userId, "userSessionsMap") sessionIds = columnsToDict(sessionIds) for sessionId in sessionIds: yield db.remove(sessionId, "sessions") yield cleanupChat(sessionId, userId, orgId) yield db.remove(userId, "userSessionsMap") groups = yield db.get_slice(userId, "entityGroupsMap") groupIds = [x.column.name.split(":")[1] for x in groups] groupAdmins = yield db.multiget_slice(groupIds, "entities", ["admins"]) groupAdmins = multiSuperColumnsToDict(groupAdmins) for group in groups: name, groupId = group.column.name.split(":") yield db.remove(groupId, "followers", userId) yield db.remove(groupId, "groupMembers", userId) if len(groupAdmins[groupId].get("admins", {})) == 1 and userId in groupAdmins[groupId]["admins"]: yield db.insert(groupId, "entities", "", orgAdminId, "admins") cols = yield db.get_slice(groupId, "groupMembers", [orgAdminId]) if not cols: itemId = getUniqueKey() acl = {"accept": {"groups": [groupId]}} yield db.insert(orgAdminId, "entityGroupsMap", "", group.column.name) yield db.insert(groupId, "groupMembers", itemId, orgAdminId) # only group members can post to a group so, item should be # created only after adding orgAdmin to the group. item = yield createNewItem(request, "activity", orgAdmin, acl, "groupJoin") item["meta"]["target"] = groupId yield db.batch_insert(itemId, "items", item) yield db.insert(groupId, "followers", "", orgAdminId) yield db.insert(orgAdminId, "entities", name, groupId, "adminOfGroups") yield updateDisplayNameIndex(orgAdminId, [groupId], org.basic["name"], None) # TODO: push to group-feed # XXX: call Group.addMember ? yield db.remove(groupId, "entities", userId, "admins") yield updateDisplayNameIndex(userId, groupIds, None, displayName) yield db.remove(userId, "entityGroupsMap") yield db.remove(userId, "entities", super_column="adminOfGroups") yield db.remove(emailId, "userAuth") yield db.remove(orgId, "orgUsers", userId) yield db.remove(orgId, "blockedUsers", userId) yield db.insert(userId, "entities", "", "deleted", "basic") yield db.insert(orgId, "deletedUsers", "", userId) yield updateDisplayNameIndex(userId, [orgId], None, displayName) yield updateNameIndex(userId, [orgId], None, displayName) yield updateNameIndex(userId, [orgId], None, emailId) if firstname: yield updateNameIndex(userId, [orgId], None, firstname) if lastname: yield updateNameIndex(userId, [orgId], None, lastname)
def _deliverMessage(self, convId, recipients, timeUUID, owner): """To each participant in a conversation, add the conversation to the list of unread conversations. CF Changes: mConversations mConvFolders messages mAllConversations mDeletedConversations mArchivedConversations latest """ convFolderMap = {} userFolderMap = {} toNotify = {} toRemove = {'latest': []} conv = yield db.get_slice(convId, "mConversations", ['meta']) conv = utils.supercolumnsToDict(conv) oldTimeUUID = conv['meta']['uuid'] unread = "u:%s" % (convId) read = "r:%s" % (convId) cols = yield db.get_slice(convId, 'mConvFolders', recipients) cols = utils.supercolumnsToDict(cols) for recipient in recipients: deliverToInbox = True # for a new message, mConvFolders will be empty # so recipient may not necessarily be present in cols if recipient != owner: toNotify[recipient] = {'latest': {'messages': {timeUUID: convId}}} toRemove['latest'].append(recipient) for folder in cols.get(recipient, []): cf = self._folders[folder] if folder in self._folders else folder yield db.remove(recipient, cf, oldTimeUUID) if cf == 'mDeletedConversations': #don't add to recipient's inbox if the conv is deleted. deliverToInbox = False else: yield db.remove(convId, 'mConvFolders', folder, recipient) if deliverToInbox: val = unread if recipient != owner else read convFolderMap[recipient] = {'mAllConversations': {timeUUID: val}} userFolderMap[recipient] = {'mAllConversations': ''} if recipient != owner: convFolderMap[recipient]['mUnreadConversations'] = {timeUUID: unread} userFolderMap[recipient]['mUnreadConversations'] = '' else: val = unread if recipient != owner else read convFolderMap[recipient] = {'mDeletedConversations': {timeUUID: val}} yield db.batch_mutate(convFolderMap) yield db.batch_insert(convId, "mConvFolders", userFolderMap) if toRemove['latest'] and oldTimeUUID != timeUUID: yield db.batch_remove(toRemove, names=[oldTimeUUID], supercolumn="messages") if toNotify: yield db.batch_mutate(toNotify)
def postFeedback(self, request): """creates a feedback item with feedback, feedback-{mood} tags. Push item to feeback, feedback-{mood} tag followers. Note: Item is owned by feedback-domain/synovel.com, not user sending the feedback. Only users of feedback-domain/synovel.com can access the item. """ comment = utils.getRequestArg(request, 'comment') mood = utils.getRequestArg(request, 'mood') if not mood or not comment: raise errors.MissingParams([_("Feedback")]) authInfo = request.getSession(IAuthInfo) myId = authInfo.username orgId = authInfo.organization tagName = 'feedback' moodTagName = 'feedback-' + mood feedbackDomain = config.get('Feedback', 'Domain') or 'synovel.com' cols = yield db.get_slice(feedbackDomain, 'domainOrgMap') if not cols: raise errors.ConfigurationError("feedbackDomain is invalid!") # Only one org exists per domain synovelOrgId = cols[0].column.name tagId, tag = yield tags.ensureTag(request, tagName, synovelOrgId) moodTagId, moodTag = yield tags.ensureTag(request, moodTagName, synovelOrgId) # Anyone in synovel can receive feedback. acl = {'accept': {'orgs': [synovelOrgId]}} acl = json.dumps(acl) synovelOrg = base.Entity(synovelOrgId) yield synovelOrg.fetchData() # createNewItem expects an entity object with has org in basic info. # organizations wont have 'org' set. synovelOrg.basic['org'] = synovelOrgId item = yield utils.createNewItem(request, 'feedback', synovelOrg, acl, subType=mood) item['meta']['org'] = synovelOrgId item['meta']['userId'] = myId item['meta']['userOrgId'] = orgId item['meta']['comment'] = comment item['tags'] = {tagId: synovelOrgId, moodTagId: synovelOrgId} itemId = utils.getUniqueKey() tagItemCount = int(tag['itemsCount']) moodTagItemCount = int(moodTag['itemsCount']) if tagItemCount % 10 == 7: tagItemCount = yield db.get_count(tagId, "tagItems") if moodTagItemCount % 10 == 7: moodTagItemCount = yield db.get_count(moodTagId, "tagItems") tagItemCount += 1 moodTagItemCount += 1 # Finally save the feedback yield db.batch_insert(itemId, "items", item) yield db.insert(tagId, "tagItems", itemId, item["meta"]["uuid"]) yield db.insert(moodTagId, "tagItems", itemId, item["meta"]["uuid"]) yield db.insert(synovelOrgId, "orgTags", str(tagItemCount), "itemsCount", tagId) yield db.insert(synovelOrgId, "orgTags", str(moodTagItemCount), "itemsCount", moodTagId) cols = yield db.multiget_slice([tagId, moodTagId], "tagFollowers") followers = utils.multiColumnsToDict(cols) followers = set(followers[tagId].keys() + followers[moodTagId].keys()) value = {"feed": {item['meta']['uuid']: itemId}} muts = dict([(x, value) for x in followers]) if muts: yield db.batch_mutate(muts)
def _tokenForAuthCode(self, request, refresh=False): clientId = utils.getRequestArg(request, 'client_id') clientSecret = utils.getRequestArg(request, 'client_secret') redirectUri = utils.getRequestArg(request, 'redirect_uri', sanitize=False) scopes = utils.getRequestArg(request, 'scope') if refresh: authCode = utils.getRequestArg(request, 'refresh_token') else: authCode = utils.getRequestArg(request, 'code') # XXX: We should be checking for HTTP authentication before # throwing an error in case of missing clientId and clientSecret. if not all([redirectUri, clientId, clientSecret, authCode]): self._error(request, "invalid_request") return grant = yield db.get_slice(authCode, "oAuthData") grant = utils.columnsToDict(grant) if not grant or grant['client_id'] != clientId or\ grant['redirect_uri'] != b64encode(redirectUri) or\ not (grant['type'] == 'auth' and not refresh or\ grant['type'] == 'refresh' and refresh): self._error(request, "invalid_grant") return grantedScopes = grant['scope'].split(' ') if scopes: scopes = scopes.split(' ') if [x for x in scopes if x not in grantedScopes]: self._error(request, "invalid_scope") return else: scopes = grantedScopes client = yield db.get_slice(clientId, "apps") client = utils.supercolumnsToDict(client) if not client or not utils.checkpass(clientSecret, client['meta']['secret']): self._error(request, "invalid_client") return userId = grant["user_id"] orgId = grant["org_id"] accessToken = utils.getRandomKey() accessTokenData = {"user_id": userId, "org_id": orgId, "type": "access", "client_id": clientId, "auth_code": authCode, "scope": " ".join(scopes)} yield db.batch_insert(accessToken, "oAuthData", accessTokenData, ttl=self._accessTokenExpiry) refreshToken = utils.getRandomKey() refreshTokenData = {"user_id": userId, "org_id": orgId, "type": "refresh", "client_id": clientId, "redirect_uri": grant["redirect_uri"], "auth_code": authCode, "scope": grant["scope"]} yield db.batch_insert(refreshToken, "oAuthData", refreshTokenData, ttl=self._refreshTokenExpiry) yield db.insert(userId, "entities", refreshToken, clientId, "apps", ttl=self._refreshTokenExpiry) yield db.remove(authCode, "oAuthData") self._success(request, accessToken, refreshToken)
def _comment(convId, conv, comment, snippet, myId, orgId, richText, reviewed, fids=None): convType = conv["meta"].get("type", "status") # 1. Create the new item timeUUID = uuid.uuid1().bytes meta = {"owner": myId, "parent": convId, "comment": comment, "timestamp": str(int(time.time())), "org": orgId, "uuid": timeUUID, "richText": str(richText)} item = {'meta':meta} followers = {myId: ''} itemId = utils.getUniqueKey() if snippet: meta['snippet'] = snippet # 1.5. Check if the comment matches any of the keywords entities = base.EntitySet([myId, orgId]) yield entities.fetchData(['basic', 'admins']) orgAdmins = entities[orgId].admins.keys() if orgAdmins: matchedKeywords = yield utils.watchForKeywords(orgId, comment) if matchedKeywords: if reviewed: # Add item to list of items that matched this keyword # and notify the administrators about it. for keyword in matchedKeywords: yield db.insert(orgId + ":" + keyword, "keywordItems", itemId + ":" + convId, timeUUID) yield notifications.notify(orgAdmins, ':KW:' + keyword, myId, entities=entities) else: # This item contains a few keywords that are being monitored # by the admin and cannot be posted unless reviewOK is set. defer.returnValue((None, convId, {convId: conv}, matchedKeywords)) # 1.9. Actually store the item if fids: attachments = yield utils._upload_files(myId, fids) if attachments: item['attachments'] = {} for attachmentId in attachments: fileId, name, size, ftype = attachments[attachmentId] item["attachments"][attachmentId] = "%s:%s:%s" % (name, size, ftype) yield db.batch_insert(itemId, "items", item) yield files.pushfileinfo(myId, orgId, itemId, item, conv) # 2. Update response count and add myself to the followers of conv convOwnerId = conv["meta"]["owner"] convType = conv["meta"]["type"] responseCount = int(conv["meta"].get("responseCount", "0")) if responseCount % 5 == 3: responseCount = yield db.get_count(convId, "itemResponses") responseCount += 1 conv['meta']['responseCount'] = responseCount convUpdates = {"responseCount": str(responseCount)} yield db.batch_insert(convId, "items", {"meta": convUpdates, "followers": followers}) # 3. Add item as response to parent yield db.insert(convId, "itemResponses", "%s:%s" % (myId, itemId), timeUUID) # 4. Update userItems and userItems_* responseType = "Q" if convType == "question" else 'C' commentSnippet = utils.toSnippet(comment, 35, richText) userItemValue = ":".join([responseType, itemId, convId, convType, convOwnerId, commentSnippet]) yield db.insert(myId, "userItems", userItemValue, timeUUID) if convType in plugins and plugins[convType].hasIndex: yield db.insert(myId, "userItems_" + convType, userItemValue, timeUUID) # 5. Update my feed. feedItemVal = "%s:%s:%s" % (responseType, myId, itemId) yield Feed.push(myId, orgId, convId, conv, timeUUID, feedItemVal) yield _notify("C", convId, timeUUID, convType=convType, convOwnerId=convOwnerId, myId=myId, me=entities[myId], comment=comment, richText=richText) search.solr.updateItemIndex(itemId, {'meta': meta}, orgId, conv=conv) items = {itemId: item, convId: conv} defer.returnValue((itemId, convId, items, None))
def _addUser(self, request): emailId = utils.getRequestArg(request, 'email') existingUser = db.get_count(emailId, "userAuth") localpart, domain = emailId.split("@") displayName = utils.getRequestArg(request, 'name') jobTitle = utils.getRequestArg(request, 'jobTitle') timezone = utils.getRequestArg(request, 'timezone') passwd = utils.getRequestArg(request, 'password', sanitize=False) pwdrepeat = utils.getRequestArg(request, 'pwdrepeat', sanitize=False) if not displayName or not jobTitle or not timezone or not passwd: raise errors.MissingParams([_("All fields are required to create the user")]) if passwd != pwdrepeat: raise PasswordsNoMatch() args = {'emailId': emailId, 'view': 'invite'} existingUser = yield existingUser if not existingUser: authinfo = yield defer.maybeDeferred(request.getSession, IAuthInfo) orgId = yield getOrgId(domain) if not orgId: orgId = utils.getUniqueKey() domains = {domain: ''} basic = {"name": domain, "type": "org"} yield db.batch_insert(orgId, "entities", {"basic": basic, "domains": domains}) yield db.insert(domain, "domainOrgMap", '', orgId) userId = yield utils.addUser(emailId, displayName, passwd, orgId, jobTitle, timezone) authinfo.username = userId authinfo.organization = orgId authinfo.isAdmin = False yield request._saveSessionToDB() cols = yield db.get_slice(domain, "invitations", [emailId]) cols = utils.supercolumnsToDict(cols) userIds = cols.get(emailId, {}).values() if userIds: db.batch_remove({'invitationsSent': userIds}, names=[emailId]) yield db.remove(domain, "invitations", super_column=emailId) t.render(request, "signup.mako", **args) # Notify all invitees about this user. token = utils.getRequestArg(request, "token") acceptedInvitationSender = cols.get(emailId, {}).get(token) otherInvitees = [x for x in userIds if x not in (acceptedInvitationSender, emailId)] entities = base.EntitySet(userIds + [orgId, userId]) yield entities.fetchData() data = {"entities": entities, 'orgId': orgId} yield notifications.notify([acceptedInvitationSender], ":IA", userId, **data) yield notifications.notify(otherInvitees, ":NU", userId, **data) else: raise InvalidRegistration("A user with this e-mail already exists! Already registered?")
def updateData(): yield db.truncate('user_files') try: yield db.get('asdf', 'entityFeed_files', uuid.uuid1().bytes) except ttypes.InvalidRequestException as exception: log.msg(exception) raise Exception('entityFeed_files CF missing, create the CF') except ttypes.NotFoundException: pass entities = {} items = {} rows = yield db.get_range_slice('items', count=10000, reverse=True) for row in rows: itemId = row.key item = utils.supercolumnsToDict(row.columns) items[itemId]=item for itemId in items: item = items[itemId] log.msg(itemId) if 'meta' not in item: continue # Add org to all items try: owner = item['meta']['owner'] col = yield db.get(owner, "entities", 'org', 'basic') ownerOrgId = col.column.value yield db.insert(itemId, 'items', ownerOrgId, 'org', 'meta') except Exception as e: if item['meta'].get('type', '') == 'feedback': yield db.insert(itemId, 'items', owner, 'org', 'meta') # Fix ACLs if 'parent' not in item['meta']: acl = item['meta']['acl'] convOwner = item['meta']['owner'] convId = itemId if acl == 'company': col = yield db.get(convOwner, "entities", "org", "basic") ownerOrgId = col.column.value acl = pickle.dumps({"accept":{"orgs":[ownerOrgId]}}) yield db.insert(convId, 'items', acl, 'acl', 'meta') else: try: acl = pickle.loads(acl) if 'accept' in acl and 'friends' in acl['accept'] and isinstance(acl['accept']['friends'], bool): del acl['accept']['friends'] acl = pickle.dumps(acl) yield db.insert(convId, 'items', acl, 'acl', 'meta') except : log.msg('cannot unpack acl', acl) # Migrate files # truncate user_files # update user_files and entityFeed_files if 'owner' in item['meta'] and 'attachments' in item: ownerId = item['meta']['owner'] if ownerId not in entities: cols = yield db.get_slice(ownerId, 'entities', ['basic']) entities.update({ownerId: utils.supercolumnsToDict(cols)}) for attachmentId in item['attachments']: orgId = entities[ownerId]['basic']['org'] timeuuid, name = item['attachments'][attachmentId].split(':')[:2] timeuuid = utils.decodeKey(timeuuid) val = '%s:%s:%s:%s' % (attachmentId, name, itemId, ownerId) yield db.insert(ownerId, "user_files", val, timeuuid) if 'parent' not in item['meta'] and item['meta'].get('acl', ''): _entities = yield utils.expandAcl(ownerId, orgId, item['meta']['acl'], itemId, ownerId, True) for entityId in _entities: yield db.insert(entityId, "entityFeed_files", val, timeuuid) # Migrate items # Meta fields in "link", "event" and "poll" if item['meta'].get('type', None) in ['link', 'poll', 'event']: itemMeta = item['meta'] itemType = itemMeta['type'] updated = {} if itemType == "link": if 'url' in itemMeta: updated['link_url'] = itemMeta['url'] if 'title' in itemMeta: updated['link_title'] = itemMeta['title'] if 'summary' in itemMeta: updated['link_summary'] = itemMeta['summary'] if 'imgSrc' in itemMeta: updated['link_imgSrc'] = itemMeta['imgSrc'] if 'embedType' in itemMeta: updated['link_embedType'] = itemMeta['embedType'] if 'embedSrc' in itemMeta: updated['link_embedSrc'] = itemMeta['embedSrc'] if 'embedHeight' in itemMeta: updated['link_embedHeight'] = itemMeta['embedHeight'] if 'embedWidth' in itemMeta: updated['link_embedWidth'] = itemMeta['embedWidth'] elif itemType == 'poll': if 'question' in itemMeta: updated['comment'] = itemMeta['question'] else: print 'Found an event:', itemId if updated: yield db.batch_insert(itemId, 'items', {'meta': updated}) # # Create poll indexes for feed and userItems # rows = yield db.get_range_slice('entities', count=10000, reverse=True) mutations = {} for row in rows: entityId = row.key entity = utils.supercolumnsToDict(row.columns) if entity['basic']['type'] != 'user': continue d1 = db.get_slice(entityId, 'feed', count=10000) d2 = db.get_slice(entityId, 'userItems', count=10000) results = yield d1 for col in results: value = col.column.value if value in items: if items.get(value, {}).get('meta', {}).get('type', '') == 'poll': mutations.setdefault(entityId, {}).setdefault('feed_poll', {}).update({col.column.name: value}) results = yield d2 for col in results: value = col.column.value responseType, itemId, convId, convType, others = value.split(':', 4) if convType == 'poll': mutations.setdefault(entityId, {}).setdefault('userItems_poll', {}).update({col.column.name: value}) yield db.batch_mutate(mutations) #Group type changed from public-private to open-closed. rows = yield db.get_range_slice('entityGroupsMap', count=1000) groupIds = set() for row in rows: for col in row.columns: name_, groupId = col.column.name.split(':') groupIds.add(groupId) cols = yield db.multiget_slice(groupIds, "entities") groups = utils.multiSuperColumnsToDict(cols) for groupId in groups: access = groups[groupId]['basic']['access'].lower() if access == 'public': yield db.insert(groupId, 'entities', 'open', 'access', 'basic') elif access.lower() == 'private': yield db.insert(groupId, 'entities', 'closed', 'access', 'basic') #Fix entityGroupsMap rows = yield db.get_range_slice('entityGroupsMap', count=1000) for row in rows: entityId = row.key for col in row.columns: name_, groupId = col.column.name.split(':') if col.column.name != '%s:%s'%(groups[groupId]['basic']['name'].lower(), groupId): yield db.remove(entityId, 'entityGroupsMap', col.column.name) yield db.insert(entityId, 'entityGroupsMap', '', '%s:%s' %(groups[groupId]['basic']['name'].lower(), groupId))
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();")