Auto generate urls with customer ids

This commit is contained in:
2024-05-11 20:35:06 +02:00
parent 5a854279b1
commit 80c2c6b0b8
4 changed files with 72 additions and 45 deletions

View File

@@ -1,14 +1,15 @@
import os import os
import json import json
import boto3 import boto3
from typing import Dict, Optional from uuid import uuid4
from pydantic import BaseModel from pydantic import BaseModel
from typing import Dict, Optional
from redirects_base import Content, Customer, Redirects, Tag from redirects_base import Content, Customer, Redirects, Tag
s3_client = None s3_client = None
bucket_config = '' bucket_config = ''
bucket_data = '' bucket_data = ''
function_url = ''
class S3Bucket(BaseModel): class S3Bucket(BaseModel):
name: str name: str
@@ -33,12 +34,13 @@ class Record(BaseModel):
s3: S3Event s3: S3Event
def lambda_handler(event: dict, context): 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: if s3_client is None:
print("Init Function") print("Init Function")
bucket_config = os.environ.get('BUCKET_CONFIG', 'standout-config') bucket_config = os.environ.get('BUCKET_CONFIG', 'standout-config')
bucket_data = os.environ.get('BUCKET_DATA', 'standout-data') 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 Config: {bucket_config}')
print(f' Bucket Data: {bucket_data}') print(f' Bucket Data: {bucket_data}')
s3_client = boto3.client('s3') s3_client = boto3.client('s3')
@@ -76,39 +78,7 @@ def lambda_handler(event: dict, context):
processAdd(record=record, redirects=redirects, client=s3_client) processAdd(record=record, redirects=redirects, client=s3_client)
case "ObjectRemoved:Delete": case "ObjectRemoved:Delete":
keys = getObjectKeys(record=record) processDelete(record=record, redirects=redirects)
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}")
case "ObjectCreated:Copy": case "ObjectCreated:Copy":
print(f"Object copy: {record.s3.object.key}") print(f"Object copy: {record.s3.object.key}")
@@ -137,14 +107,17 @@ def processAdd(record: Record, redirects: Redirects, client) -> None:
keys = getObjectKeys(record=record) keys = getObjectKeys(record=record)
# crea il primo utente se necessario o selezionalo # 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: if redirects.customers is None:
redirects.customers = {cust_key: Customer(status="active", tags=None)} redirects.customers = {cust_id: Customer(name=cust_name, status="active", tags=None)}
if cust_key not in redirects.customers.keys(): if cust_id 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)
# Aggiunto solo un cliente # Aggiunto solo un cliente
c = redirects.customers[cust_key] c = redirects.customers[cust_id]
if len(keys) == 0 or not c: if len(keys) == 0 or not c:
return return
@@ -164,24 +137,75 @@ def processAdd(record: Record, redirects: Redirects, client) -> None:
file_name = keys[0] file_name = keys[0]
if file_name == "url.txt": if file_name == "url.txt":
with client.get_object(Bucket=bucket_data, Key=record.s3.object.key)['Body'] as url_file: 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: 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 # Aggiungi il contenuto a una faccia o al tag a seconda della lunghezza del path
match len(keys): match len(keys):
case 2: case 2:
content.tag_url = generateTagUrl(cust_id, tag_key, face_id=keys[1])
if t.content is None or isinstance(t.content, Content): if t.content is None or isinstance(t.content, Content):
t.content = {keys[1]: content} t.content = {keys[1]: content}
elif isinstance(t.content, dict): elif isinstance(t.content, dict):
t.content[keys[1]] = content t.content[keys[1]] = content
case 1: case 1:
content.tag_url = generateTagUrl(cust_id, tag_key, None)
t.content = content t.content = content
case _: case _:
print("Too long keys") print("Too long keys")
print(f"ObjectCreated: {record.s3.object.key}") 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__": if __name__ == "__main__":
with open('/home/emanuele/dev/StandOut/lambda_config/test.json', 'r') as f: with open('/home/emanuele/dev/StandOut/lambda_config/test.json', 'r') as f:

View File

@@ -4,7 +4,8 @@ from pydantic import BaseModel
class Content(BaseModel): class Content(BaseModel):
type: str type: str
key: str key: str
url: Optional[str | None] url: Optional[str]
tag_url: Optional[str]
class Tag(BaseModel): class Tag(BaseModel):
status: str status: str
@@ -12,6 +13,7 @@ class Tag(BaseModel):
class Customer(BaseModel): class Customer(BaseModel):
status: str status: str
name: str
tags: Optional[Dict[str, Optional[Tag]] ] tags: Optional[Dict[str, Optional[Tag]] ]
class Redirects(BaseModel): class Redirects(BaseModel):

View File

@@ -66,7 +66,7 @@ def lambda_handler(event: dict, context):
match content.type: match content.type:
case "s3": case "s3":
file_name = content.key.replace('+',' ') # remove slugify of filename 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', final_redirect = s3_client.generate_presigned_url('get_object',
Params={'Bucket': bucket_data, Params={'Bucket': bucket_data,
'Key': key}, 'Key': key},

View File

@@ -206,6 +206,7 @@ resource "aws_lambda_function" "lambda_standout_config" {
variables = { variables = {
BUCKET_CONFIG = aws_s3_bucket.s3_standout_config.bucket, BUCKET_CONFIG = aws_s3_bucket.s3_standout_config.bucket,
BUCKET_DATA = aws_s3_bucket.s3_standout.bucket BUCKET_DATA = aws_s3_bucket.s3_standout.bucket
FUNCTION_URL = aws_apigatewayv2_stage.api_standout_lambda_stage.invoke_url
} }
} }
} }