86 lines
3.0 KiB
Python
86 lines
3.0 KiB
Python
import json
|
|
import logging
|
|
import os
|
|
from dataclasses import dataclass
|
|
from typing import Optional
|
|
|
|
from aws_lambda_powertools import Tracer
|
|
|
|
from common.const import PERMISSION_ROLE_ALL, PERMISSION_ROLE_CREATE
|
|
from common.ddb_service.client import DynamoDbUtilsService
|
|
from common.response import bad_request, created
|
|
from libs.data_types import Role, PARTITION_KEYS
|
|
from libs.utils import get_permissions_by_username, permissions_check, response_error, get_user_name
|
|
|
|
tracer = Tracer()
|
|
user_table = os.environ.get('MULTI_USER_TABLE')
|
|
|
|
logger = logging.getLogger(__name__)
|
|
logger.setLevel(os.environ.get('LOG_LEVEL') or logging.ERROR)
|
|
|
|
ddb_service = DynamoDbUtilsService(logger=logger)
|
|
|
|
|
|
@dataclass
|
|
class UpsertRoleEvent:
|
|
role_name: str
|
|
permissions: [str]
|
|
initial: Optional[bool] = False
|
|
# todo: will be removed
|
|
creator: str = ""
|
|
|
|
|
|
@tracer.capture_lambda_handler
|
|
def handler(raw_event, ctx):
|
|
try:
|
|
logger.info(json.dumps(raw_event))
|
|
event = UpsertRoleEvent(**json.loads(raw_event['body']))
|
|
|
|
if event.initial:
|
|
username = get_user_name(raw_event)
|
|
else:
|
|
username = permissions_check(raw_event, [PERMISSION_ROLE_ALL, PERMISSION_ROLE_CREATE])
|
|
|
|
if not ctx or 'from_sd_local' not in vars(ctx):
|
|
# should check the creator permission contains role:all
|
|
creator_permissions = get_permissions_by_username(ddb_service, user_table, username)
|
|
|
|
if 'all' not in creator_permissions['role']:
|
|
target_role = _get_role_by_name(event.role_name)
|
|
if target_role and target_role.creator != username:
|
|
return bad_request(
|
|
message=f'creator {username} not have permission to update role {target_role.sort_key}')
|
|
|
|
for permission_str in event.permissions:
|
|
permission_parts = permission_str.split(':')
|
|
resource = permission_parts[0]
|
|
action = permission_parts[1]
|
|
if resource not in creator_permissions or \
|
|
('all' not in creator_permissions[resource] and action not in creator_permissions[
|
|
resource]):
|
|
return bad_request(
|
|
message=f'creator {username} have not permission to create role with permission: [{permission_str}]')
|
|
|
|
ddb_service.put_items(user_table, Role(
|
|
kind=PARTITION_KEYS.role,
|
|
sort_key=event.role_name,
|
|
permissions=event.permissions,
|
|
creator=username,
|
|
).__dict__)
|
|
|
|
return created(message='role created')
|
|
except Exception as e:
|
|
return response_error(e)
|
|
|
|
|
|
def _get_role_by_name(role_name):
|
|
role_raw = ddb_service.query_items(table=user_table, key_values={
|
|
'kind': PARTITION_KEYS.role,
|
|
'sort_key': role_name,
|
|
})
|
|
|
|
if not role_raw or len(role_raw) == 0:
|
|
return None
|
|
|
|
return Role(**(ddb_service.deserialize(role_raw)))
|