admin key can read all images + fix env var for cloud function
This commit is contained in:
parent
f80505bd74
commit
348bcf93a7
1
deployment/terraform/.terraform.tfstate.lock.info
Normal file
1
deployment/terraform/.terraform.tfstate.lock.info
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"ID":"9b771a70-f4b7-dbb4-f919-38d27ca55e23","Operation":"OperationTypeApply","Info":"","Who":"DESKTOP\\habal@Desktop","Version":"1.10.1","Created":"2025-05-24T22:38:22.6064375Z","Path":"terraform.tfstate"}
|
||||||
@ -66,6 +66,8 @@ resource "google_cloudfunctions2_function" "image_processor" {
|
|||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
LOG_LEVEL = "INFO"
|
LOG_LEVEL = "INFO"
|
||||||
|
|
||||||
|
PROJECT_ID = var.project_id
|
||||||
}
|
}
|
||||||
|
|
||||||
service_account_email = local.cloud_function_service_account
|
service_account_email = local.cloud_function_service_account
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 4,
|
"version": 4,
|
||||||
"terraform_version": "1.10.1",
|
"terraform_version": "1.10.1",
|
||||||
"serial": 410,
|
"serial": 415,
|
||||||
"lineage": "a183cd95-f987-8698-c6dd-84e933c394a5",
|
"lineage": "a183cd95-f987-8698-c6dd-84e933c394a5",
|
||||||
"outputs": {
|
"outputs": {
|
||||||
"cloud_function_name": {
|
"cloud_function_name": {
|
||||||
@ -98,16 +98,16 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"exclude_symlink_directories": null,
|
"exclude_symlink_directories": null,
|
||||||
"excludes": null,
|
"excludes": null,
|
||||||
"id": "7a7a706b5bba3a12744f2dd109eb18de7112f351",
|
"id": "bfc4b3b9de401cd15676a09a067a8e4095b0bf4e",
|
||||||
"output_base64sha256": "0wAfDV7tH41jEspQ3LBLvIEnrQ6XU2aEtK2GWsMdyCA=",
|
"output_base64sha256": "cXx9sC1kIbTDG7BlKAtf3FUasHLZ/wZPzVoyBvt8p9Q=",
|
||||||
"output_base64sha512": "glsNAiHzSTOy9mGDckkSyDJhBVFDtLh8Xr6+hSxtCT8nok9qNGO+61iTRLU42OPxaPS/BrbDAXJeT86F3riefA==",
|
"output_base64sha512": "dcntRZ4Hz4dfBBj7YVsTzx+SEAqCXZCD8TAAh8cr5xa3uT2Lsmtf8zpxpyQEeMlsCNaF8dUohGQ7BD9LJYigPw==",
|
||||||
"output_file_mode": null,
|
"output_file_mode": null,
|
||||||
"output_md5": "a5d3a7fe131c972bf8d0edf309545042",
|
"output_md5": "46efa1aee5386e2f244b597289c7c4ba",
|
||||||
"output_path": "./function-source.zip",
|
"output_path": "./function-source.zip",
|
||||||
"output_sha": "7a7a706b5bba3a12744f2dd109eb18de7112f351",
|
"output_sha": "bfc4b3b9de401cd15676a09a067a8e4095b0bf4e",
|
||||||
"output_sha256": "d3001f0d5eed1f8d6312ca50dcb04bbc8127ad0e97536684b4ad865ac31dc820",
|
"output_sha256": "717c7db02d6421b4c31bb065280b5fdc551ab072d9ff064fcd5a3206fb7ca7d4",
|
||||||
"output_sha512": "825b0d0221f34933b2f66183724912c83261055143b4b87c5ebebe852c6d093f27a24f6a3463beeb589344b538d8e3f168f4bf06b6c301725e4fce85deb89e7c",
|
"output_sha512": "75c9ed459e07cf875f0418fb615b13cf1f92100a825d9083f1300087c72be716b7b93d8bb26b5ff33a71a7240478c96c08d685f1d52884643b043f4b2588a03f",
|
||||||
"output_size": 4487,
|
"output_size": 6734,
|
||||||
"source": [],
|
"source": [],
|
||||||
"source_content": null,
|
"source_content": null,
|
||||||
"source_content_filename": null,
|
"source_content_filename": null,
|
||||||
@ -182,7 +182,7 @@
|
|||||||
"goog-terraform-provisioned": "true"
|
"goog-terraform-provisioned": "true"
|
||||||
},
|
},
|
||||||
"generation": 1,
|
"generation": 1,
|
||||||
"labels": null,
|
"labels": {},
|
||||||
"namespace": "gen-lang-client-0424120530",
|
"namespace": "gen-lang-client-0424120530",
|
||||||
"resource_version": "AAY16UbSm4k",
|
"resource_version": "AAY16UbSm4k",
|
||||||
"self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact",
|
"self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact",
|
||||||
@ -256,8 +256,8 @@
|
|||||||
"container_concurrency": 80,
|
"container_concurrency": 80,
|
||||||
"containers": [
|
"containers": [
|
||||||
{
|
{
|
||||||
"args": null,
|
"args": [],
|
||||||
"command": null,
|
"command": [],
|
||||||
"env": [
|
"env": [
|
||||||
{
|
{
|
||||||
"name": "FIRESTORE_DATABASE_NAME",
|
"name": "FIRESTORE_DATABASE_NAME",
|
||||||
@ -332,7 +332,7 @@
|
|||||||
"cpu": "1",
|
"cpu": "1",
|
||||||
"memory": "1Gi"
|
"memory": "1Gi"
|
||||||
},
|
},
|
||||||
"requests": null
|
"requests": {}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"startup_probe": [
|
"startup_probe": [
|
||||||
@ -354,7 +354,7 @@
|
|||||||
"working_dir": ""
|
"working_dir": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"node_selector": null,
|
"node_selector": {},
|
||||||
"service_account_name": "761163285547-compute@developer.gserviceaccount.com",
|
"service_account_name": "761163285547-compute@developer.gserviceaccount.com",
|
||||||
"serving_state": "",
|
"serving_state": "",
|
||||||
"timeout_seconds": 300,
|
"timeout_seconds": 300,
|
||||||
@ -596,6 +596,13 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"mode": "managed",
|
||||||
|
"type": "google_compute_address",
|
||||||
|
"name": "vector_db_static_ip",
|
||||||
|
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
|
||||||
|
"instances": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"mode": "managed",
|
"mode": "managed",
|
||||||
"type": "google_compute_firewall",
|
"type": "google_compute_firewall",
|
||||||
@ -822,7 +829,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "get_attr",
|
"type": "get_attr",
|
||||||
"value": "disk_encryption_key_rsa"
|
"value": "disk_encryption_key_raw"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@ -839,7 +846,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "get_attr",
|
"type": "get_attr",
|
||||||
"value": "disk_encryption_key_raw"
|
"value": "disk_encryption_key_rsa"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
@ -868,8 +875,8 @@
|
|||||||
"database_edition": "STANDARD",
|
"database_edition": "STANDARD",
|
||||||
"delete_protection_state": "DELETE_PROTECTION_DISABLED",
|
"delete_protection_state": "DELETE_PROTECTION_DISABLED",
|
||||||
"deletion_policy": "ABANDON",
|
"deletion_policy": "ABANDON",
|
||||||
"earliest_version_time": "2025-05-24T21:29:52.924798Z",
|
"earliest_version_time": "2025-05-24T21:38:29.341046Z",
|
||||||
"etag": "IPHgo4eUvY0DMKrW4vCEvY0D",
|
"etag": "IOGow/2VvY0DMKrW4vCEvY0D",
|
||||||
"id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb",
|
"id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb",
|
||||||
"key_prefix": "",
|
"key_prefix": "",
|
||||||
"location_id": "us-central1",
|
"location_id": "us-central1",
|
||||||
@ -989,18 +996,18 @@
|
|||||||
{
|
{
|
||||||
"mode": "managed",
|
"mode": "managed",
|
||||||
"type": "google_project_iam_member",
|
"type": "google_project_iam_member",
|
||||||
"name": "function_vision",
|
"name": "function_vertex_ai",
|
||||||
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
|
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
|
||||||
"instances": [
|
"instances": [
|
||||||
{
|
{
|
||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"condition": [],
|
"condition": [],
|
||||||
"etag": "BwY16LCINIE=",
|
"etag": "BwY16WAsDU4=",
|
||||||
"id": "gen-lang-client-0424120530/roles/ml.developer/serviceAccount:761163285547-compute@developer.gserviceaccount.com",
|
"id": "gen-lang-client-0424120530/roles/aiplatform.user/serviceAccount:761163285547-compute@developer.gserviceaccount.com",
|
||||||
"member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com",
|
"member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com",
|
||||||
"project": "gen-lang-client-0424120530",
|
"project": "gen-lang-client-0424120530",
|
||||||
"role": "roles/ml.developer"
|
"role": "roles/aiplatform.user"
|
||||||
},
|
},
|
||||||
"sensitive_attributes": [],
|
"sensitive_attributes": [],
|
||||||
"private": "bnVsbA==",
|
"private": "bnVsbA==",
|
||||||
@ -1016,6 +1023,20 @@
|
|||||||
"name": "services",
|
"name": "services",
|
||||||
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
|
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
|
||||||
"instances": [
|
"instances": [
|
||||||
|
{
|
||||||
|
"index_key": "aiplatform.googleapis.com",
|
||||||
|
"schema_version": 0,
|
||||||
|
"attributes": {
|
||||||
|
"disable_dependent_services": null,
|
||||||
|
"disable_on_destroy": false,
|
||||||
|
"id": "gen-lang-client-0424120530/aiplatform.googleapis.com",
|
||||||
|
"project": "gen-lang-client-0424120530",
|
||||||
|
"service": "aiplatform.googleapis.com",
|
||||||
|
"timeouts": null
|
||||||
|
},
|
||||||
|
"sensitive_attributes": [],
|
||||||
|
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"index_key": "cloudbuild.googleapis.com",
|
"index_key": "cloudbuild.googleapis.com",
|
||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
@ -1493,21 +1514,21 @@
|
|||||||
"content_encoding": "",
|
"content_encoding": "",
|
||||||
"content_language": "",
|
"content_language": "",
|
||||||
"content_type": "application/zip",
|
"content_type": "application/zip",
|
||||||
"crc32c": "Y4Q5hw==",
|
"crc32c": "kTROsA==",
|
||||||
"customer_encryption": [],
|
"customer_encryption": [],
|
||||||
"detect_md5hash": "pdOn/hMclyv40O3zCVRQQg==",
|
"detect_md5hash": "Ru+hruU4bi8kS1lyicfEug==",
|
||||||
"event_based_hold": false,
|
"event_based_hold": false,
|
||||||
"generation": 1748125796837241,
|
"generation": 1748126317190781,
|
||||||
"id": "gen-lang-client-0424120530-cloud-function-source-function-source-a5d3a7fe131c972bf8d0edf309545042.zip",
|
"id": "gen-lang-client-0424120530-cloud-function-source-function-source-46efa1aee5386e2f244b597289c7c4ba.zip",
|
||||||
"kms_key_name": "",
|
"kms_key_name": "",
|
||||||
"md5hash": "pdOn/hMclyv40O3zCVRQQg==",
|
"md5hash": "Ru+hruU4bi8kS1lyicfEug==",
|
||||||
"md5hexhash": "a5d3a7fe131c972bf8d0edf309545042",
|
"md5hexhash": "46efa1aee5386e2f244b597289c7c4ba",
|
||||||
"media_link": "https://storage.googleapis.com/download/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-a5d3a7fe131c972bf8d0edf309545042.zip?generation=1748125796837241\u0026alt=media",
|
"media_link": "https://storage.googleapis.com/download/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-46efa1aee5386e2f244b597289c7c4ba.zip?generation=1748126317190781\u0026alt=media",
|
||||||
"metadata": null,
|
"metadata": null,
|
||||||
"name": "function-source-a5d3a7fe131c972bf8d0edf309545042.zip",
|
"name": "function-source-46efa1aee5386e2f244b597289c7c4ba.zip",
|
||||||
"output_name": "function-source-a5d3a7fe131c972bf8d0edf309545042.zip",
|
"output_name": "function-source-46efa1aee5386e2f244b597289c7c4ba.zip",
|
||||||
"retention": [],
|
"retention": [],
|
||||||
"self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-a5d3a7fe131c972bf8d0edf309545042.zip",
|
"self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-46efa1aee5386e2f244b597289c7c4ba.zip",
|
||||||
"source": "./function-source.zip",
|
"source": "./function-source.zip",
|
||||||
"storage_class": "STANDARD",
|
"storage_class": "STANDARD",
|
||||||
"temporary_hold": false,
|
"temporary_hold": false,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 4,
|
"version": 4,
|
||||||
"terraform_version": "1.10.1",
|
"terraform_version": "1.10.1",
|
||||||
"serial": 404,
|
"serial": 410,
|
||||||
"lineage": "a183cd95-f987-8698-c6dd-84e933c394a5",
|
"lineage": "a183cd95-f987-8698-c6dd-84e933c394a5",
|
||||||
"outputs": {
|
"outputs": {
|
||||||
"cloud_function_name": {
|
"cloud_function_name": {
|
||||||
@ -98,16 +98,16 @@
|
|||||||
"attributes": {
|
"attributes": {
|
||||||
"exclude_symlink_directories": null,
|
"exclude_symlink_directories": null,
|
||||||
"excludes": null,
|
"excludes": null,
|
||||||
"id": "045029ac803155784c12f8d587fee56b85b1fbe9",
|
"id": "7a7a706b5bba3a12744f2dd109eb18de7112f351",
|
||||||
"output_base64sha256": "b/FgNMMT30JSXfrLRXNkWeNc6i22YAmT3YwQRTw1+A4=",
|
"output_base64sha256": "0wAfDV7tH41jEspQ3LBLvIEnrQ6XU2aEtK2GWsMdyCA=",
|
||||||
"output_base64sha512": "7GDDTkHwwQVAlwSxe7yzgtGccMNIRCQ7t72ZRk7bcfDI1tzpruhJ5G/0AbrUMXWQO6LffnWtwumQ7XdFHAIzBA==",
|
"output_base64sha512": "glsNAiHzSTOy9mGDckkSyDJhBVFDtLh8Xr6+hSxtCT8nok9qNGO+61iTRLU42OPxaPS/BrbDAXJeT86F3riefA==",
|
||||||
"output_file_mode": null,
|
"output_file_mode": null,
|
||||||
"output_md5": "34d81725abbd4f423de71ecd4215d116",
|
"output_md5": "a5d3a7fe131c972bf8d0edf309545042",
|
||||||
"output_path": "./function-source.zip",
|
"output_path": "./function-source.zip",
|
||||||
"output_sha": "045029ac803155784c12f8d587fee56b85b1fbe9",
|
"output_sha": "7a7a706b5bba3a12744f2dd109eb18de7112f351",
|
||||||
"output_sha256": "6ff16034c313df42525dfacb45736459e35cea2db6600993dd8c10453c35f80e",
|
"output_sha256": "d3001f0d5eed1f8d6312ca50dcb04bbc8127ad0e97536684b4ad865ac31dc820",
|
||||||
"output_sha512": "ec60c34e41f0c105409704b17bbcb382d19c70c34844243bb7bd99464edb71f0c8d6dce9aee849e46ff401bad43175903ba2df7e75adc2e990ed77451c023304",
|
"output_sha512": "825b0d0221f34933b2f66183724912c83261055143b4b87c5ebebe852c6d093f27a24f6a3463beeb589344b538d8e3f168f4bf06b6c301725e4fce85deb89e7c",
|
||||||
"output_size": 5014,
|
"output_size": 4487,
|
||||||
"source": [],
|
"source": [],
|
||||||
"source_content": null,
|
"source_content": null,
|
||||||
"source_content_filename": null,
|
"source_content_filename": null,
|
||||||
@ -170,11 +170,9 @@
|
|||||||
"run.googleapis.com/ingress": "all"
|
"run.googleapis.com/ingress": "all"
|
||||||
},
|
},
|
||||||
"effective_annotations": {
|
"effective_annotations": {
|
||||||
"run.googleapis.com/client-name": "gcloud",
|
|
||||||
"run.googleapis.com/client-version": "431.0.0",
|
|
||||||
"run.googleapis.com/ingress": "all",
|
"run.googleapis.com/ingress": "all",
|
||||||
"run.googleapis.com/ingress-status": "all",
|
"run.googleapis.com/ingress-status": "all",
|
||||||
"run.googleapis.com/operation-id": "e4d7484f-39e4-4dde-8105-28d285eb927b",
|
"run.googleapis.com/operation-id": "7869f742-fe94-42d0-8d82-a1462681980d",
|
||||||
"run.googleapis.com/urls": "[\"https://sereact-761163285547.us-central1.run.app\",\"https://sereact-p64zpdtkta-uc.a.run.app\"]",
|
"run.googleapis.com/urls": "[\"https://sereact-761163285547.us-central1.run.app\",\"https://sereact-p64zpdtkta-uc.a.run.app\"]",
|
||||||
"serving.knative.dev/creator": "johnpccd3@gmail.com",
|
"serving.knative.dev/creator": "johnpccd3@gmail.com",
|
||||||
"serving.knative.dev/lastModifier": "johnpccd3@gmail.com"
|
"serving.knative.dev/lastModifier": "johnpccd3@gmail.com"
|
||||||
@ -183,15 +181,15 @@
|
|||||||
"cloud.googleapis.com/location": "us-central1",
|
"cloud.googleapis.com/location": "us-central1",
|
||||||
"goog-terraform-provisioned": "true"
|
"goog-terraform-provisioned": "true"
|
||||||
},
|
},
|
||||||
"generation": 2,
|
"generation": 1,
|
||||||
"labels": {},
|
"labels": null,
|
||||||
"namespace": "gen-lang-client-0424120530",
|
"namespace": "gen-lang-client-0424120530",
|
||||||
"resource_version": "AAY16Gy+yWQ",
|
"resource_version": "AAY16UbSm4k",
|
||||||
"self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact",
|
"self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact",
|
||||||
"terraform_labels": {
|
"terraform_labels": {
|
||||||
"goog-terraform-provisioned": "true"
|
"goog-terraform-provisioned": "true"
|
||||||
},
|
},
|
||||||
"uid": "c67276c9-0c25-4a6c-8f39-4ea942599769"
|
"uid": "d5532269-ab10-4b77-b90f-698306bf0919"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "sereact",
|
"name": "sereact",
|
||||||
@ -218,14 +216,14 @@
|
|||||||
"type": "RoutesReady"
|
"type": "RoutesReady"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"latest_created_revision_name": "sereact-00002-cew",
|
"latest_created_revision_name": "sereact-00001-9rv",
|
||||||
"latest_ready_revision_name": "sereact-00002-cew",
|
"latest_ready_revision_name": "sereact-00001-9rv",
|
||||||
"observed_generation": 2,
|
"observed_generation": 1,
|
||||||
"traffic": [
|
"traffic": [
|
||||||
{
|
{
|
||||||
"latest_revision": true,
|
"latest_revision": true,
|
||||||
"percent": 100,
|
"percent": 100,
|
||||||
"revision_name": "sereact-00002-cew",
|
"revision_name": "sereact-00001-9rv",
|
||||||
"tag": "",
|
"tag": "",
|
||||||
"url": ""
|
"url": ""
|
||||||
}
|
}
|
||||||
@ -246,7 +244,7 @@
|
|||||||
"labels": {
|
"labels": {
|
||||||
"run.googleapis.com/startupProbeType": "Default"
|
"run.googleapis.com/startupProbeType": "Default"
|
||||||
},
|
},
|
||||||
"name": "sereact-00002-cew",
|
"name": "",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
"resource_version": "",
|
"resource_version": "",
|
||||||
"self_link": "",
|
"self_link": "",
|
||||||
@ -258,8 +256,8 @@
|
|||||||
"container_concurrency": 80,
|
"container_concurrency": 80,
|
||||||
"containers": [
|
"containers": [
|
||||||
{
|
{
|
||||||
"args": [],
|
"args": null,
|
||||||
"command": [],
|
"command": null,
|
||||||
"env": [
|
"env": [
|
||||||
{
|
{
|
||||||
"name": "FIRESTORE_DATABASE_NAME",
|
"name": "FIRESTORE_DATABASE_NAME",
|
||||||
@ -334,7 +332,7 @@
|
|||||||
"cpu": "1",
|
"cpu": "1",
|
||||||
"memory": "1Gi"
|
"memory": "1Gi"
|
||||||
},
|
},
|
||||||
"requests": {}
|
"requests": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"startup_probe": [
|
"startup_probe": [
|
||||||
@ -356,7 +354,7 @@
|
|||||||
"working_dir": ""
|
"working_dir": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"node_selector": {},
|
"node_selector": null,
|
||||||
"service_account_name": "761163285547-compute@developer.gserviceaccount.com",
|
"service_account_name": "761163285547-compute@developer.gserviceaccount.com",
|
||||||
"serving_state": "",
|
"serving_state": "",
|
||||||
"timeout_seconds": 300,
|
"timeout_seconds": 300,
|
||||||
@ -437,7 +435,7 @@
|
|||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"condition": [],
|
"condition": [],
|
||||||
"etag": "BwY16Etxb+g=",
|
"etag": "BwY16UdHJ00=",
|
||||||
"id": "v1/projects/gen-lang-client-0424120530/locations/us-central1/services/sereact/roles/run.invoker/allUsers",
|
"id": "v1/projects/gen-lang-client-0424120530/locations/us-central1/services/sereact/roles/run.invoker/allUsers",
|
||||||
"location": "us-central1",
|
"location": "us-central1",
|
||||||
"member": "allUsers",
|
"member": "allUsers",
|
||||||
@ -471,7 +469,7 @@
|
|||||||
"automatic_update_policy": [
|
"automatic_update_policy": [
|
||||||
{}
|
{}
|
||||||
],
|
],
|
||||||
"build": "projects/761163285547/locations/us-central1/builds/1b8e28d1-ee4d-4d2f-acf2-47e2b03aa421",
|
"build": "projects/761163285547/locations/us-central1/builds/b2b7e513-e00e-462a-8ac8-94abdfb4a0b9",
|
||||||
"docker_repository": "projects/gen-lang-client-0424120530/locations/us-central1/repositories/gcf-artifacts",
|
"docker_repository": "projects/gen-lang-client-0424120530/locations/us-central1/repositories/gcf-artifacts",
|
||||||
"entry_point": "process_image_embedding",
|
"entry_point": "process_image_embedding",
|
||||||
"environment_variables": {},
|
"environment_variables": {},
|
||||||
@ -485,7 +483,7 @@
|
|||||||
{
|
{
|
||||||
"bucket": "gen-lang-client-0424120530-cloud-function-source",
|
"bucket": "gen-lang-client-0424120530-cloud-function-source",
|
||||||
"generation": 1748123369545880,
|
"generation": 1748123369545880,
|
||||||
"object": "function-source-34d81725abbd4f423de71ecd4215d116.zip"
|
"object": "function-source-a5d3a7fe131c972bf8d0edf309545042.zip"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -554,7 +552,7 @@
|
|||||||
"goog-terraform-provisioned": "true"
|
"goog-terraform-provisioned": "true"
|
||||||
},
|
},
|
||||||
"timeouts": null,
|
"timeouts": null,
|
||||||
"update_time": "2025-05-24T22:08:16.899711009Z",
|
"update_time": "2025-05-24T22:31:52.525335119Z",
|
||||||
"url": "https://us-central1-gen-lang-client-0424120530.cloudfunctions.net/process-image-embedding"
|
"url": "https://us-central1-gen-lang-client-0424120530.cloudfunctions.net/process-image-embedding"
|
||||||
},
|
},
|
||||||
"sensitive_attributes": [
|
"sensitive_attributes": [
|
||||||
@ -598,13 +596,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"mode": "managed",
|
|
||||||
"type": "google_compute_address",
|
|
||||||
"name": "vector_db_static_ip",
|
|
||||||
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
|
|
||||||
"instances": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"mode": "managed",
|
"mode": "managed",
|
||||||
"type": "google_compute_firewall",
|
"type": "google_compute_firewall",
|
||||||
@ -877,8 +868,8 @@
|
|||||||
"database_edition": "STANDARD",
|
"database_edition": "STANDARD",
|
||||||
"delete_protection_state": "DELETE_PROTECTION_DISABLED",
|
"delete_protection_state": "DELETE_PROTECTION_DISABLED",
|
||||||
"deletion_policy": "ABANDON",
|
"deletion_policy": "ABANDON",
|
||||||
"earliest_version_time": "2025-05-24T21:26:23.088753Z",
|
"earliest_version_time": "2025-05-24T21:29:52.924798Z",
|
||||||
"etag": "IOqynKOTvY0DMKrW4vCEvY0D",
|
"etag": "IPHgo4eUvY0DMKrW4vCEvY0D",
|
||||||
"id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb",
|
"id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb",
|
||||||
"key_prefix": "",
|
"key_prefix": "",
|
||||||
"location_id": "us-central1",
|
"location_id": "us-central1",
|
||||||
@ -1502,21 +1493,21 @@
|
|||||||
"content_encoding": "",
|
"content_encoding": "",
|
||||||
"content_language": "",
|
"content_language": "",
|
||||||
"content_type": "application/zip",
|
"content_type": "application/zip",
|
||||||
"crc32c": "YXAlNA==",
|
"crc32c": "Y4Q5hw==",
|
||||||
"customer_encryption": [],
|
"customer_encryption": [],
|
||||||
"detect_md5hash": "NNgXJau9T0I95x7NQhXRFg==",
|
"detect_md5hash": "pdOn/hMclyv40O3zCVRQQg==",
|
||||||
"event_based_hold": false,
|
"event_based_hold": false,
|
||||||
"generation": 1748124439573408,
|
"generation": 1748125796837241,
|
||||||
"id": "gen-lang-client-0424120530-cloud-function-source-function-source-34d81725abbd4f423de71ecd4215d116.zip",
|
"id": "gen-lang-client-0424120530-cloud-function-source-function-source-a5d3a7fe131c972bf8d0edf309545042.zip",
|
||||||
"kms_key_name": "",
|
"kms_key_name": "",
|
||||||
"md5hash": "NNgXJau9T0I95x7NQhXRFg==",
|
"md5hash": "pdOn/hMclyv40O3zCVRQQg==",
|
||||||
"md5hexhash": "34d81725abbd4f423de71ecd4215d116",
|
"md5hexhash": "a5d3a7fe131c972bf8d0edf309545042",
|
||||||
"media_link": "https://storage.googleapis.com/download/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-34d81725abbd4f423de71ecd4215d116.zip?generation=1748124439573408\u0026alt=media",
|
"media_link": "https://storage.googleapis.com/download/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-a5d3a7fe131c972bf8d0edf309545042.zip?generation=1748125796837241\u0026alt=media",
|
||||||
"metadata": {},
|
"metadata": null,
|
||||||
"name": "function-source-34d81725abbd4f423de71ecd4215d116.zip",
|
"name": "function-source-a5d3a7fe131c972bf8d0edf309545042.zip",
|
||||||
"output_name": "function-source-34d81725abbd4f423de71ecd4215d116.zip",
|
"output_name": "function-source-a5d3a7fe131c972bf8d0edf309545042.zip",
|
||||||
"retention": [],
|
"retention": [],
|
||||||
"self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-34d81725abbd4f423de71ecd4215d116.zip",
|
"self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-a5d3a7fe131c972bf8d0edf309545042.zip",
|
||||||
"source": "./function-source.zip",
|
"source": "./function-source.zip",
|
||||||
"storage_class": "STANDARD",
|
"storage_class": "STANDARD",
|
||||||
"temporary_hold": false,
|
"temporary_hold": false,
|
||||||
|
|||||||
@ -136,10 +136,22 @@ async def list_images(
|
|||||||
current_user: UserModel = Depends(get_current_user)
|
current_user: UserModel = Depends(get_current_user)
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
List images for the current user's team
|
List images for the current user's team, or all images if user is admin.
|
||||||
|
|
||||||
|
Regular users can only see images from their own team.
|
||||||
|
Admin users can see all images across all teams.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
skip: Number of records to skip for pagination
|
||||||
|
limit: Maximum number of records to return (1-100)
|
||||||
|
collection_id: Optional filter by collection ID
|
||||||
|
tags: Optional comma-separated list of tags to filter by
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of images with pagination metadata
|
||||||
"""
|
"""
|
||||||
log_request(
|
log_request(
|
||||||
{"path": request.url.path, "method": request.method, "skip": skip, "limit": limit},
|
{"path": request.url.path, "method": request.method, "skip": skip, "limit": limit, "is_admin": current_user.is_admin},
|
||||||
user_id=str(current_user.id),
|
user_id=str(current_user.id),
|
||||||
team_id=str(current_user.team_id)
|
team_id=str(current_user.team_id)
|
||||||
)
|
)
|
||||||
@ -149,21 +161,37 @@ async def list_images(
|
|||||||
if tags:
|
if tags:
|
||||||
tag_filter = [tag.strip() for tag in tags.split(',') if tag.strip()]
|
tag_filter = [tag.strip() for tag in tags.split(',') if tag.strip()]
|
||||||
|
|
||||||
# Get images
|
# Check if user is admin - if so, get all images across all teams
|
||||||
images = await image_repository.get_by_team(
|
if current_user.is_admin:
|
||||||
current_user.team_id,
|
# Admin users can see all images across all teams
|
||||||
skip=skip,
|
images = await image_repository.get_all_with_pagination(
|
||||||
limit=limit,
|
skip=skip,
|
||||||
collection_id=ObjectId(collection_id) if collection_id else None,
|
limit=limit,
|
||||||
tags=tag_filter
|
collection_id=ObjectId(collection_id) if collection_id else None,
|
||||||
)
|
tags=tag_filter
|
||||||
|
)
|
||||||
|
|
||||||
# Get total count
|
# Get total count for admin
|
||||||
total = await image_repository.count_by_team(
|
total = await image_repository.count_all(
|
||||||
current_user.team_id,
|
collection_id=ObjectId(collection_id) if collection_id else None,
|
||||||
collection_id=ObjectId(collection_id) if collection_id else None,
|
tags=tag_filter
|
||||||
tags=tag_filter
|
)
|
||||||
)
|
else:
|
||||||
|
# Regular users only see images from their team
|
||||||
|
images = await image_repository.get_by_team(
|
||||||
|
current_user.team_id,
|
||||||
|
skip=skip,
|
||||||
|
limit=limit,
|
||||||
|
collection_id=ObjectId(collection_id) if collection_id else None,
|
||||||
|
tags=tag_filter
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get total count for regular user
|
||||||
|
total = await image_repository.count_by_team(
|
||||||
|
current_user.team_id,
|
||||||
|
collection_id=ObjectId(collection_id) if collection_id else None,
|
||||||
|
tags=tag_filter
|
||||||
|
)
|
||||||
|
|
||||||
# Convert to response
|
# Convert to response
|
||||||
response_images = []
|
response_images = []
|
||||||
@ -211,7 +239,7 @@ async def get_image(
|
|||||||
Get image metadata by ID
|
Get image metadata by ID
|
||||||
"""
|
"""
|
||||||
log_request(
|
log_request(
|
||||||
{"path": request.url.path, "method": request.method, "image_id": image_id},
|
{"path": request.url.path, "method": request.method, "image_id": image_id, "is_admin": current_user.is_admin},
|
||||||
user_id=str(current_user.id),
|
user_id=str(current_user.id),
|
||||||
team_id=str(current_user.team_id)
|
team_id=str(current_user.team_id)
|
||||||
)
|
)
|
||||||
@ -226,8 +254,8 @@ async def get_image(
|
|||||||
if not image:
|
if not image:
|
||||||
raise HTTPException(status_code=404, detail="Image not found")
|
raise HTTPException(status_code=404, detail="Image not found")
|
||||||
|
|
||||||
# Check team access
|
# Check team access (admins can access any image)
|
||||||
if image.team_id != current_user.team_id:
|
if not current_user.is_admin and image.team_id != current_user.team_id:
|
||||||
raise HTTPException(status_code=403, detail="Not authorized to access this image")
|
raise HTTPException(status_code=403, detail="Not authorized to access this image")
|
||||||
|
|
||||||
# Update last accessed
|
# Update last accessed
|
||||||
@ -278,7 +306,7 @@ async def download_image(
|
|||||||
Download image file
|
Download image file
|
||||||
"""
|
"""
|
||||||
log_request(
|
log_request(
|
||||||
{"path": request.url.path, "method": request.method, "image_id": image_id},
|
{"path": request.url.path, "method": request.method, "image_id": image_id, "is_admin": current_user.is_admin},
|
||||||
user_id=str(current_user.id),
|
user_id=str(current_user.id),
|
||||||
team_id=str(current_user.team_id)
|
team_id=str(current_user.team_id)
|
||||||
)
|
)
|
||||||
@ -293,8 +321,8 @@ async def download_image(
|
|||||||
if not image:
|
if not image:
|
||||||
raise HTTPException(status_code=404, detail="Image not found")
|
raise HTTPException(status_code=404, detail="Image not found")
|
||||||
|
|
||||||
# Check team access
|
# Check team access (admins can access any image)
|
||||||
if image.team_id != current_user.team_id:
|
if not current_user.is_admin and image.team_id != current_user.team_id:
|
||||||
raise HTTPException(status_code=403, detail="Not authorized to access this image")
|
raise HTTPException(status_code=403, detail="Not authorized to access this image")
|
||||||
|
|
||||||
# Get file from storage
|
# Get file from storage
|
||||||
@ -323,7 +351,7 @@ async def update_image(
|
|||||||
Update image metadata
|
Update image metadata
|
||||||
"""
|
"""
|
||||||
log_request(
|
log_request(
|
||||||
{"path": request.url.path, "method": request.method, "image_id": image_id},
|
{"path": request.url.path, "method": request.method, "image_id": image_id, "is_admin": current_user.is_admin},
|
||||||
user_id=str(current_user.id),
|
user_id=str(current_user.id),
|
||||||
team_id=str(current_user.team_id)
|
team_id=str(current_user.team_id)
|
||||||
)
|
)
|
||||||
@ -338,8 +366,8 @@ async def update_image(
|
|||||||
if not image:
|
if not image:
|
||||||
raise HTTPException(status_code=404, detail="Image not found")
|
raise HTTPException(status_code=404, detail="Image not found")
|
||||||
|
|
||||||
# Check team access
|
# Check team access (admins can update any image)
|
||||||
if image.team_id != current_user.team_id:
|
if not current_user.is_admin and image.team_id != current_user.team_id:
|
||||||
raise HTTPException(status_code=403, detail="Not authorized to update this image")
|
raise HTTPException(status_code=403, detail="Not authorized to update this image")
|
||||||
|
|
||||||
# Update image
|
# Update image
|
||||||
@ -398,7 +426,7 @@ async def delete_image(
|
|||||||
Delete an image
|
Delete an image
|
||||||
"""
|
"""
|
||||||
log_request(
|
log_request(
|
||||||
{"path": request.url.path, "method": request.method, "image_id": image_id},
|
{"path": request.url.path, "method": request.method, "image_id": image_id, "is_admin": current_user.is_admin},
|
||||||
user_id=str(current_user.id),
|
user_id=str(current_user.id),
|
||||||
team_id=str(current_user.team_id)
|
team_id=str(current_user.team_id)
|
||||||
)
|
)
|
||||||
@ -413,8 +441,8 @@ async def delete_image(
|
|||||||
if not image:
|
if not image:
|
||||||
raise HTTPException(status_code=404, detail="Image not found")
|
raise HTTPException(status_code=404, detail="Image not found")
|
||||||
|
|
||||||
# Check team access
|
# Check team access (admins can delete any image)
|
||||||
if image.team_id != current_user.team_id:
|
if not current_user.is_admin and image.team_id != current_user.team_id:
|
||||||
raise HTTPException(status_code=403, detail="Not authorized to delete this image")
|
raise HTTPException(status_code=403, detail="Not authorized to delete this image")
|
||||||
|
|
||||||
# Delete from storage
|
# Delete from storage
|
||||||
|
|||||||
@ -173,5 +173,80 @@ class FirestoreImageRepository(FirestoreRepository[ImageModel]):
|
|||||||
logger.error(f"Error getting images by tag: {e}")
|
logger.error(f"Error getting images by tag: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
async def get_all_with_pagination(
|
||||||
|
self,
|
||||||
|
skip: int = 0,
|
||||||
|
limit: int = 50,
|
||||||
|
collection_id: Optional[ObjectId] = None,
|
||||||
|
tags: Optional[List[str]] = None
|
||||||
|
) -> List[ImageModel]:
|
||||||
|
"""
|
||||||
|
Get all images across all teams with pagination and filtering (admin only)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
skip: Number of records to skip
|
||||||
|
limit: Maximum number of records to return
|
||||||
|
collection_id: Optional collection ID filter
|
||||||
|
tags: Optional list of tags to filter by
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of images
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Get all images
|
||||||
|
images = await self.get_all()
|
||||||
|
|
||||||
|
# Filter by collection if specified
|
||||||
|
if collection_id:
|
||||||
|
images = [image for image in images if image.collection_id == collection_id]
|
||||||
|
|
||||||
|
# Filter by tags if specified
|
||||||
|
if tags:
|
||||||
|
images = [
|
||||||
|
image for image in images
|
||||||
|
if any(tag in image.tags for tag in tags)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Apply pagination
|
||||||
|
return images[skip:skip + limit]
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting all images with pagination: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
async def count_all(
|
||||||
|
self,
|
||||||
|
collection_id: Optional[ObjectId] = None,
|
||||||
|
tags: Optional[List[str]] = None
|
||||||
|
) -> int:
|
||||||
|
"""
|
||||||
|
Count all images across all teams with filtering (admin only)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
collection_id: Optional collection ID filter
|
||||||
|
tags: Optional list of tags to filter by
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Count of images
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Get all images
|
||||||
|
images = await self.get_all()
|
||||||
|
|
||||||
|
# Filter by collection if specified
|
||||||
|
if collection_id:
|
||||||
|
images = [image for image in images if image.collection_id == collection_id]
|
||||||
|
|
||||||
|
# Filter by tags if specified
|
||||||
|
if tags:
|
||||||
|
images = [
|
||||||
|
image for image in images
|
||||||
|
if any(tag in image.tags for tag in tags)
|
||||||
|
]
|
||||||
|
|
||||||
|
return len(images)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error counting all images: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
# Create a singleton repository
|
# Create a singleton repository
|
||||||
firestore_image_repository = FirestoreImageRepository()
|
firestore_image_repository = FirestoreImageRepository()
|
||||||
201
test_admin_images.py
Normal file
201
test_admin_images.py
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script to verify admin image access functionality.
|
||||||
|
This script tests that:
|
||||||
|
1. Regular users can only see images from their own team
|
||||||
|
2. Admin users can see all images across all teams
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from bson import ObjectId
|
||||||
|
|
||||||
|
# Add the src directory to the path
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
||||||
|
|
||||||
|
from src.models.image import ImageModel
|
||||||
|
from src.models.user import UserModel
|
||||||
|
from src.db.repositories.image_repository import image_repository
|
||||||
|
from src.db.repositories.user_repository import user_repository
|
||||||
|
from src.db.providers.firestore_provider import firestore_db
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_test_data():
|
||||||
|
"""Set up test data for the admin functionality test"""
|
||||||
|
print("Setting up test data...")
|
||||||
|
|
||||||
|
# Create two teams
|
||||||
|
team1_id = ObjectId()
|
||||||
|
team2_id = ObjectId()
|
||||||
|
|
||||||
|
# Create users
|
||||||
|
regular_user = UserModel(
|
||||||
|
email="regular@test.com",
|
||||||
|
name="Regular User",
|
||||||
|
team_id=team1_id,
|
||||||
|
is_admin=False
|
||||||
|
)
|
||||||
|
|
||||||
|
admin_user = UserModel(
|
||||||
|
email="admin@test.com",
|
||||||
|
name="Admin User",
|
||||||
|
team_id=team1_id,
|
||||||
|
is_admin=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create test images for team 1
|
||||||
|
image1_team1 = ImageModel(
|
||||||
|
filename="team1-image1.jpg",
|
||||||
|
original_filename="team1_image1.jpg",
|
||||||
|
file_size=1024,
|
||||||
|
content_type="image/jpeg",
|
||||||
|
storage_path="images/team1-image1.jpg",
|
||||||
|
team_id=team1_id,
|
||||||
|
uploader_id=regular_user.id,
|
||||||
|
description="Team 1 Image 1",
|
||||||
|
tags=["team1", "test"]
|
||||||
|
)
|
||||||
|
|
||||||
|
image2_team1 = ImageModel(
|
||||||
|
filename="team1-image2.jpg",
|
||||||
|
original_filename="team1_image2.jpg",
|
||||||
|
file_size=2048,
|
||||||
|
content_type="image/jpeg",
|
||||||
|
storage_path="images/team1-image2.jpg",
|
||||||
|
team_id=team1_id,
|
||||||
|
uploader_id=admin_user.id,
|
||||||
|
description="Team 1 Image 2",
|
||||||
|
tags=["team1", "admin"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create test images for team 2
|
||||||
|
image1_team2 = ImageModel(
|
||||||
|
filename="team2-image1.jpg",
|
||||||
|
original_filename="team2_image1.jpg",
|
||||||
|
file_size=1536,
|
||||||
|
content_type="image/jpeg",
|
||||||
|
storage_path="images/team2-image1.jpg",
|
||||||
|
team_id=team2_id,
|
||||||
|
uploader_id=ObjectId(), # Different user from team 2
|
||||||
|
description="Team 2 Image 1",
|
||||||
|
tags=["team2", "test"]
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'regular_user': regular_user,
|
||||||
|
'admin_user': admin_user,
|
||||||
|
'team1_id': team1_id,
|
||||||
|
'team2_id': team2_id,
|
||||||
|
'images': [image1_team1, image2_team1, image1_team2]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_regular_user_access(regular_user, team1_id):
|
||||||
|
"""Test that regular users only see their team's images"""
|
||||||
|
print("\n=== Testing Regular User Access ===")
|
||||||
|
|
||||||
|
# Simulate getting images for regular user (team-filtered)
|
||||||
|
team1_images = await image_repository.get_by_team(team1_id, skip=0, limit=50)
|
||||||
|
team1_count = await image_repository.count_by_team(team1_id)
|
||||||
|
|
||||||
|
print(f"Regular user sees {len(team1_images)} images from their team")
|
||||||
|
print(f"Total count for team: {team1_count}")
|
||||||
|
|
||||||
|
for image in team1_images:
|
||||||
|
print(f" - {image.filename} (Team: {image.team_id})")
|
||||||
|
|
||||||
|
# Verify all images belong to the user's team
|
||||||
|
for image in team1_images:
|
||||||
|
assert image.team_id == team1_id, f"Regular user should not see image from different team: {image.filename}"
|
||||||
|
|
||||||
|
print("✅ Regular user access test passed - only sees team images")
|
||||||
|
return len(team1_images)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_admin_user_access(admin_user):
|
||||||
|
"""Test that admin users see all images across all teams"""
|
||||||
|
print("\n=== Testing Admin User Access ===")
|
||||||
|
|
||||||
|
# Simulate getting all images for admin user
|
||||||
|
all_images = await image_repository.get_all_with_pagination(skip=0, limit=50)
|
||||||
|
all_count = await image_repository.count_all()
|
||||||
|
|
||||||
|
print(f"Admin user sees {len(all_images)} images across all teams")
|
||||||
|
print(f"Total count across all teams: {all_count}")
|
||||||
|
|
||||||
|
teams_seen = set()
|
||||||
|
for image in all_images:
|
||||||
|
teams_seen.add(str(image.team_id))
|
||||||
|
print(f" - {image.filename} (Team: {image.team_id})")
|
||||||
|
|
||||||
|
print(f"Admin sees images from {len(teams_seen)} different teams")
|
||||||
|
|
||||||
|
# Verify admin sees more images than regular user would
|
||||||
|
assert len(all_images) >= 2, "Admin should see images from multiple teams"
|
||||||
|
assert len(teams_seen) >= 2, "Admin should see images from at least 2 teams"
|
||||||
|
|
||||||
|
print("✅ Admin user access test passed - sees all images across teams")
|
||||||
|
return len(all_images)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
"""Main test function"""
|
||||||
|
print("🧪 Testing Admin Image Access Functionality")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Connect to database
|
||||||
|
firestore_db.connect()
|
||||||
|
print("✅ Connected to Firestore")
|
||||||
|
|
||||||
|
# Set up test data
|
||||||
|
test_data = await setup_test_data()
|
||||||
|
|
||||||
|
# Create test images in database
|
||||||
|
created_images = []
|
||||||
|
for image in test_data['images']:
|
||||||
|
created_image = await image_repository.create(image)
|
||||||
|
created_images.append(created_image)
|
||||||
|
print(f"Created test image: {created_image.filename}")
|
||||||
|
|
||||||
|
# Test regular user access
|
||||||
|
regular_count = await test_regular_user_access(
|
||||||
|
test_data['regular_user'],
|
||||||
|
test_data['team1_id']
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test admin user access
|
||||||
|
admin_count = await test_admin_user_access(test_data['admin_user'])
|
||||||
|
|
||||||
|
# Verify admin sees more images than regular user
|
||||||
|
print(f"\n=== Summary ===")
|
||||||
|
print(f"Regular user images: {regular_count}")
|
||||||
|
print(f"Admin user images: {admin_count}")
|
||||||
|
|
||||||
|
if admin_count > regular_count:
|
||||||
|
print("✅ SUCCESS: Admin sees more images than regular user")
|
||||||
|
else:
|
||||||
|
print("❌ FAILURE: Admin should see more images than regular user")
|
||||||
|
|
||||||
|
# Clean up test data
|
||||||
|
print(f"\n=== Cleanup ===")
|
||||||
|
for image in created_images:
|
||||||
|
await image_repository.delete(image.id)
|
||||||
|
print(f"Deleted test image: {image.filename}")
|
||||||
|
|
||||||
|
print("✅ Test completed successfully!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Test failed with error: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
finally:
|
||||||
|
# Disconnect from database
|
||||||
|
firestore_db.disconnect()
|
||||||
|
print("✅ Disconnected from Firestore")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
Loading…
x
Reference in New Issue
Block a user