Example #1
0
class RoleUser(sql.ModelBase, sql.ModelDictMixin):
    """Roles users join table."""
    __tablename__ = 'role_user_fiware'
    role_id = sql.Column(sql.String(64),
                         sql.ForeignKey('role_fiware.id'),
                         primary_key=True)
    user_id = sql.Column(sql.String(64),
                         sql.ForeignKey('user.id'),
                         primary_key=True)
    organization_id = sql.Column(sql.String(64),
                         sql.ForeignKey('project.id'),
                         primary_key=True)
    application_id = sql.Column(sql.String(64),
                         sql.ForeignKey('consumer_oauth2.id'),
                         primary_key=True)
Example #2
0
class NonLocalUser(sql.ModelBase, sql.ModelDictMixin):
    """SQL data model for nonlocal users (LDAP and custom)."""

    __tablename__ = 'nonlocal_user'
    attributes = ['domain_id', 'name', 'user_id']
    domain_id = sql.Column(sql.String(64), primary_key=True)
    name = sql.Column(sql.String(255), primary_key=True)
    user_id = sql.Column(sql.String(64))
    __table_args__ = (
        sql.UniqueConstraint('user_id'),
        sqlalchemy.ForeignKeyConstraint(['user_id', 'domain_id'],
                                        ['user.id', 'user.domain_id'],
                                        onupdate='CASCADE',
                                        ondelete='CASCADE'),
    )
Example #3
0
class Endpoint(sql.ModelBase, sql.DictBase):
    __tablename__ = 'endpoint'
    attributes = ['id', 'interface', 'region', 'service_id', 'url',
                  'legacy_endpoint_id', 'enabled']
    id = sql.Column(sql.String(64), primary_key=True)
    legacy_endpoint_id = sql.Column(sql.String(64))
    interface = sql.Column(sql.String(8), nullable=False)
    region = sql.Column(sql.String(255))
    service_id = sql.Column(sql.String(64),
                            sql.ForeignKey('service.id'),
                            nullable=False)
    url = sql.Column(sql.Text(), nullable=False)
    enabled = sql.Column(sql.Boolean, nullable=False, default=True,
                         server_default=sqlalchemy.sql.expression.true())
    extra = sql.Column(sql.JsonBlob())
Example #4
0
class UserProjectMetadata(sql.ModelBase, sql.DictBase):
    # TODO(dolph): rename to user_project_metadata (needs a migration)
    __tablename__ = 'metadata'
    user_id = sql.Column(sql.String(64), primary_key=True)
    # TODO(dolph): rename to project_id (needs a migration)
    tenant_id = sql.Column(sql.String(64), primary_key=True)
    data = sql.Column(sql.JsonBlob())

    def to_dict(self):
        """Override parent to_dict() method with a simpler implementation.

        Metadata doesn't have non-indexed 'extra' attributes, so the parent
        implementation is not applicable.
        """
        return dict(self.iteritems())
Example #5
0
class TokenModel(sql.ModelBase, sql.DictBase):
    __tablename__ = 'token'
    attributes = ['id', 'expires', 'user_id', 'trust_id']
    id = sql.Column(sql.String(64), primary_key=True)
    expires = sql.Column(sql.DateTime(), default=None)
    extra = sql.Column(sql.JsonBlob())
    valid = sql.Column(sql.Boolean(), default=True, nullable=False)
    user_id = sql.Column(sql.String(64))
    trust_id = sql.Column(sql.String(64))
    __table_args__ = (
        sql.Index('ix_token_expires', 'expires'),
        sql.Index('ix_token_expires_valid', 'expires', 'valid'),
        sql.Index('ix_token_user_id', 'user_id'),
        sql.Index('ix_token_trust_id', 'trust_id')
    )
Example #6
0
class IdentityProviderModel(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'identity_provider'
    attributes = [
        'id', 'domain_id', 'enabled', 'description', 'remote_ids',
        'authorization_ttl'
    ]
    mutable_attributes = frozenset(
        ['description', 'enabled', 'remote_ids', 'authorization_ttl'])

    id = sql.Column(sql.String(64), primary_key=True)
    domain_id = sql.Column(sql.String(64), nullable=False)
    enabled = sql.Column(sql.Boolean, nullable=False)
    description = sql.Column(sql.Text(), nullable=True)
    authorization_ttl = sql.Column(sql.Integer, nullable=True)

    remote_ids = orm.relationship('IdPRemoteIdsModel',
                                  order_by='IdPRemoteIdsModel.remote_id',
                                  cascade='all, delete-orphan')
    expiring_user_group_memberships = orm.relationship(
        'ExpiringUserGroupMembership',
        cascade='all, delete-orphan',
        backref="idp")

    @classmethod
    def from_dict(cls, dictionary):
        new_dictionary = dictionary.copy()
        remote_ids_list = new_dictionary.pop('remote_ids', None)
        if not remote_ids_list:
            remote_ids_list = []
        identity_provider = cls(**new_dictionary)
        remote_ids = []
        # NOTE(fmarco76): the remote_ids_list contains only remote ids
        # associated with the IdP because of the "relationship" established in
        # sqlalchemy and corresponding to the FK in the idp_remote_ids table
        for remote in remote_ids_list:
            remote_ids.append(IdPRemoteIdsModel(remote_id=remote))
        identity_provider.remote_ids = remote_ids
        return identity_provider

    def to_dict(self):
        """Return a dictionary with model's attributes."""
        d = dict()
        for attr in self.__class__.attributes:
            d[attr] = getattr(self, attr)
        d['remote_ids'] = []
        for remote in self.remote_ids:
            d['remote_ids'].append(remote.remote_id)
        return d
Example #7
0
class LocalUser(sql.ModelBase, sql.DictBase):
    __tablename__ = 'local_user'
    attributes = ['id', 'user_id', 'domain_id', 'name']
    id = sql.Column(sql.Integer, primary_key=True)
    user_id = sql.Column(sql.String(64),
                         sql.ForeignKey('user.id', ondelete='CASCADE'),
                         unique=True)
    domain_id = sql.Column(sql.String(64), nullable=False)
    name = sql.Column(sql.String(255), nullable=False)
    passwords = orm.relationship('Password',
                                 single_parent=True,
                                 cascade='all,delete-orphan',
                                 lazy='subquery',
                                 backref='local_user',
                                 order_by='Password.created_at')
    __table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {})
Example #8
0
class Password(sql.ModelBase, sql.DictBase):
    __tablename__ = 'password'
    attributes = ['id', 'local_user_id', 'password']
    id = sql.Column(sql.Integer, primary_key=True)
    local_user_id = sql.Column(
        sql.Integer, sql.ForeignKey('local_user.id', ondelete='CASCADE'))
    password = sql.Column(sql.String(128))
Example #9
0
class TokenModel(sql.ModelBase, sql.DictBase):
    __tablename__ = 'token'
    attributes = ['id', 'expires']
    id = sql.Column(sql.String(64), primary_key=True)
    expires = sql.Column(sql.DateTime(), default=None)
    extra = sql.Column(sql.JsonBlob())
    valid = sql.Column(sql.Boolean(), default=True)
Example #10
0
class Consumer(sql.ModelBase, sql.DictBase):
    __tablename__ = 'consumer_oauth2'
    attributes = ['id', 'name', 'description', 'secret', 'client_type', 'redirect_uris',
                    'grant_type', 'response_type', 'scopes', 'extra']
    __table_args__ = {'extend_existing': True}                
    id = sql.Column(sql.String(64), primary_key=True, nullable=False)
    name = sql.Column(sql.String(64), nullable=False)
    description = sql.Column(sql.Text(), nullable=True)
    secret = sql.Column(sql.String(128), nullable=False)
    client_type = sql.Column(VALID_CLIENT_TYPES, nullable=False) 
    redirect_uris = sql.Column(sql.JsonBlob(), nullable=False)
    grant_type = sql.Column(VALID_GRANT_TYPES, nullable=False) 
    response_type = sql.Column(VALID_RESPONSE_TYPES, nullable=False)
    # TODO(garcianavalon) better naming to reflect they are the allowed scopes for the client
    scopes = sql.Column(sql.JsonBlob(), nullable=True)
    extra = sql.Column(sql.JsonBlob(), nullable=True)
Example #11
0
class TrustModel(sql.ModelBase, sql.DictBase):
    __tablename__ = 'trust'
    attributes = ['id', 'trustor_user_id', 'trustee_user_id',
                  'project_id', 'impersonation', 'expires_at',
                  'remaining_uses']
    id = sql.Column(sql.String(64), primary_key=True)
    #user id Of owner
    trustor_user_id = sql.Column(sql.String(64), nullable=False,)
    #user_id of user allowed to consume this preauth
    trustee_user_id = sql.Column(sql.String(64), nullable=False)
    project_id = sql.Column(sql.String(64))
    impersonation = sql.Column(sql.Boolean, nullable=False)
    deleted_at = sql.Column(sql.DateTime)
    expires_at = sql.Column(sql.DateTime)
    remaining_uses = sql.Column(sql.Integer, nullable=True)
    extra = sql.Column(sql.JsonBlob())
Example #12
0
class Permission(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'permission_fiware'
    __table_args__ = (sql.UniqueConstraint('name', 'application_id'), {'extend_existing': True})
    attributes = ['id', 'name', 'is_internal', 'application_id', 'action'
                  'resource', 'xml']
    id = sql.Column(sql.String(64), primary_key=True, nullable=False)
    name = sql.Column(sql.String(64), nullable=False)
    is_internal = sql.Column(sql.Boolean(), default=False, nullable=False)
    application_id = sql.Column(
        sql.String(64),
        sql.ForeignKey('consumer_oauth2.id'),
        nullable=False,
        index=True)
    action = sql.Column(sql.String(10), nullable=True)
    resource = sql.Column(sql.String(256), nullable=True)
    xml = sql.Column(sql.Text(), nullable=True)
Example #13
0
class RegisteredLimitModel(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'registered_limit'
    attributes = [
        'id', 'service_id', 'region_id', 'resource_name', 'default_limit'
    ]

    id = sql.Column(sql.String(length=64), primary_key=True)
    service_id = sql.Column(sql.String(255), sql.ForeignKey('service.id'))
    region_id = sql.Column(sql.String(64),
                           sql.ForeignKey('region.id'),
                           nullable=True)
    resource_name = sql.Column(sql.String(255))
    default_limit = sql.Column(sql.Integer, nullable=False)

    __table_args__ = (sqlalchemy.UniqueConstraint('service_id', 'region_id',
                                                  'resource_name'), )
Example #14
0
class Project(sql.ModelBase, sql.DictBase):
    __tablename__ = 'project'
    attributes = [
        'id', 'name', 'domain_id', 'description', 'enabled', 'parent_id'
    ]
    id = sql.Column(sql.String(64), primary_key=True)
    name = sql.Column(sql.String(64), nullable=False)
    domain_id = sql.Column(sql.String(64),
                           sql.ForeignKey('domain.id'),
                           nullable=False)
    description = sql.Column(sql.Text())
    enabled = sql.Column(sql.Boolean)
    extra = sql.Column(sql.JsonBlob())
    parent_id = sql.Column(sql.String(64), sql.ForeignKey('project.id'))
    # Unique constraint across two columns to create the separation
    # rather than just only 'name' being unique
    __table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {})
Example #15
0
class Region(sql.ModelBase, sql.DictBase):
    __tablename__ = 'region'
    attributes = ['id', 'description', 'parent_region_id']
    id = sql.Column(sql.String(255), primary_key=True)
    description = sql.Column(sql.String(255), nullable=False)
    # NOTE(jaypipes): Right now, using an adjacency list model for
    #                 storing the hierarchy of regions is fine, since
    #                 the API does not support any kind of querying for
    #                 more complex hierarchical queries such as "get me only
    #                 the regions that are subchildren of this region", etc.
    #                 If, in the future, such queries are needed, then it
    #                 would be possible to add in columns to this model for
    #                 "left" and "right" and provide support for a nested set
    #                 model.
    parent_region_id = sql.Column(sql.String(255), nullable=True)
    extra = sql.Column(sql.JsonBlob())
    endpoints = sqlalchemy.orm.relationship("Endpoint", backref="region")
Example #16
0
class AccessToken(sql.ModelBase, sql.DictBase):
    __tablename__ = 'access_token_oauth2'

    attributes = ['id', 'consumer_id', 'authorizing_user_id', 'expires_at',
                'scopes', 'refresh_token', 'valid', 'extra']

    id = sql.Column(sql.String(64), primary_key=True, nullable=False)
    consumer_id = sql.Column(sql.String(64), sql.ForeignKey('consumer_oauth2.id'),
                             nullable=False, index=True)
    # NOTE(garcianavalon) if the consumers uses the client credentials grant
    # there is no authorizing user, so it should be nullable.
    authorizing_user_id = sql.Column(sql.String(64), nullable=True)
    # TODO(garcianavalon) datetime type or similar?
    expires_at = sql.Column(sql.String(64), nullable=False)
    scopes = sql.Column(sql.JsonBlob(), nullable=True)
    refresh_token = sql.Column(sql.String(64), nullable=True)
    valid = sql.Column(sql.Boolean(), default=True, nullable=False)
    extra = sql.Column(sql.JsonBlob(), nullable=True)
Example #17
0
class ConsumerCredentials(sql.ModelBase, sql.DictBase):
    __tablename__ = 'consumer_credentials_oauth2'
    attributes = [
        'id', 'user_id', 'client_id', 'redirect_uri', 'response_type', 'state',
        'created_at', 'extra'
    ]

    id = sql.Column(sql.String(64), primary_key=True, nullable=False)
    user_id = sql.Column(sql.String(64), index=True, nullable=False)
    client_id = sql.Column(sql.String(64),
                           sql.ForeignKey('consumer_oauth2.id'),
                           nullable=False,
                           index=True)
    redirect_uri = sql.Column(sql.String(256), nullable=False)
    response_type = sql.Column(VALID_RESPONSE_TYPES, nullable=False)
    state = sql.Column(sql.String(256), nullable=True)
    created_at = sql.Column(sql.DateTime(), default=None, nullable=False)
    extra = sql.Column(sql.JsonBlob(), nullable=True)
Example #18
0
class FederatedUser(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'federated_user'
    attributes = ['id', 'user_id', 'idp_id', 'protocol_id', 'unique_id',
                  'display_name']
    id = sql.Column(sql.Integer, primary_key=True)
    user_id = sql.Column(sql.String(64), sql.ForeignKey('user.id',
                                                        ondelete='CASCADE'))
    idp_id = sql.Column(sql.String(64), sql.ForeignKey('identity_provider.id',
                                                       ondelete='CASCADE'))
    protocol_id = sql.Column(sql.String(64), nullable=False)
    unique_id = sql.Column(sql.String(255), nullable=False)
    display_name = sql.Column(sql.String(255), nullable=True)
    __table_args__ = (
        sql.UniqueConstraint('idp_id', 'protocol_id', 'unique_id'),
        sqlalchemy.ForeignKeyConstraint(['protocol_id', 'idp_id'],
                                        ['federation_protocol.id',
                                         'federation_protocol.idp_id'])
    )
Example #19
0
class AccessRuleModel(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'access_rule'
    attributes = ['external_id', 'user_id', 'service', 'path', 'method']
    id = sql.Column(sql.Integer, primary_key=True, nullable=False)
    external_id = sql.Column(sql.String(64), index=True, unique=True)
    user_id = sql.Column(sql.String(64), index=True)
    service = sql.Column(sql.String(64))
    path = sql.Column(sql.String(128))
    method = sql.Column(sql.String(16))
    __table_args__ = (sql.UniqueConstraint(
        'user_id',
        'service',
        'path',
        'method',
        name='duplicate_access_rule_for_user_constraint'), )
    application_credential = sqlalchemy.orm.relationship(
        'ApplicationCredentialAccessRuleModel',
        backref=sqlalchemy.orm.backref('access_rule'))
Example #20
0
class ApplicationCredentialRoleModel(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'application_credential_role'
    attributes = ['application_credential_id', 'role_id']
    application_credential_id = sql.Column(
        sql.Integer,
        sql.ForeignKey('application_credential.internal_id',
                       ondelete='cascade'),
        primary_key=True,
        nullable=False)
    role_id = sql.Column(sql.String(64), primary_key=True, nullable=False)
Example #21
0
class Password(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'password'
    attributes = ['id', 'local_user_id', 'password', 'password_hash',
                  'created_at', 'expires_at']
    id = sql.Column(sql.Integer, primary_key=True)
    local_user_id = sql.Column(sql.Integer, sql.ForeignKey('local_user.id',
                               ondelete='CASCADE'))
    # TODO(notmorgan): in the Q release the "password" field can be dropped as
    # long as data migration exists to move the hashes over to the
    # password_hash column if no value is in the password_hash column.
    password = sql.Column(sql.String(128), nullable=True)
    password_hash = sql.Column(sql.String(255), nullable=True)

    # created_at default set here to safe guard in case it gets missed
    created_at = sql.Column(sql.DateTime, nullable=False,
                            default=datetime.datetime.utcnow)
    expires_at = sql.Column(sql.DateTime, nullable=True)
    self_service = sql.Column(sql.Boolean, default=False, nullable=False,
                              server_default='0')
Example #22
0
class RevocationEvent(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'revocation_event'
    attributes = model.REVOKE_KEYS

    # The id field is not going to be exposed to the outside world.
    # It is, however, necessary for SQLAlchemy.
    id = sql.Column(sql.String(64), primary_key=True)
    domain_id = sql.Column(sql.String(64))
    project_id = sql.Column(sql.String(64))
    user_id = sql.Column(sql.String(64))
    role_id = sql.Column(sql.String(64))
    trust_id = sql.Column(sql.String(64))
    consumer_id = sql.Column(sql.String(64))
    access_token_id = sql.Column(sql.String(64))
    issued_before = sql.Column(sql.DateTime(), nullable=False)
    expires_at = sql.Column(sql.DateTime())
    revoked_at = sql.Column(sql.DateTime(), nullable=False, index=True)
    audit_id = sql.Column(sql.String(32))
    audit_chain_id = sql.Column(sql.String(32))
Example #23
0
class User(sql.ModelBase, sql.DictBase):
    __tablename__ = 'user'
    attributes = ['id', 'name', 'domain_id', 'password', 'enabled',
                  'default_project_id']
    id = sql.Column(sql.String(64), primary_key=True)
    name = sql.Column(sql.String(255), nullable=False)
    domain_id = sql.Column(sql.String(64), nullable=False)
    password = sql.Column(sql.String(128))
    enabled = sql.Column(sql.Boolean)
    extra = sql.Column(sql.JsonBlob())
    default_project_id = sql.Column(sql.String(64))
    # Unique constraint across two columns to create the separation
    # rather than just only 'name' being unique
    __table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {})

    def to_dict(self, include_extra_dict=False):
        d = super(User, self).to_dict(include_extra_dict=include_extra_dict)
        if 'default_project_id' in d and d['default_project_id'] is None:
            del d['default_project_id']
        return d
Example #24
0
class RegisteredLimitModel(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'registered_limit'
    attributes = [
        'internal_id', 'id', 'service_id', 'region_id', 'resource_name',
        'default_limit', 'description'
    ]

    internal_id = sql.Column(sql.Integer, primary_key=True, nullable=False)
    id = sql.Column(sql.String(length=64), nullable=False, unique=True)
    service_id = sql.Column(sql.String(255), sql.ForeignKey('service.id'))
    region_id = sql.Column(sql.String(64),
                           sql.ForeignKey('region.id'),
                           nullable=True)
    resource_name = sql.Column(sql.String(255))
    default_limit = sql.Column(sql.Integer, nullable=False)
    description = sql.Column(sql.Text())

    def to_dict(self):
        ref = super(RegisteredLimitModel, self).to_dict()
        ref.pop('internal_id')
        return ref
class IdPRemoteIdsModel(sql.ModelBase, sql.DictBase):
    __tablename__ = 'idp_remote_ids'
    attributes = ['idp_id', 'remote_id']
    mutable_attributes = frozenset(['idp_id', 'remote_id'])

    idp_id = sql.Column(
        sql.String(64),
        sql.ForeignKey('identity_provider.id', ondelete='CASCADE'))
    remote_id = sql.Column(sql.String(255), primary_key=True)

    @classmethod
    def from_dict(cls, dictionary):
        new_dictionary = dictionary.copy()
        return cls(**new_dictionary)

    def to_dict(self):
        """Return a dictionary with model's attributes."""
        d = dict()
        for attr in self.__class__.attributes:
            d[attr] = getattr(self, attr)
        return d
Example #26
0
class Password(sql.ModelBase, sql.DictBase):
    __tablename__ = 'password'
    attributes = ['id', 'local_user_id', 'password', 'created_at',
                  'expires_at']
    id = sql.Column(sql.Integer, primary_key=True)
    local_user_id = sql.Column(sql.Integer, sql.ForeignKey('local_user.id',
                               ondelete='CASCADE'))
    password = sql.Column(sql.String(128), nullable=True)
    # created_at default set here to safe guard in case it gets missed
    created_at = sql.Column(sql.DateTime, nullable=False,
                            default=datetime.datetime.utcnow)
    expires_at = sql.Column(sql.DateTime, nullable=True)
Example #27
0
class FederationProtocolModel(sql.ModelBase, sql.DictBase):
    __tablename__ = 'federation_protocol'
    attributes = ['id', 'idp_id', 'mapping_id']
    mutable_attributes = frozenset(['mapping_id'])

    id = sql.Column(sql.String(64), primary_key=True)
    idp_id = sql.Column(sql.String(64), sql.ForeignKey('identity_provider.id',
                        ondelete='CASCADE'), primary_key=True)
    mapping_id = sql.Column(sql.String(64), nullable=False)

    @classmethod
    def from_dict(cls, dictionary):
        new_dictionary = dictionary.copy()
        return cls(**new_dictionary)

    def to_dict(self):
        """Return a dictionary with model's attributes."""
        d = dict()
        for attr in self.__class__.attributes:
            d[attr] = getattr(self, attr)
        return d
Example #28
0
class IdentityProviderModel(sql.ModelBase, sql.DictBase):
    __tablename__ = 'identity_provider'
    attributes = ['id', 'remote_id', 'enabled', 'description']
    mutable_attributes = frozenset(['description', 'enabled', 'remote_id'])

    id = sql.Column(sql.String(64), primary_key=True)
    remote_id = sql.Column(sql.String(256), nullable=True)
    enabled = sql.Column(sql.Boolean, nullable=False)
    description = sql.Column(sql.Text(), nullable=True)

    @classmethod
    def from_dict(cls, dictionary):
        new_dictionary = dictionary.copy()
        return cls(**new_dictionary)

    def to_dict(self):
        """Return a dictionary with model's attributes."""
        d = dict()
        for attr in self.__class__.attributes:
            d[attr] = getattr(self, attr)
        return d
Example #29
0
class Service(sql.ModelBase, sql.DictBase):
    __tablename__ = 'service'
    id = sql.Column(sql.String(64), primary_key=True)
    type = sql.Column(sql.String(255))
    extra = sql.Column(sql.JsonBlob())

    @classmethod
    def from_dict(cls, service_dict):
        extra = {}
        for k, v in service_dict.copy().iteritems():
            if k not in ['id', 'type', 'extra']:
                extra[k] = service_dict.pop(k)

        service_dict['extra'] = extra
        return cls(**service_dict)

    def to_dict(self):
        extra_copy = self.extra.copy()
        extra_copy['id'] = self.id
        extra_copy['type'] = self.type
        return extra_copy
Example #30
0
class SystemRoleAssignment(sql.ModelBase, sql.ModelDictMixin):
    __tablename__ = 'system_assignment'
    attributes = ['type', 'actor_id', 'target_id', 'role_id', 'inherited']
    type = sql.Column(sql.String(64), nullable=False)
    actor_id = sql.Column(sql.String(64), nullable=False)
    target_id = sql.Column(sql.String(64), nullable=False)
    role_id = sql.Column(sql.String(64), nullable=False)
    inherited = sql.Column(sql.Boolean, default=False, nullable=False)
    __table_args__ = (
        sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', 'role_id',
                                 'inherited'),
        sql.Index('ix_system_actor_id', 'actor_id'),
    )

    def to_dict(self):
        """Override parent method with a simpler implementation.

        RoleAssignment doesn't have non-indexed 'extra' attributes, so the
        parent implementation is not applicable.
        """
        return dict(self.items())