-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DA v2: Modularized structure of feeds and votes (#735)
### Feature or Bugfix - Refactoring ### Detail - Adjust `feed` module to the new code layer design - Adjust `vote` module to the new code layer design - Clean up unused code ### Relates - V2.0 ### Security Please answer the questions below briefly where applicable, or write `N/A`. Based on [OWASP 10](https://owasp.org/Top10/en/). `N/A` - 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
Showing
17 changed files
with
248 additions
and
137 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,50 @@ | ||
from sqlalchemy import or_ | ||
|
||
from dataall.base.api.context import Context | ||
from dataall.base.db import paginate | ||
from dataall.base.db import exceptions | ||
from dataall.modules.feed.api.registry import FeedRegistry | ||
from dataall.modules.feed.db.feed_models import FeedMessage | ||
|
||
|
||
class Feed: | ||
def __init__(self, targetUri: str = None, targetType: str = None): | ||
self._targetUri = targetUri | ||
self._targetType = targetType | ||
|
||
@property | ||
def targetUri(self): | ||
return self._targetUri | ||
from dataall.modules.feed.services.feed_service import Feed, FeedService | ||
|
||
@property | ||
def targetType(self): | ||
return self._targetType | ||
|
||
|
||
def resolve_feed_target_type(obj, *_): | ||
return FeedRegistry.find_target(obj) | ||
def _required_uri(uri): | ||
if not uri: | ||
raise exceptions.RequiredParameter('URI') | ||
|
||
|
||
def resolve_target(context: Context, source: Feed, **kwargs): | ||
if not source: | ||
return None | ||
with context.engine.scoped_session() as session: | ||
model = FeedRegistry.find_model(source.targetType) | ||
target = session.query(model).get(source.targetUri) | ||
return target | ||
def _required_type(type): | ||
if not type: | ||
raise exceptions.RequiredParameter('TargetType') | ||
|
||
|
||
def get_feed( | ||
context: Context, | ||
source, | ||
targetUri: str = None, | ||
targetType: str = None, | ||
filter: dict = None, | ||
) -> Feed: | ||
return Feed(targetUri=targetUri, targetType=targetType) | ||
): | ||
_required_uri(targetUri) | ||
_required_type(targetType) | ||
return FeedService.get_feed(targetUri=targetUri, targetType=targetType) | ||
|
||
|
||
def post_message( | ||
def post_feed_message( | ||
context: Context, | ||
source, | ||
targetUri: str = None, | ||
targetType: str = None, | ||
input: dict = None, | ||
): | ||
with context.engine.scoped_session() as session: | ||
m = FeedMessage( | ||
targetUri=targetUri, | ||
targetType=targetType, | ||
creator=context.username, | ||
content=input.get('content'), | ||
) | ||
session.add(m) | ||
return m | ||
return FeedService.post_feed_message( | ||
targetUri=targetUri, | ||
targetType=targetType, | ||
content=input.get('content') | ||
) | ||
|
||
|
||
def resolve_feed_target_type(obj, *_): | ||
return FeedRegistry.find_target(obj) | ||
|
||
|
||
def resolve_messages(context: Context, source: Feed, filter: dict = None): | ||
if not source: | ||
return None | ||
def resolve_feed_messages(context: Context, source: Feed, filter: dict = None): | ||
_required_uri(source.targetUri) | ||
if not filter: | ||
filter = {} | ||
with context.engine.scoped_session() as session: | ||
q = session.query(FeedMessage).filter( | ||
FeedMessage.targetUri == source.targetUri | ||
) | ||
term = filter.get('term') | ||
if term: | ||
q = q.filter( | ||
or_( | ||
FeedMessage.content.ilike('%' + term + '%'), | ||
FeedMessage.creator.ilike('%' + term + '%'), | ||
) | ||
) | ||
q = q.order_by(FeedMessage.created.desc()) | ||
|
||
return paginate( | ||
q, page=filter.get('page', 1), page_size=filter.get('pageSize', 10) | ||
).to_dict() | ||
return FeedService.list_feed_messages(targetUri=source.targetUri, filter=filter) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
""" | ||
DAO layer that encapsulates the logic and interaction with the database for Feeds | ||
Provides the API to retrieve / update / delete FeedS | ||
""" | ||
from sqlalchemy import or_ | ||
|
||
from dataall.base.db import paginate | ||
from dataall.modules.feed.db.feed_models import FeedMessage | ||
|
||
|
||
class FeedRepository: | ||
def __init__(self, session): | ||
self._session = session | ||
|
||
def paginated_feed_messages(self, uri, filter): | ||
q = self._session.query(FeedMessage).filter( | ||
FeedMessage.targetUri == uri | ||
) | ||
term = filter.get('term') | ||
if term: | ||
q = q.filter( | ||
or_( | ||
FeedMessage.content.ilike('%' + term + '%'), | ||
FeedMessage.creator.ilike('%' + term + '%'), | ||
) | ||
) | ||
q = q.order_by(FeedMessage.created.desc()) | ||
|
||
return paginate( | ||
q, page=filter.get('page', 1), page_size=filter.get('pageSize', 10) | ||
).to_dict() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
""" | ||
Contains the code needed for service layer. | ||
The service layer is a layer where all business logic is aggregated | ||
""" | ||
from dataall.modules.feed.services import feed_service | ||
|
||
__all__ = ["feed_service"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
""" | ||
A service layer for Feeds | ||
Central part for working with Feeds | ||
""" | ||
import logging | ||
|
||
from dataall.base.context import get_context | ||
from dataall.modules.feed.db.feed_models import FeedMessage | ||
from dataall.modules.feed.db.feed_repository import FeedRepository | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class Feed: | ||
def __init__(self, targetUri: str = None, targetType: str = None): | ||
self._targetUri = targetUri | ||
self._targetType = targetType | ||
|
||
@property | ||
def targetUri(self): | ||
return self._targetUri | ||
|
||
@property | ||
def targetType(self): | ||
return self._targetType | ||
|
||
|
||
def _session(): | ||
return get_context().db_engine.scoped_session() | ||
|
||
|
||
class FeedService: | ||
""" | ||
Encapsulate the logic of interactions with Feeds. | ||
""" | ||
|
||
@staticmethod | ||
def get_feed( | ||
targetUri: str = None, | ||
targetType: str = None, | ||
) -> Feed: | ||
return Feed(targetUri=targetUri, targetType=targetType) | ||
|
||
@staticmethod | ||
def post_feed_message( | ||
targetUri: str = None, | ||
targetType: str = None, | ||
content: str = None, | ||
): | ||
with _session() as session: | ||
m = FeedMessage( | ||
targetUri=targetUri, | ||
targetType=targetType, | ||
creator=get_context().username, | ||
content=content, | ||
) | ||
session.add(m) | ||
return m | ||
|
||
@staticmethod | ||
def list_feed_messages(targetUri: str, filter: dict = None): | ||
with _session() as session: | ||
return FeedRepository(session).paginated_feed_messages(uri=targetUri, filter=filter) |
Oops, something went wrong.