def _S3FormData(self, request): (appchange, script, args, myId) = yield self._getBasicArgs(request) landing = not self._ajax myOrgId = args["orgId"] SKey = config.get('CloudFiles', 'SecretKey') AKey = config.get('CloudFiles', 'AccessKey') domain = config.get('CloudFiles', 'Domain') bucket = config.get('CloudFiles', 'Bucket') if domain == "": calling_format = SubdomainCallingFormat() domain = "s3.amazonaws.com" else: calling_format = VHostCallingFormat() conn = S3Connection(AKey, SKey, host=domain, is_secure=True, calling_format=calling_format) filename = utils.getRequestArg(request, "name") or None #TODO:If name is None raise an exception mime = utils.getRequestArg(request, "mime") or None if mime: if not mimetypes.guess_extension(mime): mime = mimetypes.guess_type(filename)[0] else: mime = mimetypes.guess_type(filename)[0] if not mime: mime = "text/plain" filename = urlsafe_b64encode(filename) fileId = utils.getUniqueKey() key = '%s/%s/%s' % (myOrgId, myId, fileId) attachment_filename = 'attachment;filename=\"%s\"' % (filename) x_conds = ['{"x-amz-meta-uid":"%s"}' % myId, '{"x-amz-meta-filename":"%s"}' % filename, '{"x-amz-meta-fileId":"%s"}' % fileId, '{"content-type":"%s"}' % mime] x_fields = [{"name":"x-amz-meta-uid", "value":"%s" % myId}, {"name":"x-amz-meta-filename", "value":"%s" % filename}, {"name":"content-type", "value":"%s" % mime}, {"name":"x-amz-meta-fileId", "value":"%s" % fileId}] max_content_length = constants.MAX_FILE_SIZE x_conds.append('["content-length-range", 0, %i]' % max_content_length) redirect_url = config.get('General', 'URL') + "/files/update" form_data = conn.build_post_form_args(bucket, key, http_method="https", fields=x_fields, conditions=x_conds, success_action_redirect=redirect_url) request.write(json.dumps([form_data])) defer.returnValue(0)
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 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 _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 _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 create(request, me, name, access, description, displayPic): """create a new group. add creator to the group members. make create administrator of the group. Note: No two groups in an organization should have same name. Keyword params: @request: @me: @name: name of the group. @access: group access type (open/closed). @description: description of the group. @displayPic: profile pic of the group. """ if not name: raise errors.MissingParams([_("Group name")]) cols = yield db.get_slice(me.basic['org'], "entityGroupsMap", start=name.lower(), count=2) for col in cols: if col.column.name.split(':')[0] == name.lower(): raise errors.InvalidGroupName(name) groupId = utils.getUniqueKey() group = base.Entity(groupId) meta = {"name": name, "type": "group", "access": access, "org": me.basic['org']} admins = {me.id: ''} if description: meta["desc"] = description if displayPic: avatar = yield saveAvatarItem(group.id, me.basic['org'], displayPic) meta["avatar"] = avatar group.update({'basic': meta, 'admins': admins}) yield group.save() colname = _entityGroupMapColName(group) yield db.insert(me.id, "entities", name, group.id, 'adminOfGroups') yield db.insert(me.basic['org'], "entityGroupsMap", '', colname) yield _addMember(request, group, me)
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 _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 addSampleData(client): # # Organization Name: # Example Software Inc. # Users: # Kevin King (CEO) # Ashok Ajax (HR Manager) # William Wiki (Administrator) # John Doe (Programmer) # Paul Foobar (Programmer) # # The organization exampleKey = utils.getUniqueKey() # List of users in the organization kevinKey = utils.getUniqueKey() williamKey = utils.getUniqueKey() ashokKey = utils.getUniqueKey() johnKey = utils.getUniqueKey() paulKey = utils.getUniqueKey() adminKey = williamKey # Create the organization yield client.batch_insert(exampleKey, 'entities', { 'basic': { 'name': 'Example Software', 'type': 'org' }, 'domains': { 'example.com': '', 'example.org': '' }, 'admins': {adminKey: ''}}) # Map domains to organization yield client.insert('example.com', 'domainOrgMap', '', exampleKey) yield client.insert('example.org', 'domainOrgMap', '', exampleKey) # Create groups managementGroupId = utils.getUniqueKey() yield client.batch_insert(managementGroupId, "entities", { "basic": { "name": "Management", "desc": "Group of all executives involved in policy making", "org": exampleKey, "access": "private", "type": "group" }, "admins": { adminKey:''}}) yield client.insert(exampleKey, "entityGroupsMap", '', 'management:%s'%(managementGroupId)) programmersGroupId = utils.getUniqueKey() yield client.batch_insert(programmersGroupId, "entities", { "basic": { "name": "Programmers", "desc": "Group of all programmers", "org": exampleKey, "access": "private", "type": "group" }, "admins": { adminKey:''}}) yield client.insert(exampleKey, "entityGroupsMap", '', 'programmers:%s'%(programmersGroupId)) # Index used to sort users in company user's list yield client.insert(exampleKey, "displayNameIndex", "", "kevin:"+kevinKey) yield client.insert(exampleKey, "displayNameIndex", "", "ashok:"+ashokKey) yield client.insert(exampleKey, "displayNameIndex", "", "paul:"+paulKey) yield client.insert(exampleKey, "displayNameIndex", "", "john:"+johnKey) yield client.insert(exampleKey, "displayNameIndex", "", "william:"+williamKey) # Index used to search for users (mainly in autocomplete widgets) yield client.insert(exampleKey, "nameIndex", "", "kevin:"+kevinKey) yield client.insert(exampleKey, "nameIndex", "", "ashok:"+ashokKey) yield client.insert(exampleKey, "nameIndex", "", "paul:"+paulKey) yield client.insert(exampleKey, "nameIndex", "", "john:"+johnKey) yield client.insert(exampleKey, "nameIndex", "", "william:"+williamKey) yield client.insert(exampleKey, "nameIndex", "", "wiki:"+williamKey) yield client.insert(exampleKey, "nameIndex", "", "king:"+kevinKey) yield client.insert(exampleKey, "nameIndex", "", "foobar:"+paulKey) yield client.insert(exampleKey, "nameIndex", "", "ajax:"+ashokKey) # Add users to organization yield client.batch_insert(exampleKey, 'orgUsers', { kevinKey: '', williamKey: '', ashokKey: '', johnKey: '', paulKey: '' }) # User profiles yield client.batch_insert(kevinKey, 'entities', { 'basic': { 'name': 'Kevin', 'firstname':"Kevin", "lastname": "King", 'jobTitle': 'Chief Executive Officer', 'location': 'San Fransisco', 'org': exampleKey, 'type': "user", 'timezone': 'America/Los_Angeles', 'emailId': "*****@*****.**", }, 'languages': { 'English': 'srw', 'Spanish': 'srw', 'Hindi': 'rw' }, 'schools': { '1996:Hraward Business School': 'Graduation' }, 'companies': { '200710:200304:Example Technology Services': 'Chief Financial Officer' }, 'contact': { 'phone': '+11234567890', 'mobile': '+12234567890' }, 'interests': { "Business Development": "", "Networking": "" }, 'personal': { 'email': '*****@*****.**', 'hometown': 'New York', 'birthday': '19700229', 'sex': 'M' }}) yield client.batch_insert(ashokKey, 'entities', { 'basic': { 'name': 'Ashok', "firstname": "Ashok", "lastname": "Ajax", 'jobTitle': 'HR Manager', 'location': 'San Fransisco', 'timezone': 'America/Los_Angeles', 'org': exampleKey, 'type': "user", "emailId": "*****@*****.**" }, 'expertise': { 'expertise': 'recruiting,hr-policies' }, 'languages': { 'Telugu': 'srw', 'Hindi': 'srw', 'English': 'srw' }, 'schools': { '2003:Acpak School of Management': 'Post Graduation', '1998:Acpak Institute of Technology': 'Graduation' }, 'contact': { 'phone': '+11234567890' }, 'personal': { 'email': '*****@*****.**', 'hometown': 'Guntur, India' }}) yield client.batch_insert(williamKey, 'entities', { 'basic': { 'name': 'William', "firstname": "William", "lastname": "Wiki", 'jobTitle': 'Administrator', 'location': 'San Fransisco', 'org': exampleKey, 'timezone': 'America/Los_Angeles', 'type': "user", "emailId": "*****@*****.**" }, 'languages': { 'English': 'srw', 'German': 'srw' }, 'schools': { '2008:Mocha Frappe Institute of Technology': 'Graduation' }, 'companies': { '201010:200806:JohnDoe Corp': 'Chief Executive Officer' }, 'contact': { 'phone': '+11234567890' }, 'interests': { "Cycling": "sports", "Trekking": "sports" }, 'personal': { 'email': '*****@*****.**', 'hometown': 'Berlin, Germany', 'currentcity': 'San Fransisco' }, 'adminOfGroups':{ managementGroupId:'', programmersGroupId:'' }}) yield client.batch_insert(paulKey, 'entities', { 'basic': { 'name': 'Paul', "firstname": "Paul", "lastname": "Foobar", 'jobTitle': 'Programmer', 'location': 'Hyderabad, India', 'org': exampleKey, 'timezone': 'America/Los_Angeles', 'type': "user", "emailId": "*****@*****.**" }, 'languages': { 'English': 'srw', 'Hindi': 'rw' }, 'schools': { '2004:Green Tea Institute of Technology': 'Graduation' }, 'contact': { 'phone': '+911234567890' }, 'interests': { "Wii": "sports", "Open Source": "technology" }, 'personal': { 'email': '*****@*****.**', 'hometown': 'San Antonio', 'birthday': '19820202', 'sex': 'M' }}) yield client.batch_insert(johnKey, 'entities', { 'basic': { 'name': 'John', 'jobTitle': 'Programmer', 'location': 'Hyderabad, India', 'org': exampleKey, 'timezone': 'America/Los_Angeles', 'type': "user", "emailId": "*****@*****.**" }, 'languages': { 'French': 'srw', 'English': 'srw' }, 'schools': { '2008:Diced Onion Technology University': 'Graduation' }, 'contact': { 'phone': '+911234567890' }, 'interests': { "Wii": "sports", "Open Source": "technology" }, 'personal': { 'email': '*****@*****.**', 'hometown': 'Beechum County, Alabama', 'birthday': '19780215', 'sex': 'M' }}) # User authentication - password set to "example" yield client.batch_insert('*****@*****.**', 'userAuth', { 'passwordHash': '1a79a4d60de6718e8e5b326e338ae533', 'org': exampleKey, 'user': kevinKey }) yield client.batch_insert('*****@*****.**', 'userAuth', { 'passwordHash': '1a79a4d60de6718e8e5b326e338ae533', 'org': exampleKey, 'user': ashokKey }) yield client.batch_insert('*****@*****.**', 'userAuth', { 'passwordHash': '1a79a4d60de6718e8e5b326e338ae533', 'org': exampleKey, 'user': williamKey, 'isAdmin': 'True' }) yield client.batch_insert('*****@*****.**', 'userAuth', { 'passwordHash': '1a79a4d60de6718e8e5b326e338ae533', 'org': exampleKey, 'user': paulKey }) yield client.batch_insert('*****@*****.**', 'userAuth', { 'passwordHash': '1a79a4d60de6718e8e5b326e338ae533', 'org': exampleKey, 'user': johnKey }) # Create activity items and insert into feeds and userItems acl_company = pickle.dumps({"accept":{"orgs": [exampleKey]}}) # Subscriptions yield client.insert(williamKey, "subscriptions", "", kevinKey) yield client.insert(kevinKey, "followers", "", williamKey) # Create activity items and insert subscriptions into feeds and userItems williamFollowingKevinKey = utils.getUniqueKey() timeUUID = uuid.uuid1().bytes timestamp = str(int(time.time())) yield client.batch_insert(williamFollowingKevinKey, "items", { "meta": { "acl": acl_company, "owner": williamKey, "type": "activity", "subType": "following", "timestamp": timestamp, "uuid": timeUUID, "target": kevinKey }}) userItemValue = ":".join(["I", williamFollowingKevinKey, williamFollowingKevinKey, "activity", williamKey, ""]) yield client.insert(williamKey, "userItems", userItemValue, timeUUID) yield client.insert(williamKey, "feed", williamFollowingKevinKey, timeUUID) yield client.insert(williamKey, "feedItems", "I:%s:%s:%s:" % (williamKey, williamFollowingKevinKey, kevinKey), timeUUID, williamFollowingKevinKey)
def _submitReport(self, request, action): (appchange, script, args, myId) = yield self._getBasicArgs(request) landing = not self._ajax snippet, comment = utils.getTextWithSnippet(request, "comment", constants.COMMENT_PREVIEW_LENGTH) orgId = args['orgId'] isNewReport = False timeUUID = uuid.uuid1().bytes convId, conv = yield utils.getValidItemId(request, "id") convMeta = conv["meta"] convOwnerId = convMeta["owner"] convType = convMeta["type"] convACL = convMeta["acl"] toFetchEntities = set([myId, convOwnerId]) if "reportId" in convMeta: reportId = convMeta["reportId"] isNewReport = False toFetchEntities.add(convMeta['reportedBy']) else: isNewReport = True reportId = utils.getUniqueKey() if isNewReport and convOwnerId == myId: raise errors.InvalidRequest(_("You cannot report your own Item. \ Delete the item instead")) toFetchEntities.remove(myId) entities = base.EntitySet(toFetchEntities) yield entities.fetchData() entities.update({myId: args["me"]}) if myId == convOwnerId: if action not in ["accept", "repost"]: raise errors.InvalidRequest(_('Invalid action was performed on the report')) convReport = {"reportStatus": action} yield db.batch_insert(convId, "items", {"meta": convReport}) if action == "accept": # Owner removed the comment. Delete the item from his feed yield Item.deleteItem(convId, myId, orgId) request.write("$$.fetchUri('/feed/');") request.write("$$.alerts.info('%s')" % _("Your item has been deleted")) request.finish() else: # Owner posted a reply, so notify reporter of the same yield Item._notify("RFC", convId, timeUUID, convType=convType, convOwnerId=convOwnerId, myId=myId, entities=entities, me=args["me"], reportedBy=convMeta["reportedBy"]) else: if action not in ["report", "repost", "reject"]: raise errors.InvalidRequest(_('Invalid action was performed on the report')) if isNewReport: # Update Existing Item Information with Report Meta newACL = pickle.dumps({"accept": {"users": [convOwnerId, myId]}}) convReport = {"reportedBy": myId, "reportId": reportId, "reportStatus": "pending", "state": "flagged"} convMeta.update(convReport) yield db.batch_insert(convId, "items", {"meta": convReport}) reportLink = """·<a class="button-link" title="View Report" href="/item/report?id=%s"> View Report</a>""" % convId request.write("""$("#item-footer-%s").append('%s');""" % (convId, reportLink)) yield Item._notify("FC", convId, timeUUID, convType=convType, entities=entities, convOwnerId=convOwnerId, myId=myId, me=args["me"]) else: if action == "repost": # Remove the reportId key, so owner cannot post any comment yield db.batch_remove({'items': [convId]}, names=["reportId", "reportStatus", "reportedBy", "state"], supercolumn='meta') oldReportMeta = {"reportedBy": convMeta["reportedBy"], "reportId": reportId} # Save the now resolved report in items and remove its # reference in the item meta so new reporters wont't see # old reports timestamp = str(int(time.time())) yield db.insert(convId, "items", reportId, timestamp, "reports") yield db.batch_insert(reportId, "items", {"meta": oldReportMeta}) # Notify the owner that the report has been withdrawn yield Item._notify("UFC", convId, timeUUID, convType=convType, convOwnerId=convOwnerId, myId=myId, entities=entities, me=args["me"]) elif action in ["reject", "report"]: # Reporter rejects the comment by the owner or reports the # same item again. convReport = {"reportStatus": "pending"} yield Item._notify("RFC", convId, timeUUID, convType=convType, convOwnerId=convOwnerId, myId=myId, entities=entities, me=args["me"], reportedBy=convMeta["reportedBy"]) yield db.batch_insert(convId, "items", {"meta": convReport}) args.update({"entities": entities, "ownerId": convOwnerId, "convId": convId}) # Update New Report comment Details commentId = utils.getUniqueKey() timeUUID = uuid.uuid1().bytes meta = {"owner": myId, "parent": reportId, "comment": comment, "timestamp": str(int(time.time())), "uuid": timeUUID, "richText": str(False)} if snippet: meta['snippet'] = snippet yield db.batch_insert(commentId, "items", {'meta': meta}) # Update list of comments for this report yield db.insert(reportId, "itemResponses", "%s:%s:%s" % (myId, commentId, action), timeUUID) yield self._renderReportResponses(request, convId, convMeta, args) request.write("$('#report-comment').attr('value', '')")
def _postChat(self, request): comment = utils.getRequestArg(request, 'message') channelId = utils.getRequestArg(request, 'room') if not comment: # Ignore empty comment return authInfo = request.getSession(IAuthInfo) myId = authInfo.username orgId = authInfo.organization timeuuid = uuid.uuid1().bytes recipientId, recipient = yield utils.getValidEntityId(request, 'to') me = base.Entity(myId) yield me.fetchData() myName = me.basic['name'] myAvatar = utils.userAvatar(myId, me, 's') chatId = utils.getUniqueKey() sessionId = request.getCookie('session') try: col = yield db.get(orgId, 'presence', sessionId, myId) except ttypes.NotFoundException: self.setResponseCodeAndWrite(request, 200, {'error': 'You are currently offline'}) return cols = yield db.get_slice(orgId, "presence", super_column=recipientId) recipientStatus = getMostAvailablePresence( utils.columnsToDict(cols).values()) if recipientStatus == PresenceStates.OFFLINE: self.setResponseCodeAndWrite(request, 200, {'error': 'Cannot send message. User is currently offline'}) return message = {"from": myName, "to": recipientId, "message": comment, "timestamp": time.time(), "avatar": myAvatar} data = {"type": "room", "from": myId, "to": recipientId, "message": message} if channelId: channelSubscribers = yield db.get_slice(channelId, 'channelSubscribers') channelSubscribers = utils.columnsToDict(channelSubscribers) channelSubscribers = set([x.split(':', 1)[0] \ for x in channelSubscribers]) if myId not in channelSubscribers: self.setResponseCodeAndWrite(request, 200, {'error': 'Access denied'}) return yield db.insert(channelId, 'channelSubscribers', '', '%s:%s'\ % (myId, sessionId)) yield db.insert("%s:%s" % (myId, sessionId), "sessionChannelsMap", '', channelId) data["room"] = channelId startKey = '%s:' % recipientId cols = yield db.get_slice(channelId, "channelSubscribers", start=startKey, count=1) count = len([col for col in cols \ if col.column.name.startswith(startKey)]) try: yield comet.publish('/chat/%s' % (channelId), message) if not count: yield comet.publish('/notify/%s' % (recipientId), data) except Exception, e: self.setResponseCodeAndWrite(request, 200, {'error': 'The message could not be sent!'}) return
startKey = '%s:' % recipientId cols = yield db.get_slice(channelId, "channelSubscribers", start=startKey, count=1) count = len([col for col in cols \ if col.column.name.startswith(startKey)]) try: yield comet.publish('/chat/%s' % (channelId), message) if not count: yield comet.publish('/notify/%s' % (recipientId), data) except Exception, e: self.setResponseCodeAndWrite(request, 200, {'error': 'The message could not be sent!'}) return else: channelId = utils.getUniqueKey() data['room'] = channelId try: yield comet.publish('/notify/%s' % (myId), data) yield comet.publish('/notify/%s' % (recipientId), data) except Exception, e: self.setResponseCodeAndWrite(request, 200, {'error': 'The message could not be sent!'}) return yield db.insert(channelId, 'channelSubscribers', '', myId) yield db.insert(channelId, 'channelSubscribers', '', recipientId) channelSubscribers = set([myId, recipientId]) start = utils.uuid1(timestamp=time.time() - 3600).bytes cols = yield db.get_slice(myId, 'chatArchiveList', start=start, )
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 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 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 _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))