From 80c2c6b0b8ceb4afe19a562e70ab0f1c1f68f84d Mon Sep 17 00:00:00 2001 From: Emanuele Date: Sat, 11 May 2024 20:35:06 +0200 Subject: [PATCH] Auto generate urls with customer ids --- lambda_config/lambda_config.py | 110 ++++++++++++++++++----------- lambda_config/redirects_base.py | 4 +- lambda_redirect/lambda_redirect.py | 2 +- master.tf | 1 + 4 files changed, 72 insertions(+), 45 deletions(-) diff --git a/lambda_config/lambda_config.py b/lambda_config/lambda_config.py index 0c30e60..e76aa4a 100644 --- a/lambda_config/lambda_config.py +++ b/lambda_config/lambda_config.py @@ -1,14 +1,15 @@ import os import json import boto3 -from typing import Dict, Optional +from uuid import uuid4 from pydantic import BaseModel +from typing import Dict, Optional from redirects_base import Content, Customer, Redirects, Tag s3_client = None bucket_config = '' bucket_data = '' - +function_url = '' class S3Bucket(BaseModel): name: str @@ -33,12 +34,13 @@ class Record(BaseModel): s3: S3Event def lambda_handler(event: dict, context): - global s3_client, bucket_config, bucket_data + global s3_client, bucket_config, bucket_data, function_url if s3_client is None: print("Init Function") bucket_config = os.environ.get('BUCKET_CONFIG', 'standout-config') bucket_data = os.environ.get('BUCKET_DATA', 'standout-data') + function_url = os.environ.get('FUNCTION_URL', 'https://api.standout.it/dev') print(f'Bucket Config: {bucket_config}') print(f' Bucket Data: {bucket_data}') s3_client = boto3.client('s3') @@ -76,39 +78,7 @@ def lambda_handler(event: dict, context): processAdd(record=record, redirects=redirects, client=s3_client) case "ObjectRemoved:Delete": - keys = getObjectKeys(record=record) - - if not redirects.customers: - return False - cust_key = keys.pop() - customer = redirects.customers.get(cust_key, None) - if len(keys) == 0 or not customer: - redirects.customers.pop(cust_key, None) - break - - if not customer.tags: - return False - tag_key = keys.pop() - tag = customer.tags.get(tag_key, None) - if len(keys) == 0 or not tag: - customer.tags.pop(tag_key, None) - break - - match len(keys): - case 2: - if not tag.content or not isinstance(tag.content, Dict): - return False - tag.content.pop(keys[1], None) - case 1: - if isinstance(tag.content, Dict) and keys[0] in tag.content.keys(): - tag.content[keys[0]] = None - else: - tag.content = None - case _: - print("Unexpected") - return False - - print(f"Object remove: {record.s3.object.key}") + processDelete(record=record, redirects=redirects) case "ObjectCreated:Copy": print(f"Object copy: {record.s3.object.key}") @@ -137,14 +107,17 @@ def processAdd(record: Record, redirects: Redirects, client) -> None: keys = getObjectKeys(record=record) # crea il primo utente se necessario o selezionalo - cust_key = keys.pop() + cust_name = keys.pop() + cust_id = searchCustomerKey(redirects=redirects, cust_name=cust_name, default=uuid4().hex) + assert(cust_id is not None) # uuid cannot return none + if redirects.customers is None: - redirects.customers = {cust_key: Customer(status="active", tags=None)} - if cust_key not in redirects.customers.keys(): - redirects.customers[cust_key] = Customer(status="active", tags=None) + redirects.customers = {cust_id: Customer(name=cust_name, status="active", tags=None)} + if cust_id not in redirects.customers.keys(): + redirects.customers[cust_id] = Customer(name=cust_name, status="active", tags=None) # Aggiunto solo un cliente - c = redirects.customers[cust_key] + c = redirects.customers[cust_id] if len(keys) == 0 or not c: return @@ -164,24 +137,75 @@ def processAdd(record: Record, redirects: Redirects, client) -> None: file_name = keys[0] if file_name == "url.txt": with client.get_object(Bucket=bucket_data, Key=record.s3.object.key)['Body'] as url_file: - content = Content(type='url', key=file_name, url=url_file.readline().decode().strip()) + content = Content(type='url', key=file_name, url=url_file.readline().decode().strip(), tag_url=None) else: - content = Content(type='s3', key=file_name, url=None) + content = Content(type='s3', key=file_name, url=None, tag_url=None) # Aggiungi il contenuto a una faccia o al tag a seconda della lunghezza del path match len(keys): case 2: + content.tag_url = generateTagUrl(cust_id, tag_key, face_id=keys[1]) if t.content is None or isinstance(t.content, Content): t.content = {keys[1]: content} elif isinstance(t.content, dict): t.content[keys[1]] = content case 1: + content.tag_url = generateTagUrl(cust_id, tag_key, None) t.content = content case _: print("Too long keys") print(f"ObjectCreated: {record.s3.object.key}") + +def generateTagUrl(cust_id: str, tag_id: str, face_id: str | None) -> str: + return f"{function_url}/api?id={cust_id}&tag_id={tag_id}{f"&face_id={face_id}" if face_id else ""}" + +def searchCustomerKey(redirects: Redirects, cust_name: str, default: str | None) -> str | None: + if redirects.customers is None: + return default + for k,v in redirects.customers.items(): + if v is not None and v.name == cust_name: + return k + return default +def processDelete(record: Record, redirects: Redirects) -> None: + keys = getObjectKeys(record=record) + + if not redirects.customers: + return + cust_name = keys.pop() + cust_key = searchCustomerKey(redirects=redirects, cust_name=cust_name, default=None) + if cust_key is None: + return + + customer = redirects.customers.get(cust_key, None) + if len(keys) == 0 or not customer: + redirects.customers.pop(cust_key, None) + return + + if not customer.tags: + return + tag_key = keys.pop() + tag = customer.tags.get(tag_key, None) + if len(keys) == 0 or not tag: + customer.tags.pop(tag_key, None) + return + + match len(keys): + case 2: + if not tag.content or not isinstance(tag.content, Dict): + return + tag.content.pop(keys[1], None) + case 1: + if isinstance(tag.content, Dict) and keys[0] in tag.content.keys(): + tag.content[keys[0]] = None + else: + tag.content = None + case _: + print("Unexpected") + return + + print(f"Object remove: {record.s3.object.key}") if __name__ == "__main__": with open('/home/emanuele/dev/StandOut/lambda_config/test.json', 'r') as f: diff --git a/lambda_config/redirects_base.py b/lambda_config/redirects_base.py index ca4d8cb..996a380 100644 --- a/lambda_config/redirects_base.py +++ b/lambda_config/redirects_base.py @@ -4,7 +4,8 @@ from pydantic import BaseModel class Content(BaseModel): type: str key: str - url: Optional[str | None] + url: Optional[str] + tag_url: Optional[str] class Tag(BaseModel): status: str @@ -12,6 +13,7 @@ class Tag(BaseModel): class Customer(BaseModel): status: str + name: str tags: Optional[Dict[str, Optional[Tag]] ] class Redirects(BaseModel): diff --git a/lambda_redirect/lambda_redirect.py b/lambda_redirect/lambda_redirect.py index 256340e..b6a1993 100644 --- a/lambda_redirect/lambda_redirect.py +++ b/lambda_redirect/lambda_redirect.py @@ -66,7 +66,7 @@ def lambda_handler(event: dict, context): match content.type: case "s3": file_name = content.key.replace('+',' ') # remove slugify of filename - key = f'{params.id}/{params.tag_id}{'/'+params.face_id if params.face_id else ''}/{file_name}' + key = f'{customer['name']}/{params.tag_id}{'/'+params.face_id if params.face_id else ''}/{file_name}' final_redirect = s3_client.generate_presigned_url('get_object', Params={'Bucket': bucket_data, 'Key': key}, diff --git a/master.tf b/master.tf index 2ea8d7e..6d80932 100644 --- a/master.tf +++ b/master.tf @@ -206,6 +206,7 @@ resource "aws_lambda_function" "lambda_standout_config" { variables = { BUCKET_CONFIG = aws_s3_bucket.s3_standout_config.bucket, BUCKET_DATA = aws_s3_bucket.s3_standout.bucket + FUNCTION_URL = aws_apigatewayv2_stage.api_standout_lambda_stage.invoke_url } } }