예제 #1
0
class UserAccountV1(Model):
    """A user account."""

    bucket = "useraccount"
    VERSION = 1
    MIGRATOR = UserAccountMigrator

    # key is uuid
    username = Unicode(max_length=255)
    # TODO: tagpools can be made OneToMany once vumi.persist.fields
    #       gains a OneToMany field
    tagpools = ManyToMany(UserTagPermissionVNone)
    applications = ManyToMany(UserAppPermissionVNone)
    created_at = Timestamp(default=datetime.utcnow)
    event_handler_config = Json(default=list)
    msisdn = Unicode(max_length=255, null=True)
    confirm_start_conversation = Boolean(default=False)
    # `tags` is allowed to be null so that we can detect freshly-migrated
    # accounts and populate the tags from active conversations. A new account
    # has no legacy tags or conversations, so we start with an empty list and
    # skip the tag collection.
    tags = Json(default=[], null=True)

    @Manager.calls_manager
    def has_tagpool_permission(self, tagpool):
        for tp_bunch in self.tagpools.load_all_bunches():
            for tp in (yield tp_bunch):
                if tp.tagpool == tagpool:
                    returnValue(True)
        returnValue(False)
예제 #2
0
class UserAccountV4(Model):
    """A user account."""

    VERSION = 4

    # key is uuid
    username = Unicode(max_length=255)
    # TODO: tagpools can be made OneToMany once vumi.persist.fields
    #       gains a OneToMany field
    tagpools = ManyToMany(UserTagPermissionVNone)
    applications = ManyToMany(UserAppPermissionVNone)
    created_at = Timestamp(default=datetime.utcnow)
    event_handler_config = Json(default=list)
    msisdn = Unicode(max_length=255, null=True)
    confirm_start_conversation = Boolean(default=False)
    can_manage_optouts = Boolean(default=False)
    email_summary = Unicode(max_length=255, null=True)
    tags = Json(default=[])
    routing_table = RoutingTableField(default=RoutingTable({}))

    @Manager.calls_manager
    def has_tagpool_permission(self, tagpool):
        for tp_bunch in self.tagpools.load_all_bunches():
            for tp in (yield tp_bunch):
                if tp.tagpool == tagpool:
                    returnValue(True)
        returnValue(False)
예제 #3
0
class UserAccountVNone(Model):
    """A user account."""
    bucket = "useraccount"

    # key is uuid
    username = Unicode(max_length=255)
    # TODO: tagpools can be made OneToMany once vumi.persist.fields
    #       gains a OneToMany field
    tagpools = ManyToMany(UserTagPermissionVNone)
    applications = ManyToMany(UserAppPermissionVNone)
    created_at = Timestamp(default=datetime.utcnow)
    event_handler_config = Json(null=True)
    msisdn = Unicode(max_length=255, null=True)
    confirm_start_conversation = Boolean(default=False)
예제 #4
0
 def test_from_riak(self):
     j = Json()
     d = {"foo": [1, 2, 3]}
     self.assertEqual(j.from_riak(d), d)
예제 #5
0
 def test_to_riak(self):
     j = Json()
     d = {"foo": 5}
     self.assertEqual(j.to_riak(d), d)
예제 #6
0
 def test_validate(self):
     j = Json()
     j.validate({"foo": None})
     self.assertRaises(ValidationError, j.validate, None)
예제 #7
0
 def test_from_riak(self):
     j = Json()
     d = {"foo": [1, 2, 3]}
     self.assertEqual(j.from_riak(d), d)
예제 #8
0
 def test_to_riak(self):
     j = Json()
     d = {"foo": 5}
     self.assertEqual(j.to_riak(d), d)
예제 #9
0
 def test_validate(self):
     j = Json()
     j.validate({"foo": None})
     self.assertRaises(ValidationError, j.validate, None)
예제 #10
0
class Conversation(Model):
    """A conversation with an audience"""

    VERSION = 3
    MIGRATOR = ConversationMigrator

    user_account = ForeignKey(UserAccount)
    name = Unicode(max_length=255)
    description = Unicode(default=u'')
    conversation_type = Unicode(index=True)
    config = Json(default=dict)
    extra_endpoints = ListOf(Unicode())

    created_at = Timestamp(default=datetime.utcnow, index=True)
    archived_at = Timestamp(null=True, index=True)

    archive_status = Unicode(default=CONVERSATION_ACTIVE, index=True)
    status = Unicode(default=CONVERSATION_STOPPED, index=True)

    groups = ManyToMany(ContactGroup)
    batch = ForeignKey(Batch)

    delivery_class = Unicode(null=True)

    def active(self):
        return self.archive_status == CONVERSATION_ACTIVE

    def archived(self):
        return self.archive_status == CONVERSATION_ARCHIVED

    def ended(self):
        # TODO: Get rid of this once the old UI finally goes away.
        return self.archived()

    def starting(self):
        return self.status == CONVERSATION_STARTING

    def running(self):
        return self.status == CONVERSATION_RUNNING

    def stopping(self):
        return self.status == CONVERSATION_STOPPING

    def stopped(self):
        return self.status == CONVERSATION_STOPPED

    def is_draft(self):
        # TODO: Get rid of this once the old UI finally goes away.
        return self.active() and self.status == CONVERSATION_STOPPED

    def get_status(self):
        """Get the status of this conversation.

        Possible values are:

          * CONVERSATION_STARTING
          * CONVERSATION_RUNNING
          * CONVERSATION_STOPPING
          * CONVERSATION_STOPPED

        :rtype: str

        """
        return self.status

    # The following are to keep the implementation of this stuff in the model
    # rather than potentially multiple external places.
    def set_status_starting(self):
        self.status = CONVERSATION_STARTING

    def set_status_started(self):
        self.status = CONVERSATION_RUNNING

    def set_status_stopping(self):
        self.status = CONVERSATION_STOPPING

    def set_status_stopped(self):
        self.status = CONVERSATION_STOPPED

    def set_status_finished(self):
        self.archive_status = CONVERSATION_ARCHIVED

    def add_group(self, group):
        if isinstance(group, ContactGroup):
            self.groups.add(group)
        else:
            self.groups.add_key(group)

    def __unicode__(self):
        return self.name

    def get_contacts_addresses(self, contacts):
        """
        Get the contacts assigned to this group with an address attribute
        that is appropriate for this conversation's delivery_class
        """
        addrs = [contact.addr_for(self.delivery_class) for contact in contacts]
        return [addr for addr in addrs if addr]

    def get_connector(self):
        return GoConnector.for_conversation(self.conversation_type, self.key)
예제 #11
0
class ConversationV1(Model):
    """A conversation with an audience"""

    VERSION = 1
    MIGRATOR = ConversationMigrator

    bucket = 'conversation'

    user_account = ForeignKey(UserAccount)
    name = Unicode(max_length=255)
    description = Unicode(default=u'')
    conversation_type = Unicode(index=True)
    config = Json(default=dict)

    created_at = Timestamp(default=datetime.utcnow, index=True)
    start_timestamp = Timestamp(index=True)
    end_timestamp = Timestamp(null=True, index=True)
    status = Unicode(default=CONVERSATION_DRAFT, index=True)

    groups = ManyToMany(ContactGroup)
    batches = ManyToMany(Batch)

    delivery_class = Unicode(null=True)
    delivery_tag_pool = Unicode(null=True)
    delivery_tag = Unicode(null=True)

    def started(self):
        return self.running() or self.ended()

    def ended(self):
        return self.status == CONVERSATION_FINISHED

    def running(self):
        return self.status == CONVERSATION_RUNNING

    def get_status(self):
        """
        Get the status of this conversation

        :rtype: str, (CONVERSATION_FINISHED, CONVERSATION_RUNNING, or
            CONVERSATION_DRAFT)

        """
        return self.status

    # The following are to keep the implementation of this stuff in the model
    # rather than potentially multiple external places.
    def set_status_started(self):
        self.status = CONVERSATION_RUNNING

    def set_status_finished(self):
        self.status = CONVERSATION_FINISHED

    def add_group(self, group):
        if isinstance(group, ContactGroup):
            self.groups.add(group)
        else:
            self.groups.add_key(group)

    def __unicode__(self):
        return self.name

    def get_contacts_addresses(self, contacts):
        """
        Get the contacts assigned to this group with an address attribute
        that is appropriate for this conversation's delivery_class
        """
        addrs = [contact.addr_for(self.delivery_class) for contact in contacts]
        return [addr for addr in addrs if addr]

    def get_routing_name(self):
        return ':'.join((self.conversation_type, self.key))
예제 #12
0
class ConversationVNone(Model):
    """A conversation with an audience"""

    MIGRATOR = ConversationMigrator

    bucket = 'conversation'

    user_account = ForeignKey(UserAccount)
    subject = Unicode(max_length=255)
    message = Unicode()
    start_timestamp = Timestamp()
    end_timestamp = Timestamp(null=True, index=True)
    created_at = Timestamp(default=datetime.utcnow)

    groups = ManyToMany(ContactGroup)
    conversation_type = Unicode()
    delivery_class = Unicode(null=True)
    delivery_tag_pool = Unicode(null=True)
    delivery_tag = Unicode(null=True)

    batches = ManyToMany(Batch)
    metadata = Json(null=True)

    def started(self):
        # TODO: Better way to tell if we've started than looking for batches.
        return bool(self.batches.keys())

    def ended(self):
        return self.end_timestamp is not None

    def running(self):
        return self.started() and not self.ended()

    def get_status(self):
        """
        Get the status of this conversation

        :rtype: str, (CONVERSATION_FINISHED, CONVERSATION_RUNNING, or
            CONVERSATION_DRAFT)

        """
        if self.ended():
            return CONVERSATION_FINISHED
        elif self.running():
            return CONVERSATION_RUNNING
        else:
            return CONVERSATION_DRAFT

    def add_group(self, group):
        if isinstance(group, ContactGroup):
            self.groups.add(group)
        else:
            self.groups.add_key(group)

    def __unicode__(self):
        return self.subject

    def get_contacts_addresses(self, contacts):
        """
        Get the contacts assigned to this group with an address attribute
        that is appropriate for this conversation's delivery_class
        """
        addrs = [contact.addr_for(self.delivery_class) for contact in contacts]
        return [addr for addr in addrs if addr]
예제 #13
0
 class JsonModel(Model):
     """
     Toy model for Json tests.
     """
     j = Json()
예제 #14
0
class Router(Model):
    """A router for sending messages to interesting places."""

    VERSION = 1
    MIGRATOR = None

    user_account = ForeignKey(UserAccount)
    name = Unicode(max_length=255)
    description = Unicode(default=u'')
    router_type = Unicode(index=True)
    config = Json(default=dict)
    extra_inbound_endpoints = ListOf(Unicode())
    extra_outbound_endpoints = ListOf(Unicode())

    created_at = Timestamp(default=datetime.utcnow, index=True)
    archived_at = Timestamp(null=True, index=True)

    archive_status = Unicode(default=ROUTER_ACTIVE, index=True)
    status = Unicode(default=ROUTER_STOPPED, index=True)

    batch = ForeignKey(Batch)

    def active(self):
        return self.archive_status == ROUTER_ACTIVE

    def archived(self):
        return self.archive_status == ROUTER_ARCHIVED

    def starting(self):
        return self.status == ROUTER_STARTING

    def running(self):
        return self.status == ROUTER_RUNNING

    def stopping(self):
        return self.status == ROUTER_STOPPING

    def stopped(self):
        return self.status == ROUTER_STOPPED

    # The following are to keep the implementation of this stuff in the model
    # rather than potentially multiple external places.
    def set_status_starting(self):
        self.status = ROUTER_STARTING

    def set_status_started(self):
        self.status = ROUTER_RUNNING

    def set_status_stopping(self):
        self.status = ROUTER_STOPPING

    def set_status_stopped(self):
        self.status = ROUTER_STOPPED

    def set_status_finished(self):
        self.archive_status = ROUTER_ARCHIVED

    def __unicode__(self):
        return self.name

    def get_inbound_connector(self):
        return GoConnector.for_router(self.router_type, self.key,
                                      GoConnector.INBOUND)

    def get_outbound_connector(self):
        return GoConnector.for_router(self.router_type, self.key,
                                      GoConnector.OUTBOUND)