Example #1
0
def updateAndPublishStatus(userId, orgId, sessionId, status, user=None):
    # Check if there is a change in the online status
    results = yield db.get_slice(orgId, 'presence', super_column=userId)
    results = utils.columnsToDict(results)
    oldPublishedStatus = getMostAvailablePresence(results.values())

    # Update the online status
    if status != 'offline':
        yield db.insert(orgId, 'presence', status, sessionId, userId)
    else:
        yield db.remove(orgId, 'presence', sessionId, userId)

    # If status changed broadcast the change
    # XXX: Currently everyone on the network will get the presence update.
    #      This will not scale well with big networks
    results[sessionId] = status
    newPublishedStatus = getMostAvailablePresence(results.values())

    if oldPublishedStatus != newPublishedStatus:
        if not user:
            user = base.Entity(userId)
            yield user.fetchData()
        data = {"userId": userId, 'status': newPublishedStatus,
                'name': user.basic['name'],
                'title': user.basic['jobTitle'],
                'avatar': utils.userAvatar(userId, user, 's')}
        yield comet.publish('/presence/' + orgId, data)
Example #2
0
    def _getPresence(self, request):
        authInfo = request.getSession(IAuthInfo)
        orgId = authInfo.organization
        myId = authInfo.username
        data = []

        cols = yield db.get_slice(orgId, "presence")
        cols = utils.supercolumnsToDict(cols)
        if myId not in cols:
            myPresence = yield db.get_slice(orgId, "presence", super_column=myId)
            cols[myId] = utils.columnsToDict(myPresence)

        presence = {}
        for userId in cols:
            presence[userId] = getMostAvailablePresence(cols[userId].values())

        if presence[myId] == PresenceStates.OFFLINE:
            request.write(json.dumps(data))
            return

        userIds = cols.keys()
        entities = base.EntitySet(userIds)
        yield entities.fetchData()
        for entityId in entities.keys():
            entity = entities[entityId]
            _data = {"userId": entityId, "name": entity.basic['name'],
                     "status": presence.get(entityId, PresenceStates.OFFLINE),
                     "title": entity.basic["jobTitle"],
                     "avatar": utils.userAvatar(entityId,  entity, 's')}
            data.append(_data)

        request.write(json.dumps(data))
Example #3
0
    def render(self, parts, value, toOwner=False,
               getTitle=True, getBody=True, data=None):
        convId, convType, convOwnerId, notifyType = parts
        if convType == "question":
            templates = self._toOthers_A if not toOwner else self._toOwner_A
        else:
            templates = self._toOthers_C if not toOwner else self._toOwner_C

        title, body, html = '', '', ''
        senderName = data['me'].basic['name']
        convOwnerName = data['entities'][convOwnerId].basic['name']

        if getTitle:
            title = templates[0] % locals()

        if getBody:
            senderAvatarUrl = utils.userAvatar(data['myId'], data['me'], "medium")
            convUrl = "%s/item?id=%s" % (rootUrl, convId)

            comment = data.get('comment', '')
            body = templates[1] % locals()

            if 'richComment' in data:
                comment = data['richComment']

            vals = locals().copy()
            del vals['self']
            html = t.getBlock("emails.mako", templates[2], **vals)

        return (title, body, html)
    def _render(self, parts, value, getTitle, getBody, data, args):
        args.update({'brandName': brandName, 'rootUrl': rootUrl})

        if getTitle:
            title = self._template[0] % args

        if getBody:
            args['senderAvatarUrl'] = utils.userAvatar(value,
                                                       data['entities'][value],
                                                       "medium")
            args['senderId'] = value
            args['senderName'] = data['entities'][value].basic['name']
            body = self._template[1] % args
            html = t.getBlock("emails.mako", self._template[2], **args)

        return (title, body, html)
Example #5
0
    def updatePeopleIndex(self, myId, me, orgId):
        mailId = me.basic['emailId']
        fields = [self.elementMaker.field(myId, {"name":"id"}),
                  self.elementMaker.field(orgId, {"name":"org"}),
                  self.elementMaker.field('people', {"name":"_type"}),
                  self.elementMaker.field(mailId, {'name':'email'}) ]

        for field in ['name', 'lastname', 'firstname', 'jobTitle']:
            if field in me.basic:
                fields.append(self.elementMaker.field(_toUnicodeOrText(me.basic[field]), {'name': field}))

        for field in ['phone', 'mobile']:
            if field in me.contact:
                fields.append(self.elementMaker.field(_toUnicodeOrText(me.contact[field]), {'name': field}))

        for field in ['email', 'phone', 'mobile', 'currentCity']:
            if field in me.personal:
                fields.append(self.elementMaker.field(_toUnicodeOrText(me.personal[field]), {'name': field}))

        schools = set()
        for school in me.schools.keys():
            year, name = school.split(':', 1)
            schools.add(name)
        fields.extend([self.elementMaker.field(_toUnicodeOrText(x), {'name': 'school'}) for x in schools])

        companies = set()
        for company in me.companies.keys():
            end, start, name = company.split(':', 2)
            companies.add(name)
        fields.extend([self.elementMaker.field(_toUnicodeOrText(x), {'name': 'company'}) for x in companies])

        skills = ','.join(me.expertise.keys())
        if skills:
            fields.append(self.elementMaker.field(_toUnicodeOrText(skills), {'name': 'expertise'}))

        fields.append(self.elementMaker.field(str(int(time.time())), {'name': 'timestamp'}))

        avatarURI = utils.userAvatar(myId, me, 'small')
        fields.append(self.elementMaker.field(avatarURI, {'name': 'avatar'}))

        root = self.elementMaker.add(self.elementMaker.doc(*fields))
        return self._request("POST", self._updateURL, {}, XMLBodyProducer(root))
Example #6
0
    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
Example #7
0
    def render(self, parts, value, toOwner=False, getTitle=True, getBody=True,
                                                                    data=None):
        convId, convType, convOwnerId, notifyType = parts
        convTitle, convLocation, convTime = "", "", ""
        if "convMeta" in data:
            convMeta = data["convMeta"]
            me = data['me']
            entities = data['entities']

            convTitle = convMeta["event_title"]
            convLocation = convMeta.get("event_location", "")
            start = convMeta["event_startTime"]
            end   = convMeta["event_endTime"]
            owner = convMeta["owner"]
            ownerName = entities[owner].basic["name"]

            my_tz = timezone(me.basic['timezone'])
            owner_tz = timezone(entities[owner].basic['timezone'])
            utc = pytz.utc
            startdatetime = datetime.datetime.utcfromtimestamp(float(start)).replace(tzinfo=utc)
            enddatetime = datetime.datetime.utcfromtimestamp(float(end)).replace(tzinfo=utc)

            utc_dt = utc.normalize(startdatetime)
            start_dt = my_tz.normalize(startdatetime.astimezone(my_tz))
            end_dt = my_tz.normalize(enddatetime.astimezone(my_tz))

            if start_dt.date() == end_dt.date():
                sameDay = True
            else:
                sameDay = False

            allDay = True if convMeta.get("event_allDay", "0") == "1" else False

            if not allDay:
                event_start_fmt = "%a %b %d, %I:%M %p"
            else:
                event_start_fmt = "%a %b %d"
            event_start = start_dt.strftime(event_start_fmt)

            if allDay:
                event_end_fmt = "%a %b %d"
            elif sameDay:
                event_end_fmt = "%I:%M %p"
            else:
                event_end_fmt = "%a %b %d, %I:%M %p"
            event_end = end_dt.strftime(event_end_fmt)

            if not allDay:
                convTime += event_start
                if sameDay:
                    convTime += " to %s" % (event_end)
                else:
                    convTime += " -- %s" % (event_end)
            else:
                convTime += event_start
                if sameDay:
                    convTime += _("All Day")
                else:
                    convTime += " -- %s" % (event_end)

        if notifyType == "EI":
            templates = self._toOthers_EI
        else:
            templates = self._toOwner_EA

        title, body, html = '', '', ''
        senderName = data['me'].basic['name']
        convOwnerName = data['entities'][convOwnerId].basic['name']

        if getTitle:
            title = templates[0] % locals()

        if getBody:
            senderAvatarUrl = utils.userAvatar(data['myId'], data['me'], "medium")
            convUrl = "%s/item?id=%s" % (rootUrl, convId)
            body = templates[1] % locals()

            vals = locals().copy()
            del vals['self']
            html = t.getBlock("event.mako", templates[2], **vals)

        return (title, body, html)
Example #8
0
def _sendInvitations(myOrgUsers, otherOrgUsers, me, myId, myOrg):
    rootUrl = config.get('General', 'URL')
    brandName = config.get('Branding', 'Name')
    senderName = me.basic["name"]
    senderOrgName = myOrg.basic["name"]
    senderAvatarUrl = utils.userAvatar(myId, me, "medium")
    sentUsers = []
    blockedUsers = []
    existingUsers = []

    myOrgSubject = "%s invited you to %s" % (senderName, brandName)
    myOrgBody = "Hi,\n\n"\
                "%(senderName)s has invited you to %(senderOrgName)s network on %(brandName)s.\n"\
                "To activate your account please visit: %(activationUrl)s.\n\n"
    otherOrgSubject = "%s invited you to %s" % (senderName, brandName)
    otherOrgBody = "Hi,\n\n"\
                   "%(senderName)s has invited you to try %(brandName)s.\n"\
                   "To activate your account please visit: %(activationUrl)s.\n\n"

    signature = "Flocked.in Team.\n\n\n\n"\
                "--\n"\
                "To block invitations from %(senderName)s visit %(blockSenderUrl)s\n"\
                "To block all invitations from %(brandName)s visit %(blockAllUrl)s"

    blockSenderTmpl = "%(rootUrl)s/signup/blockSender?email=%(emailId)s&token=%(token)s"
    blockAllTmpl = "%(rootUrl)s/signup/blockAll?email=%(emailId)s&token=%(token)s"
    activationTmpl = "%(rootUrl)s/signup?email=%(emailId)s&token=%(token)s"

    # Combine all users.
    myOrgUsers.extend(otherOrgUsers)

    # Ensure that the users do not already exist and that the users are
    # not in the doNotSpam list (for this sender or globally)
    d1 = db.multiget(myOrgUsers, "userAuth", "user")
    d2 = db.multiget_slice(myOrgUsers, "doNotSpam", [myId, '*'])
    existing = yield d1
    existing = utils.multiColumnsToDict(existing)
    doNotSpam = yield d2
    doNotSpam = utils.multiColumnsToDict(doNotSpam)

    deferreds = []
    for emailId in myOrgUsers:
        if emailId in existing and existing[emailId]:
            existingUsers.append(emailId)
            continue

        token = utils.getRandomKey()

        # Add invitation to the database
        localpart, domainpart = emailId.split('@')
        deferreds.append(db.insert(domainpart, "invitations", myId, token, emailId))
        deferreds.append(db.insert(myId, "invitationsSent", '', emailId))

        # Mail the invitation if everything is ok.
        if emailId in doNotSpam and doNotSpam[emailId]:
            blockedUsers.append(emailId)
            continue

        activationUrl = activationTmpl % locals()
        blockAllUrl = blockAllTmpl % locals()
        blockSenderUrl = blockSenderTmpl % locals()
        sameOrg = False if emailId in otherOrgUsers else True
        if not sameOrg:
            subject = otherOrgSubject
            textBody = (otherOrgBody + signature) % locals()
        else:
            subject = myOrgSubject
            textBody = (myOrgBody + signature) % locals()

        # XXX: getBlock blocks the application for disk reads when reading template
        htmlBody = t.getBlock("emails.mako", "invite", **locals())
        deferreds.append(utils.sendmail(emailId, subject, textBody, htmlBody))
        sentUsers.append(emailId)

    yield defer.DeferredList(deferreds)
    defer.returnValue((sentUsers, blockedUsers, existingUsers))
Example #9
0
    def _editBasicInfo(self, request):
        authInfo = request.getSession(IAuthInfo)
        myId = authInfo.username
        orgId = authInfo.organization

        userInfo = {"basic":{}}
        to_remove = []
        basicUpdatedInfo, basicUpdated = {}, False

        me = base.Entity(myId)
        yield me.fetchData([])

        # Check if any basic information is being updated.
        for cn in ("jobTitle", "name", "firstname", "lastname", "timezone"):
            val = utils.getRequestArg(request, cn)
            if not val and cn in ['name', 'jobTitle', 'timezone']:
                request.write("<script>parent.$$.alerts.error('One or more required parameters are missing')</script>")
                raise errors.MissingParams(_([cn]))
            if val:
                userInfo["basic"][cn] = val
                basicUpdatedInfo[cn] = val
            elif cn in ["firstname", "lastname"]:
                to_remove.append(cn)
                basicUpdatedInfo[cn] = ""
            if me.basic.get(cn, None) != userInfo['basic'].get(cn, None):
                basicUpdated = True

        # Update name indicies of organization.
        nameIndexKeys = [orgId]
        nameIndicesDeferreds = []
        oldNameParts = []
        newNameParts = []
        for field in ["name", "lastname", "firstname"]:
            if field in basicUpdatedInfo:
                newNameParts.extend(basicUpdatedInfo[field].split())
                oldNameParts.extend(me.basic.get(field, '').split())
                if field == 'name':
                    d1 = utils.updateDisplayNameIndex(myId, nameIndexKeys,
                                                      basicUpdatedInfo[field],
                                                      me.basic.get(field, None))
                    nameIndicesDeferreds.append(d1)
        d = utils.updateNameIndex(myId, nameIndexKeys,
                                  " ".join(newNameParts),
                                  " ".join(oldNameParts))
        nameIndicesDeferreds.append(d)

        # Avatar (display picture)
        dp = utils.getRequestArg(request, "dp", sanitize=False)
        if dp:
            avatar = yield saveAvatarItem(myId, orgId, dp)
            userInfo["basic"]["avatar"] = avatar
            me.basic["avatar"] = avatar
            avatarURI = utils.userAvatar(myId, me)
            basicUpdatedInfo["avatar"] = avatarURI
            basicUpdated = True
        if userInfo["basic"]:
            yield db.batch_insert(myId, "entities", userInfo)
            me.basic.update(userInfo['basic'])
            yield search.solr.updatePeopleIndex(myId, me, orgId)

        if to_remove:
            yield db.batch_remove({'entities':[myId]}, names=to_remove, supercolumn='basic')

        if basicUpdated:
            response = """
                        <script>
                            var data = %s;
                            if (data.avatar){
                              var imageUrl = data.avatar;
                              parent.$('#avatar').css('background-image', 'url(' + imageUrl + ')');
                            }
                            parent.$('#name').html(data.name + ', ' + data.jobTitle);
                            parent.$$.alerts.info("%s");
                        </script>
                        """ % (json.dumps(basicUpdatedInfo),  _("Profile updated"))
            request.write(response)

        # Wait for name indices to be updated.
        if nameIndicesDeferreds:
            yield defer.DeferredList(nameIndicesDeferreds)

        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)