Skip to content

Commit

Permalink
Core/Organization refactoring (#989)
Browse files Browse the repository at this point in the history
### Feature or Bugfix
- Refactoring

### Detail
Adding service layer to Organizations in order to follow the
resolver-service-repository structure we established for v2.0
modularization.
Also cleanup some dead code.

### Relates
[#741 ](#741)

### Security
Please answer the questions below briefly where applicable, or write
`N/A`. Based on
[OWASP 10](https://owasp.org/Top10/en/).

- Does this PR introduce or modify any input fields or queries - this
includes
fetching data from storage outside the application (e.g. a database, an
S3 bucket)?
  - Is the input sanitized?
- What precautions are you taking before deserializing the data you
consume?
  - Is injection prevented by parametrizing queries?
  - Have you ensured no `eval` or similar functions are used?
- Does this PR introduce any functionality or component that requires
authorization?
- How have you ensured it respects the existing AuthN/AuthZ mechanisms?
  - Are you logging failed auth attempts?
- Are you using or adding any cryptographic features?
  - Do you use a standard proven implementations?
  - Are the used keys controlled by the customer? Where are they stored?
- Are you introducing any new policies/roles/users?
  - Have you used the least-privilege principle? How?


By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license.
  • Loading branch information
dbalintx authored Jan 23, 2024
1 parent b8b8d23 commit a764c4a
Show file tree
Hide file tree
Showing 19 changed files with 340 additions and 327 deletions.
2 changes: 1 addition & 1 deletion backend/dataall/core/environment/api/resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from dataall.base.aws.parameter_store import ParameterStoreManager
from dataall.base.aws.sts import SessionHelper
from dataall.base.utils import Parameter
from dataall.core.environment.db.environment_models import EnvironmentGroup
from dataall.core.environment.db.environment_models import Environment, EnvironmentGroup
from dataall.core.environment.services.environment_resource_manager import EnvironmentResourceManager
from dataall.core.environment.services.environment_service import EnvironmentService
from dataall.core.environment.api.enums import EnvironmentPermission
Expand Down
13 changes: 13 additions & 0 deletions backend/dataall/core/environment/db/environment_repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,16 @@ def get_environment_by_uri(session, uri):
if not environment:
raise exceptions.ObjectNotFound(Environment.__name__, uri)
return environment

@staticmethod
def count_environments_with_organization_uri(session, uri):
return session.query(Environment).filter(Environment.organizationUri == uri).count()

@staticmethod
def count_environments_with_organization_and_group(session, organization, group):
return session.query(Environment).filter(
and_(
Environment.organizationUri == organization.organizationUri,
Environment.SamlGroupName == group,
)
).count()
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
)
from dataall.base.db import exceptions
from dataall.core.permissions import permissions
from dataall.core.organizations.db.organization_repositories import Organization
from dataall.core.organizations.db.organization_repositories import OrganizationRepository
from dataall.core.environment.db.environment_models import Environment, EnvironmentGroup
from dataall.core.environment.api.enums import EnvironmentPermission, EnvironmentType

Expand All @@ -42,7 +42,7 @@ class EnvironmentService:
def create_environment(session, uri, data=None):
context = get_context()
EnvironmentService._validate_creation_params(data, uri)
organization = Organization.get_organization_by_uri(session, uri)
organization = OrganizationRepository.get_organization_by_uri(session, uri)
env = Environment(
organizationUri=data.get('organizationUri'),
label=data.get('label', 'Unnamed'),
Expand Down
6 changes: 3 additions & 3 deletions backend/dataall/core/groups/api/resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dataall.base.services.service_provider_factory import ServiceProviderFactory
from dataall.core.groups.db.group_models import Group
from dataall.core.environment.services.environment_service import EnvironmentService
from dataall.core.organizations.db.organization_repositories import Organization
from dataall.core.organizations.db.organization_repositories import OrganizationRepository
from dataall.core.permissions.db.tenant_policy_repositories import TenantPolicy
from dataall.base.db import exceptions

Expand Down Expand Up @@ -61,8 +61,8 @@ def list_groups(context, source, filter: dict = None):
).all()
if category == 'organization':
with context.engine.scoped_session() as session:
organization = Organization.get_organization_by_uri(session, category_uri)
invited_groups = Organization.query_organization_groups(
organization = OrganizationRepository.get_organization_by_uri(session, category_uri)
invited_groups = OrganizationRepository.query_organization_groups(
session=session,
uri=organization.organizationUri,
filter=None,
Expand Down
18 changes: 0 additions & 18 deletions backend/dataall/core/organizations/api/input_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,6 @@ class OrganizationSortField(GraphQLEnumMapper):
],
)


OrganizationTopicFilter = gql.InputType(
name='OrganizationTopicFilter',
arguments=[
gql.Argument(name='term', type=gql.String),
gql.Argument(name='page', type=gql.Integer),
gql.Argument(name='pageSize', type=gql.Integer),
],
)

OrganizationTopicInput = gql.InputType(
name='OrganizationTopicInput',
arguments=[
gql.Argument(name='label', type=gql.String),
gql.Argument(name='description', type=gql.String),
],
)

InviteGroupToOrganizationInput = gql.InputType(
name='InviteGroupToOrganizationInput',
arguments=[
Expand Down
122 changes: 41 additions & 81 deletions backend/dataall/core/organizations/api/resolvers.py
Original file line number Diff line number Diff line change
@@ -1,123 +1,86 @@
from dataall.base.api.context import Context
from dataall.core.environment.db.environment_models import Environment
from dataall.core.organizations.api.enums import OrganisationUserRole
from dataall.core.organizations.db.organization_repositories import Organization
from dataall.base.db import exceptions
from dataall.core.organizations.db import organization_models as models
from dataall.core.organizations.services.organization_service import OrganizationService


def create_organization(context: Context, source, input=None):
with context.engine.scoped_session() as session:
organization = Organization.create_organization(
session=session,
data=input,
)
return organization
if not input:
raise exceptions.RequiredParameter(input)
if not input.get('SamlGroupName'):
raise exceptions.RequiredParameter('groupUri')
if not input.get('label'):
raise exceptions.RequiredParameter('label')

return OrganizationService.create_organization(data=input)


def update_organization(context, source, organizationUri=None, input=None):
with context.engine.scoped_session() as session:
return Organization.update_organization(
session=session,
uri=organizationUri,
data=input,
)
return OrganizationService.update_organization(
uri=organizationUri,
data=input,
)


def get_organization(context: Context, source, organizationUri=None):
with context.engine.scoped_session() as session:
return Organization.get_organization_by_uri(
session=session, uri=organizationUri
)
return OrganizationService.get_organization(uri=organizationUri)


def list_organizations(context: Context, source, filter=None):
if not filter:
filter = {'page': 1, 'pageSize': 5}

with context.engine.scoped_session() as session:
return Organization.paginated_user_organizations(
session=session,
data=filter,
)
return OrganizationService.list_organizations(filter)


def list_organization_environments(context, source, filter=None):
if not filter:
filter = {'page': 1, 'pageSize': 5}
with context.engine.scoped_session() as session:
return Organization.paginated_organization_environments(
session=session,
uri=source.organizationUri,
data=filter,
)


def stats(context, source: models.Organization, **kwargs):
with context.engine.scoped_session() as session:
environments = Organization.count_organization_environments(
session=session, uri=source.organizationUri
)
return OrganizationService.list_organization_environments(filter=filter, uri=source.organizationUri)

groups = Organization.count_organization_invited_groups(
session=session, uri=source.organizationUri, group=source.SamlGroupName
)

return {'environments': environments, 'groups': groups, 'users': 0}
def stats(context, source: models.Organization, **kwargs):
return OrganizationService.count_organization_resources(
uri=source.organizationUri,
group=source.SamlGroupName
)


def resolve_user_role(context: Context, source: models.Organization):
if source.owner == context.username:
return OrganisationUserRole.Owner.value
elif source.SamlGroupName in context.groups:
return OrganisationUserRole.Admin.value
else:
with context.engine.scoped_session() as session:
if Organization.find_organization_membership(
session=session, uri=source.organizationUri, groups=context.groups
):
return OrganisationUserRole.Invited.value
return OrganisationUserRole.NoPermission.value
return OrganizationService.resolve_user_role(organization=source)


def archive_organization(context: Context, source, organizationUri: str = None):
with context.engine.scoped_session() as session:
return Organization.archive_organization(
session=session,
uri=organizationUri,
)
return OrganizationService.archive_organization(uri=organizationUri)


def invite_group(context: Context, source, input):
with context.engine.scoped_session() as session:
organization, organization_group = Organization.invite_group(
session=session,
uri=input['organizationUri'],
data=input,
)
return organization
if not input:
raise exceptions.RequiredParameter(input)
if not input.get('groupUri'):
raise exceptions.RequiredParameter('groupUri')

return OrganizationService.invite_group(uri=input['organizationUri'], data=input)


def remove_group(context: Context, source, organizationUri=None, groupUri=None):
with context.engine.scoped_session() as session:
organization = Organization.remove_group(
session=session,
uri=organizationUri,
group=groupUri
)
return organization
return OrganizationService.remove_group(
uri=organizationUri,
group=groupUri,
)


def list_organization_groups(
context: Context, source, organizationUri=None, filter=None
):
if filter is None:
filter = {}
with context.engine.scoped_session() as session:
return Organization.paginated_organization_groups(
session=session,
uri=organizationUri,
data=filter,
)

return OrganizationService.list_organization_groups(
filter=filter,
uri=organizationUri
)


def resolve_organization_by_env(context, source, **kwargs):
Expand All @@ -126,8 +89,5 @@ def resolve_organization_by_env(context, source, **kwargs):
"""
if not source:
return None
with context.engine.scoped_session() as session:
env: Environment = session.query(Environment).get(
source.environmentUri
)
return session.query(models.Organization).get(env.organizationUri)

return OrganizationService.resolve_organization_by_env(uri=source.environmentUri)
Loading

0 comments on commit a764c4a

Please sign in to comment.