Skip to content

Commit 9318aa3

Browse files
authored
Merge pull request #143 from ioet/fix/return-all-time-metries-range-time#122
Fix/return all time entries range time#122
2 parents 56af879 + e877315 commit 9318aa3

File tree

7 files changed

+85
-35
lines changed

7 files changed

+85
-35
lines changed

commons/data_access_layer/cosmos_db.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -222,17 +222,8 @@ def find(
222222
function_mapper = self.get_mapper_or_dict(mapper)
223223
return function_mapper(self.check_visibility(found_item, visible_only))
224224

225-
def find_all(
226-
self,
227-
event_context: EventContext,
228-
conditions: dict = {},
229-
custom_sql_conditions: List[str] = [],
230-
custom_params: dict = {},
231-
max_count=None,
232-
offset=0,
233-
visible_only=True,
234-
mapper: Callable = None,
235-
):
225+
def find_all(self, event_context: EventContext, conditions: dict = {}, custom_sql_conditions: List[str] = [],
226+
custom_params: dict = {}, max_count=None, offset=0, visible_only=True, mapper: Callable = None):
236227
partition_key_value = self.find_partition_key_value(event_context)
237228
max_count = self.get_page_size_or(max_count)
238229
params = [
@@ -242,8 +233,7 @@ def find_all(
242233
]
243234
params.extend(self.generate_params(conditions))
244235
params.extend(custom_params)
245-
result = self.container.query_items(
246-
query="""
236+
query_str = """
247237
SELECT * FROM c
248238
WHERE c.{partition_key_attribute}=@partition_key_value
249239
{conditions_clause}
@@ -261,7 +251,10 @@ def find_all(
261251
custom_sql_conditions
262252
),
263253
order_clause=self.create_sql_order_clause(),
264-
),
254+
)
255+
256+
result = self.container.query_items(
257+
query=query_str,
265258
parameters=params,
266259
partition_key=partition_key_value,
267260
max_item_count=max_count,

commons/data_access_layer/database.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def delete(self, id):
3333
raise NotImplementedError # pragma: no cover
3434

3535

36-
class EventContext():
36+
class EventContext:
3737
def __init__(self, container_id: str, action: str, description: str = None,
3838
user_id: str = None, tenant_id: str = None, session_id: str = None,
3939
app_id: str = None):

time_tracker_api/database.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from commons.data_access_layer.cosmos_db import CosmosDBDao
1313
from commons.data_access_layer.database import EventContext
14-
from time_tracker_api.security import current_user_id, current_user_tenant_id
14+
from time_tracker_api.security import current_user_id, current_user_tenant_id, current_role_user, roles
1515

1616

1717
class CRUDDao(abc.ABC):
@@ -37,10 +37,11 @@ def delete(self, id):
3737

3838

3939
class ApiEventContext(EventContext):
40-
def __init__(self, container_id: str, action: str, description: str = None,
41-
user_id: str = None, tenant_id: str = None, session_id: str = None):
40+
def __init__(self, container_id: str, action: str, description: str = None, user_id: str = None,
41+
tenant_id: str = None, session_id: str = None, user_role: str = None):
4242
super(ApiEventContext, self).__init__(container_id, action, description)
4343
self._user_id = user_id
44+
self._user_role = user_role
4445
self._tenant_id = tenant_id
4546
self._session_id = session_id
4647

@@ -50,6 +51,10 @@ def user_id(self) -> str:
5051
self._user_id = current_user_id()
5152
return self._user_id
5253

54+
@property
55+
def user_role(self) -> str:
56+
return self._user_role if self._user_role else current_role_user()
57+
5358
@property
5459
def tenant_id(self) -> str:
5560
if self._tenant_id is None:
@@ -60,6 +65,10 @@ def tenant_id(self) -> str:
6065
def session_id(self) -> str:
6166
return self._session_id
6267

68+
@property
69+
def is_admin(self):
70+
return True if self.user_role == roles.get("admin").get("name") else False
71+
6372

6473
class APICosmosDBDao(CosmosDBDao):
6574
def create_event_context(self, action: str = None, description: str = None):

time_tracker_api/projects/projects_model.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ def get_all(self, conditions: dict = None, **kwargs) -> list:
7373
customers_id = [customer.id for customer in customers]
7474
conditions = conditions if conditions else {}
7575
custom_condition = "c.customer_id IN {}".format(str(tuple(customers_id)))
76-
return self.repository.find_all(event_ctx, conditions, custom_sql_conditions=[custom_condition], **kwargs)
76+
if "custom_sql_conditions" in kwargs:
77+
kwargs["custom_sql_conditions"].append(custom_condition)
78+
else:
79+
kwargs["custom_sql_conditions"] = [custom_condition]
80+
return self.repository.find_all(event_ctx, conditions, **kwargs)
7781

7882

7983
def create_dao() -> ProjectDao:

time_tracker_api/security.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929

3030
iss_claim_pattern = re.compile(r"(.*).b2clogin.com/(?P<tenant_id>%s)" % UUID_REGEX)
3131

32+
roles = {
33+
"admin": {"name": "time-tracker-admin"},
34+
"client": {"name": "client-role"}
35+
}
36+
3237

3338
def current_user_id() -> str:
3439
oid_claim = get_token_json().get("oid")
@@ -38,6 +43,11 @@ def current_user_id() -> str:
3843
return oid_claim
3944

4045

46+
def current_role_user() -> str:
47+
role_user = get_token_json().get("extension_role", None)
48+
return role_user if role_user else roles.get("client").get("name")
49+
50+
4151
def current_user_tenant_id() -> str:
4252
iss_claim = get_token_json().get("iss")
4353
if iss_claim is None:

time_tracker_api/time_entries/time_entries_model.py

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from time_tracker_api.time_entries.custom_modules.utils import (
2222
add_project_name_to_time_entries,
2323
)
24+
from time_tracker_api.projects.projects_model import ProjectCosmosDBModel, create_dao as project_create_dao
2425
from time_tracker_api.projects import projects_model
2526
from time_tracker_api.database import CRUDDao, APICosmosDBDao
2627
from time_tracker_api.security import current_user_id
@@ -74,6 +75,14 @@ def __init__(self, data): # pragma: no cover
7475
def running(self):
7576
return self.end_date is None
7677

78+
def __add__(self, other):
79+
if type(other) is ProjectCosmosDBModel:
80+
time_entry = self.__class__
81+
time_entry.project_id = other.__dict__
82+
return time_entry
83+
else:
84+
raise NotImplementedError
85+
7786
def __repr__(self):
7887
return '<Time Entry %r>' % self.start_date # pragma: no cover
7988

@@ -116,21 +125,31 @@ def find_all(
116125
conditions: dict = {},
117126
date_range: dict = {},
118127
):
119-
custom_sql_conditions = []
120-
custom_sql_conditions.append(
121-
self.create_sql_date_range_filter(date_range)
122-
)
128+
custom_sql_conditions = [self.create_sql_date_range_filter(date_range)]
123129

124-
custom_params = self.generate_params(date_range)
130+
if event_context.is_admin:
131+
conditions.pop("owner_id")
132+
# TODO should be removed when implementing a role-based permission module ↑
125133

126-
return CosmosDBRepository.find_all(
134+
custom_params = self.generate_params(date_range)
135+
time_entries = CosmosDBRepository.find_all(
127136
self,
128137
event_context=event_context,
129138
conditions=conditions,
130139
custom_sql_conditions=custom_sql_conditions,
131140
custom_params=custom_params,
132141
)
133142

143+
if time_entries:
144+
projects_id = [project.project_id for project in time_entries]
145+
p_ids = str(tuple(projects_id)).replace(",", "") if len(projects_id) == 1 else str(tuple(projects_id))
146+
custom_conditions = "c.id IN {}".format(p_ids)
147+
# TODO this must be refactored to be used from the utils module ↑
148+
project_dao = projects_model.create_dao()
149+
projects = project_dao.get_all(custom_sql_conditions=[custom_conditions])
150+
add_project_name_to_time_entries(time_entries, projects)
151+
return time_entries
152+
134153
def on_create(self, new_item_data: dict, event_context: EventContext):
135154
CosmosDBRepository.on_create(self, new_item_data, event_context)
136155

@@ -282,19 +301,12 @@ def checks_owner_and_is_not_started(cls, data: dict):
282301
"The specified time entry is already running",
283302
)
284303

285-
def get_all(self, conditions: dict = {}) -> list:
304+
def get_all(self, conditions: dict = None, **kwargs) -> list:
286305
event_ctx = self.create_event_context("read-many")
287306
conditions.update({"owner_id": event_ctx.user_id})
288307

289308
date_range = self.handle_date_filter_args(args=conditions)
290-
time_entries = self.repository.find_all(
291-
event_ctx, conditions=conditions, date_range=date_range
292-
)
293-
294-
project_dao = projects_model.create_dao()
295-
projects = project_dao.get_all()
296-
add_project_name_to_time_entries(time_entries, projects)
297-
return time_entries
309+
return self.repository.find_all(event_ctx, conditions=conditions, date_range=date_range)
298310

299311
def get(self, id):
300312
event_ctx = self.create_event_context("read")
@@ -366,19 +378,26 @@ def get_worked_time(self, conditions: dict = {}):
366378

367379
@staticmethod
368380
def handle_date_filter_args(args: dict) -> dict:
381+
date_range = None
369382
if 'month' and 'year' in args:
370383
month = int(args.get("month"))
371384
year = int(args.get("year"))
372385
args.pop('month')
373386
args.pop('year')
387+
elif "start_date" and "end_date" in args:
388+
date_range = args.copy()
389+
if "owner_id" in date_range:
390+
date_range.pop("owner_id")
391+
args.pop("start_date")
392+
args.pop("end_date")
374393
elif 'month' in args:
375394
month = int(args.get("month"))
376395
year = get_current_year()
377396
args.pop('month')
378397
else:
379398
month = get_current_month()
380399
year = get_current_year()
381-
return get_date_range_of_month(year, month)
400+
return date_range if date_range else get_date_range_of_month(year, month)
382401

383402

384403
def create_dao() -> TimeEntriesDao:

time_tracker_api/time_entries/time_entries_namespace.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,21 @@
151151
location='args',
152152
)
153153

154+
attributes_filter.add_argument(
155+
'start_date',
156+
required=False,
157+
store_missing=False,
158+
help="(Filter) Start to filter by",
159+
location='args',
160+
)
161+
attributes_filter.add_argument(
162+
'end_date',
163+
required=False,
164+
store_missing=False,
165+
help="(Filter) End time to filter by",
166+
location='args',
167+
)
168+
154169

155170
@ns.route('')
156171
class TimeEntries(Resource):

0 commit comments

Comments
 (0)