Skip to content

Commit

Permalink
LITE-29268 User can delete or update a feed
Browse files Browse the repository at this point in the history
  • Loading branch information
jonatrios committed Feb 7, 2024
1 parent b2b4dcc commit f79752f
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 49 deletions.
2 changes: 1 addition & 1 deletion connect_bi_reporter/credentials/api/schemas.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Optional

from connect_bi_reporter.schemas import Events, NonNullSchema, ReferenceSchema
from connect_extension_utils.api.schemas import Events, NonNullSchema, ReferenceSchema


class CredentialCreateSchema(NonNullSchema):
Expand Down
14 changes: 13 additions & 1 deletion connect_bi_reporter/feeds/api/schemas.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import Optional

from connect_bi_reporter.schemas import Events, NonNullSchema, ReferenceSchema
from connect_extension_utils.api.schemas import Events, NonNullSchema, ReferenceSchema

from connect_bi_reporter.schemas import flatten


class FeedCreateSchema(NonNullSchema):
Expand Down Expand Up @@ -31,3 +33,13 @@ def map_to_feed_schema(feed):
'updated': {'at': feed.updated_at, 'by': {'id': feed.updated_by}},
},
)


class FeedUpdateSchema(NonNullSchema):
credential: Optional[ReferenceSchema]
file_name: Optional[str]
description: Optional[str]

def dict(self, *args, **kwargs):
result = super().dict(*args, **kwargs)
return flatten(result)
49 changes: 47 additions & 2 deletions connect_bi_reporter/feeds/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,19 @@
from connect_extension_utils.api.views import get_user_data_from_auth_token
from connect_extension_utils.db.models import get_db, VerboseBaseSession

from connect_bi_reporter.feeds.api.schemas import FeedCreateSchema, FeedSchema, map_to_feed_schema
from connect_bi_reporter.feeds.services import create_feed, get_feed_or_404, get_feeds
from connect_bi_reporter.feeds.api.schemas import (
FeedCreateSchema,
FeedSchema,
FeedUpdateSchema,
map_to_feed_schema,
)
from connect_bi_reporter.feeds.services import (
create_feed,
delete_feed,
get_feed_or_404,
get_feeds,
update_feed,
)
from connect_bi_reporter.feeds.validator import FeedValidator


Expand Down Expand Up @@ -63,3 +74,37 @@ def create_feed(
account_id = installation['owner']['id']
feed = create_feed(db, feed_schema, account_id, logged_user_data)
return map_to_feed_schema(feed)

@router.put(
'/feeds/{feed_id}',
summary='Update a Feed',
response_model=FeedSchema,
status_code=status.HTTP_200_OK,
)
def update_feed(
self,
feed_id: str,
feed_schema: FeedUpdateSchema,
db: VerboseBaseSession = Depends(get_db),
installation: dict = Depends(get_installation),
logger: Logger = Depends(get_logger),
request: Request = None,
):
logged_user_data = get_user_data_from_auth_token(request.headers['connect-auth'])
feed = update_feed(
db, feed_schema, installation, feed_id, logged_user_data, logger,
)
return map_to_feed_schema(feed)

@router.delete(
'/feeds/{feed_id}',
summary='Delete a Feed',
status_code=status.HTTP_204_NO_CONTENT,
)
def delete_feed(
self,
feed_id: str,
db: VerboseBaseSession = Depends(get_db),
installation: dict = Depends(get_installation),
):
delete_feed(db, installation, feed_id)
4 changes: 3 additions & 1 deletion connect_bi_reporter/feeds/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ class FeedError(ExtensionErrorBase):

ERRORS = {
0: "Report schedule `{report_schedule}` not valid for feed creation: {reason}",
1: "Credential `{credential_id}` not valid for feed creation.",
1: "Can not {action} Feed, the Credential `{credential_id}` is not valid.",
2: "Can not delete Feed `{feed_id}`, "
"is already related to Uploads `{uploads}`.",
}
44 changes: 43 additions & 1 deletion connect_bi_reporter/feeds/services.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from logging import Logger
from typing import Any, Dict

from connect_extension_utils.api.views import get_object_or_404

from connect_bi_reporter.feeds.api.schemas import FeedCreateSchema, FeedUpdateSchema
from connect_bi_reporter.feeds.errors import FeedError
from connect_bi_reporter.feeds.models import Feed
from connect_bi_reporter.feeds.api.schemas import FeedCreateSchema
from connect_bi_reporter.feeds.validator import FeedValidator


def create_feed(db, data: FeedCreateSchema, account_id: str, user: Dict[str, Any]):
Expand Down Expand Up @@ -34,3 +37,42 @@ def get_feed_or_404(db, installation: Dict[str, Any], feed_id: str):

def get_feeds(db, installation: Dict[str, Any]):
return db.query(Feed).filter_by(account_id=installation['owner']['id']).all()


def update_feed(
db,
data: FeedUpdateSchema,
installation: Dict[str, Any],
feed_id: str,
user: Dict[str, str],
logger: Logger,
):
feed = get_feed_or_404(db, installation, feed_id)
update_dict = data.dict()
if update_dict:
if data.credential:
FeedValidator.validate_credential(db, None, installation, data, logger, action='update')
for k, v in update_dict.items():
setattr(feed, k, v)
feed.updated_by = user['id']
db.commit()
db.refresh(feed)
return feed


def delete_feed(
db,
installation: Dict[str, Any],
feed_id: str,
):
feed = get_feed_or_404(db, installation, feed_id)
related_uploads = feed.upload.all()
if related_uploads:
raise FeedError.RF_002(
format_kwargs={
'feed_id': feed.id,
'uploads': ', '.join(upload.id for upload in related_uploads),
},
)
db.delete(feed)
db.commit()
6 changes: 5 additions & 1 deletion connect_bi_reporter/feeds/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,15 @@ def validate_credential(cls, *args, **kwargs):
installation = args[2]
feed_schema = args[3]
logger = args[4]
action = kwargs.pop('action', 'create')
cred = db.query(Credential).filter(
Credential.account_id == installation['owner']['id'],
Credential.id == feed_schema.credential.id,
).one_or_none()
if not cred:
exc = FeedError.RF_001(format_kwargs={'credential_id': feed_schema.credential.id})
exc = FeedError.RF_001(format_kwargs={
'credential_id': feed_schema.credential.id,
'action': action,
})
logger.warning(exc.message)
raise exc
60 changes: 20 additions & 40 deletions connect_bi_reporter/schemas.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,26 @@
from datetime import datetime
from typing import Dict, Optional, Union
from typing import Any, Dict

from pydantic import BaseModel, root_validator

_By = Optional[Union[str, Dict[str, str]]]
Events = Dict[str, Dict[str, Union[datetime, _By]]]


def clean_empties_from_dict(data):
def flatten(d: Dict[Any, Any], parent=True):
"""
Removes inplace all the fields that are None or empty dicts in data.
Returns param data, that was modified inplace.
If the param is not a dict, will return the param unmodified.
Transform nested dict to flat.
Optionally can preserve parent key within the child.
If use `parent=False`repeated inner keys will update the value
of outter.
:param data: dict
:rtype: dict
"""
if not isinstance(data, dict):
return data

for key in list(data.keys()):
value = data[key]
if isinstance(value, dict):
clean_empties_from_dict(value)
value = data[key]
if not value:
del data[key]
return data


class NonNullSchema(BaseModel):
def dict(self, *args, **kwargs):
kwargs['exclude_none'] = True
return super().dict(*args, **kwargs)

@root_validator(pre=True)
def validate_events(cls, values):
events = values.get('events')
if events:
values['events'] = clean_empties_from_dict(events)
return values


class ReferenceSchema(NonNullSchema):
id: str
name: Optional[str]
out = {}
for key, val in d.items():
if isinstance(val, dict):
val = [val]
if isinstance(val, list):
for subdict in val:
deeper = flatten(subdict, parent=parent).items()
out.update(
{key + '_' + key2: val2 for key2, val2 in deeper}
if parent else dict(deeper),
)
else:
out[key] = val
return out
Loading

0 comments on commit f79752f

Please sign in to comment.