示例#1
0
class Client(ff.AggregateRoot):
    id: str = ff.id_()
    name: str = ff.required(str)
    grant_type: str = ff.required(str,
                                  validators=[
                                      ff.IsOneOf(
                                          (authorization_code, implicit,
                                           resource_owner_password_credentials,
                                           client_credentials))
                                  ])
    response_type: str = ff.optional(
        str, validators=[ff.IsOneOf(response_type_choices)])
    scopes: str = ff.required(str)
    default_redirect_uri: str = ff.required(str)
    redirect_uris: List[str] = ff.list_()
    allowed_response_types: List[str] = ff.list_(
        validators=[ff.IsOneOf(('code', 'token'))])

    def validate_redirect_uri(self, redirect_uri: str):
        return redirect_uri in self.redirect_uris

    def validate_response_type(self, response_type: str):
        return response_type in self.allowed_response_types

    def validate_scopes(self, scopes: List[str]):
        for scope in scopes:
            if scope not in self.scopes:
                return False
        return True
示例#2
0
class Table:
    entity: sql.Entity = ff.required()
    relationships: List[sql.Relationship] = ff.required()
    name: str = None
    columns: List[Column] = ff.list_()
    constraints: List = ff.list_()
    _pks: List[str] = ff.list_()

    def __post_init__(self):
        self._initialize()

    def _initialize(self):
        self.name = inflection.tableize(self.entity.entity.__name__)
        for field_ in self.entity.fields:
            st = field_.sqlalchemy_type
            if st is not None:
                self._build_regular_column(field_, st)
            elif self._needs_relation_column(field_):
                self._build_relation_column(field_)
        self._build_pk()

    def _build_pk(self):
        self.constraints.append(
            PrimaryKeyConstraint(*self._pks, name=f'{self.name}_pk'))

    def _build_regular_column(self, field_: sql.EntityField,
                              sqlalchemy_type: Type):
        args = [field_.name, sqlalchemy_type]
        kwargs = {}
        if field_.is_pk():
            self._pks.append(field_.name)

        self.columns.append(Column(*args, **kwargs))

    def _needs_relation_column(self, field_: sql.EntityField):
        r = self._find_relationship(field_)
        if r.type == sql.Relationship.ONE_TO_ONE and not r.needs_uselist:
            return False

        return not field_.is_list() and r.type != sql.Relationship.MANY_TO_MANY

    def _build_relation_column(self, field_: sql.EntityField):
        name = f'{field_.name}_id'
        setattr(self.entity.entity, name, None)
        relationship = self._find_relationship(field_)
        table_name = inflection.tableize(relationship.entity_b.entity.__name__)
        self.columns.append(
            Column(
                name, String(length=36),
                ForeignKey(
                    f'{table_name}.{relationship.entity_b.primary_key_column.name}'
                )))

    def _find_relationship(self, field_: sql.EntityField):
        for relationship in self.relationships:
            if relationship.field_a == field_:
                return relationship
        raise RuntimeError(
            f'Could not find relationship for field {field_.name}')
示例#3
0
class Audience(ff.AggregateRoot):
    id: str = ff.id_()
    name: str = ff.required()
    tenant: domain.Tenant = ff.required()
    campaigns: List[domain.Campaign] = ff.list_()
    services: list = ff.list_(validators=ff.IsOneOf((MAILCHIMP, )))
    meta: dict = ff.dict_()

    def get_campaign(self, id_: str) -> Optional[domain.Campaign]:
        for campaign in self.campaigns:
            if campaign.id == id_:
                return campaign
示例#4
0
class Group(ff.AggregateRoot):
    id: str = ff.id_()
    name: str = ff.required(str)

    users: List[str] = ff.list_()
    roles: List[str] = ff.list_()

    def assign_user_to_group(self, user_id: str):
        if user_id not in self.users:
            self.users.append(user_id)
        return 'iam.GroupAssigned', {'user_id': user_id, 'group_id': self.id}

    def remove_user_from_group(self, user_id: str):
        if user_id in self.users:
            self.users.remove(user_id)
        return 'iam.GroupRemoved', {'user_id': user_id, 'group_id': self.id}
class JoinTable:
    relationship: sql.Relationship = ff.required()
    name: str = None
    columns: List[Column] = ff.list_()
    sql_table: Table = None

    def __post_init__(self):
        self._initialize()

    def _initialize(self):
        terms = [
            inflection.tableize(self.relationship.entity_a.entity.__name__),
            inflection.tableize(self.relationship.entity_b.entity.__name__),
        ]
        terms.sort()

        self.name = f'{terms[0]}_{terms[1]}'
        self.columns.append(
            Column(self.relationship.entity_a.foreign_id_column_name,
                   String(length=36),
                   ForeignKey(self.relationship.entity_a.fk_column_string)))

        self.columns.append(
            Column(self.relationship.entity_b.foreign_id_column_name,
                   String(length=36),
                   ForeignKey(self.relationship.entity_b.fk_column_string)))

    def __eq__(self, other):
        if isinstance(other, str):
            return other == self.name
        return other.name == self.name

    def __hash__(self):
        return hash(self.name)
示例#6
0
class Project(ff.AggregateRoot):
    id: str = ff.id_(is_uuid=False)
    services: List[Service] = ff.list_()

    def plan_deployment(self, deployment: ff.Deployment,
                        config: ff.Configuration):
        project = config.all.get('project')
        aws = config.contexts.get('firefly_aws')
        try:
            api_gateway_resource = aws.get('api_gateways').get('default')
        except AttributeError:
            api_gateway_resource = None

        for s in deployment.services:
            id_ = f'{project}-{s.name}'
            service = self.get_service(id_) or Service(id=id_)
            function = service.get_lambda()

            for gateway in s.api_gateways:
                for endpoint in gateway.endpoints:
                    print(endpoint.route)

            for topic in s.network_topology.topics:
                print(f'{topic.name}:')
                for sub in topic.subscribers:
                    print(f'  {sub.name}')

    def get_service(self, id_: str):
        for s in self.services:
            if s.id == id_:
                return s
示例#7
0
class TodoList(ff.AggregateRoot,
               create_on='iam.UserCreated',
               delete_on='iam.UserDeleted'):
    id: str = ff.id_()
    user: User = ff.required()
    name: str = ff.optional()
    tasks: List[Task] = ff.list_()

    def __post_init__(self):
        if self.name is None:
            self.name = f"{self.user.name}'s TODO List"

    @ff.rest('/task', method='POST')
    def add_task(self, task: Task) -> ff.EventList:
        self.tasks.append(task)
        return 'TaskAdded', task

    def remove_task(self, task: Task):
        self.tasks.remove(task)

    def complete_task(self, task_id: str) -> ff.EventList:
        for task in self.tasks:
            if task_id == task.id:
                task.complete_task()
                return 'TaskCompleted', task
        raise Exception(f'Task {task_id} not found in TodoList {self}')
示例#8
0
class Widget(ff.AggregateRoot):
    id: str = ff.pk()
    name: str = ff.required()
    addresses: List[Address] = ff.list_()
    category: Category = None
    part: Part = None
    priority: int = ff.optional()
    deleted: bool = ff.optional(default=False)
示例#9
0
class Grant(ff.AggregateRoot):
    id: str = ff.id_()
    client_id: str = ff.required(str)
    user_id: str = ff.required(str)
    code: str = ff.required(str)
    redirect_uri: str = ff.required(str)
    scopes: List[str] = ff.list_()
    expires: datetime = ff.required(datetime)

    def validate_redirect_uri(self, redirect_uri: str):
        return self.redirect_uri == redirect_uri
示例#10
0
class Stack(ff.Entity):
    id: str = ff.id_()
    resources: List[AWSObject] = ff.list_()
    parameters: List[BaseAWSObject] = ff.list_()

    def __post_init__(self):
        for t in ['resources', 'parameters']:
            converted = []
            for resource in getattr(self, t):
                if isinstance(resource, dict) and 'module' in resource:
                    module = importlib.import_module(resource['module'])
                    type_ = module.get(resource['type'])
                    converted.append(type_.from_dict(resource['data']))
            setattr(self, t, converted)

    def to_dict(self):
        ret = {
            'id': self.id,
        }
        for t in ['resources', 'parameters']:
            ret[t] = [{
                'module': r.__class__.__module__,
                'type': r.__class__.__name__,
                'data': r.to_dict(),
            } for r in getattr(self, t)]
        return ret

    def num_resources(self):
        return len(self.resources) + len(self.parameters)

    def has_resource(self, title: str):
        for resource in self.resources:
            if resource.title == title:
                return True
        return False

    def get_resource(self, title: str):
        for resource in self.resources:
            if resource.title == title:
                return resource
示例#11
0
class Calendar(ff.AggregateRoot):
    id: str = ff.id_()
    events: List[cal.Event] = ff.list_()

    def add_event(self, event: cal.Event):
        self.events.append(event)
        self.dispatch('EventAdded', asdict(event))

    def add_reminder(self, event_id: str, reminder: cal.Reminder):
        for event in self.events:
            if event.id == event_id:
                event.reminders.append(reminder)
                self.dispatch('ReminderAdded', asdict(reminder))
示例#12
0
class Role(ff.AggregateRoot):
    id: str = ff.id_()
    name: str = ff.required(str)

    users: List[str] = ff.list_()

    def assign_role_to_user(self, user_id: str):
        if user_id not in self.users:
            self.users.append(user_id)
        return 'iam.RoleAssigned', {'user_id': user_id, 'role_id': self.id}

    def remove_role_from_user(self, user_id: str):
        if user_id in self.users:
            self.users.remove(user_id)
        return 'iam.RoleRemoved', {'user_id': user_id, 'role_id': self.id}
class Campaign(ff.Entity):
    id: str = ff.id_()
    name: str = ff.required()
    members: List[domain.AudienceMember] = ff.list_()

    def get_member_by_contact_id(self, contact_id: str):
        for member in self.members:
            if member.contact.id == contact_id:
                return member

    def add_contact(self, contact: domain.Contact, **kwargs):
        if self.get_member_by_contact_id(contact.id) is None:
            kwargs.update({'contact': contact})
            self.members.append(
                domain.AudienceMember(
                    **ff.build_argument_list(kwargs, domain.AudienceMember)))
示例#14
0
class Address(ff.AggregateRoot):
    id: str = ff.pk()
    name: str = ff.required()
    widgets: List[Widget] = ff.list_()
示例#15
0
class AudienceMember(ff.AggregateRoot):
    id: str = ff.id_()
    audience: str = ff.required()
    contact: str = ff.required()
    tags: List[str] = ff.list_()
    meta: dict = ff.dict_()
class Event(ff.Entity):
    id: str = ff.id_()
    name: str = ff.required()
    reminders: List[cal.Reminder] = ff.list_()
示例#17
0
class Category(ff.Entity):
    id: str = ff.pk()
    name: str = ff.required()
    widgets: List[Widget] = ff.list_()
示例#18
0
class Role(ff.AggregateRoot):
    id: str = ff.id_()
    name: str = ff.required(length=255, index=True)
    scopes: List[Scope] = ff.list_()
示例#19
0
class Entity:
    entity: Type[E] = ff.required()
    fields: List[sql.EntityField] = ff.list_()

    def __post_init__(self):
        annotations_ = get_type_hints(self.entity)
        for field_ in fields(self.entity):
            self.fields.append(
                sql.EntityField(entity=self,
                                field=field_,
                                annotations=annotations_))

    @property
    def type(self):
        return self.entity

    @property
    def primary_key_column(self):
        for field_ in self.fields:
            if field_.is_pk():
                return field_

    @property
    def table_name(self):
        return inflection.tableize(self.entity.__name__)

    @property
    def fk_column_string(self):
        return f'{self.table_name}.{self.primary_key_column.name}'

    @property
    def foreign_id_column_name(self):
        return f'{self.entity.__name__.lower()}_id'

    def get_field(self, name: str):
        for f in self.fields:
            if f.name == name:
                return f

    def get_relationship_fields(self) -> List[sql.EntityField]:
        ret = []
        for field_ in self.fields:
            if field_.sqlalchemy_type is None:
                ret.append(field_)
        return ret

    def add_id_column(self, field_: sql.EntityField,
                      foreign_entity: sql.Entity):
        name = f'{field_.name}_id'
        setattr(self.entity, name, None)

    def __eq__(self, other):
        try:
            if issubclass(other, ff.Entity):
                return self.entity == other
        except TypeError:
            pass

        try:
            if isinstance(other, sql.Entity):
                return self.entity == other.entity
        except TypeError:
            pass

        return False
示例#20
0
class User(ff.AggregateRoot):
    id: str = ff.id_()
    name: str = ff.required()
    email: str = ff.required(index=True)
    roles: List[Role] = ff.list_()
    special_role: Role = ff.optional()
class Widget(ff.AggregateRoot):
    stuff: List[BaseClass] = ff.list_()
示例#22
0
class ConditionSet(ff.ValueObject):
    all: bool = ff.optional(default=True)
    conditions: List[Condition] = ff.list_()
    sub_conditions: List[ConditionSet] = ff.list_()
示例#23
0
class Rule(ff.ValueObject):
    conditions: ConditionSet = ff.required()
    commands: List[Command] = ff.list_()
示例#24
0
class Mappings(ff.AggregateRoot):
    relationships: List[sql.Relationship] = ff.list_()
    tables: List[sql.Table] = ff.list_()
    join_tables: Dict[str, sql.JoinTable] = ff.dict_()
    entities: List[sql.Entity] = ff.list_()

    def initialize(self, entities: List[Type[E]]):
        for entity in entities:
            self.entities.append(sql.Entity(entity))

        for entity in self.entities:
            relationships = []
            for field_ in entity.get_relationship_fields():
                relationships.append(self._create_relationship(entity, field_))
            self.tables.append(sql.Table(entity=entity, relationships=relationships))
            self.relationships.extend(relationships)

        for r in self.relationships:
            if r.type == sql.Relationship.MANY_TO_MANY:
                jt = sql.JoinTable(r)
                if jt not in self.join_tables:
                    r.join_table = jt
                    self.join_tables[jt.name] = jt
                else:
                    r.join_table = self.join_tables[jt.name]

    def add_mappings(self, metadata):
        for table in self.join_tables.values():
            table.sql_table = Table(table.name, metadata, *table.columns)
            setattr(self, table.name, table.sql_table)

        for table in self.tables:
            sql_table = Table(table.name, metadata, *table.columns, *table.constraints)
            props = {}
            for r in table.relationships:
                if r.type == sql.Relationship.MANY_TO_MANY:
                    props[r.field_a.name] = relationship(
                        r.entity_b.entity,
                        secondary=r.join_table.sql_table,
                        back_populates=r.field_b.name,
                        cascade='all'
                    )
                else:
                    args = [r.entity_b.entity]
                    kwargs = {'cascade': 'all'}
                    if r.field_b is not None:
                        kwargs['back_populates'] = r.field_b.name
                    if r.type == sql.Relationship.ONE_TO_ONE:
                        kwargs['uselist'] = False

                    props[r.field_a.name] = relationship(*args, **kwargs)

            mapper(table.entity.entity, sql_table, properties=props, primary_key=sql_table.primary_key)

    def _create_relationship(self, entity: sql.Entity, field_: sql.EntityField):
        entity_b = None
        for e in self.entities:
            if e == field_.type():
                entity_b = e
                break

        if entity_b is None:
            raise RuntimeError(f'Entity "{field_.type().__name__}" in relationship is unmapped.')

        return sql.Relationship(
            entity_a=entity,
            field_a=field_,
            entity_b=entity_b
        )