diff --git a/app/core/api_auth.py b/app/core/api_auth.py
index 0771b93..5f8b282 100644
--- a/app/core/api_auth.py
+++ b/app/core/api_auth.py
@@ -9,6 +9,8 @@
from app.lib.utils import cryptography
+import pandas as pd
+
dotenv.load_dotenv()
@@ -48,55 +50,46 @@ def get_all_user_api_keys() -> List[str]:
results: List[Dict] = response["result"]
- api_keys: List[str] = [result["name"] for result in results]
+ keys: List[str] = [result["name"] for result in results]
+
+ # Filter out the emails from the keys
+ keys_series = pd.Series(keys)
+
+ # Filter the series to exclude strings containing '@'
+ api_keys: List[str] = keys_series[~keys_series.str.contains("@")].tolist()
return api_keys
-def read_api_key_from_email(email: str):
+# The KV is str -> str
+def _read_key(key_name: str) -> str:
account_id: str = CLOUDFLARE_ACCOUNT_ID
namespace_id: str = CLOUDFLARE_KV_NAMESPACE_ID
- key_name: str = email
headers = {"Authorization": "Bearer undefined", "Content-Type": "application/json"}
# Get response from api
- response = requests.get(
+ response: str = requests.get(
f"https://api.cloudflare.com/client/v4/accounts/{account_id}/storage/kv/namespaces/{namespace_id}/values/{key_name}",
headers=headers,
)
- # if isinstance(response, dict) and response["success"] is False:
- # return None
+ return response
- api_key: str = response
+
+def read_api_key_from_email(email: str):
+ api_key: str = _read_key(email)
return api_key
def read_email_from_api_key(api_key: str):
- account_id: str = CLOUDFLARE_ACCOUNT_ID
- namespace_id: str = CLOUDFLARE_KV_NAMESPACE_ID
- key_name: str = api_key
-
- headers = {"Authorization": "Bearer undefined", "Content-Type": "application/json"}
-
- # Get response from api
- response = requests.get(
- f"https://api.cloudflare.com/client/v4/accounts/{account_id}/storage/kv/namespaces/{namespace_id}/values/{key_name}",
- headers=headers,
- )
-
- # if isinstance(response, dict) and response["success"] is False:
- # return None
-
- user_email: str = response
+ user_email: str = _read_key(api_key)
return user_email
-# user_id is hopefully a string
-def create_api_key(user_email: str) -> str:
+def create_api_key(user_email: str, expiration_ttl: int = -1) -> str:
# Generate it first
api_key: str = cryptography.generate_api_key()
@@ -104,30 +97,37 @@ def create_api_key(user_email: str) -> str:
account_id: str = CLOUDFLARE_ACCOUNT_ID
namespace_id: str = CLOUDFLARE_KV_NAMESPACE_ID
- headers = {"Authorization": "Bearer undefined", "Content-Type": "application/json"}
+ def make_url(key_name: str) -> str:
+ return f"https://api.cloudflare.com/client/v4/accounts/{account_id}/storage/kv/namespaces/{namespace_id}/values/{key_name}"
- # Forward mapping: [email -> api_key]
- query_params = {"base64": False, "key": user_email, "value": api_key}
+ headers = {
+ "Content-Type": "multipart/form-data",
+ "Authorization": "Bearer undefined",
+ }
- response = requests.put(
- f"https://api.cloudflare.com/client/v4/accounts/{account_id}/storage/kv/namespaces/{namespace_id}/bulk",
- headers=headers,
- params=query_params,
- )
+ def make_request(key: str, val, expiration_ttl: int = -1):
+ url: str = make_url(key_name=key)
+
+ body = {"metadata": {}, "value": val}
+
+ if expiration_ttl != -1:
+ body["expiration_ttl"] = expiration_ttl
+
+ response = requests.request("PUT", url, headers=headers, json=body)
+ return response
+
+ # Forward mapping: [user_email -> api_key]
+ (K, V) = (user_email, api_key)
+ response = make_request(K, V, expiration_ttl=expiration_ttl)
# Print results of call
print("Forward Mapping:")
print(response.status_code)
print(response.text)
- # Reverse Mapping: [api_key -> email]
- query_params = {"base64": False, "key": api_key, "value": user_email}
-
- response = requests.put(
- f"https://api.cloudflare.com/client/v4/accounts/{account_id}/storage/kv/namespaces/{namespace_id}/bulk",
- headers=headers,
- params=query_params,
- )
+ # Reverse Mapping: [api_key -> user_email]
+ (K, V) = (api_key, user_email)
+ response = make_request(K, V, expiration_ttl=expiration_ttl)
# Print results of call
print("Reverse Mapping:")
diff --git a/app/core/routes/user.py b/app/core/routes/user.py
index b2cb6dc..617d60e 100644
--- a/app/core/routes/user.py
+++ b/app/core/routes/user.py
@@ -33,10 +33,29 @@ async def create_api_key(request: Request) -> str:
user_details: UserDetails = UserDetails(**user_client.get_user_details())
# user_auth_id: str = user_details.id
+ expiration_ttl = request.query_params.get("expiration_ttl_seconds")
+
+ # 'int'ify it
+ if expiration_ttl is None:
+ expiration_ttl = -1
+ else:
+ expiration_ttl = int(expiration_ttl)
# Make api key and store it
- api_key: str = api_auth.create_api_key(user_details.email)
+ api_key: str = api_auth.create_api_key(
+ user_details.email, expiration_ttl=expiration_ttl
+ )
+
+ return api_key
+
+
+# using post for the additional security
+@router.post("/get_apikey")
+async def get_api_key(request: Request) -> str:
+ user_client = user_kinde_client(request.url)
+ user_details: UserDetails = UserDetails(**user_client.get_user_details())
+ api_key: str = api_auth.read_api_key_from_email(user_details.email)
return api_key
diff --git a/frontend/package.json b/frontend/package.json
index 4525a4d..f4ef5d7 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -74,6 +74,8 @@
"typescript": "^5.4.5"
},
"devDependencies": {
+ "@melt-ui/pp": "^0.3.2",
+ "@melt-ui/svelte": "^0.81.0",
"flowbite": "^2.3.0",
"flowbite-svelte": "^0.46.1",
"svelte-headless-table": "^0.18.2"
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index dd651b3..f17e3d2 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -193,6 +193,12 @@ dependencies:
version: 5.4.5
devDependencies:
+ '@melt-ui/pp':
+ specifier: ^0.3.2
+ version: 0.3.2(@melt-ui/svelte@0.81.0)(svelte@4.2.17)
+ '@melt-ui/svelte':
+ specifier: ^0.81.0
+ version: 0.81.0(svelte@4.2.17)
flowbite:
specifier: ^2.3.0
version: 2.3.0
@@ -1496,7 +1502,6 @@ packages:
resolution: {integrity: sha512-qoVJVro+O0rBaw+8HPjUB1iH8Ihf8oziEnqMnvhJUSuVIrHOuZ6eNLHNvzXJKUvAtaDiqMnRlg8Z2mgh09BlUw==}
dependencies:
'@swc/helpers': 0.5.11
- dev: false
/@isaacs/cliui@8.0.2:
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
@@ -1709,6 +1714,18 @@ packages:
resolution: {integrity: sha512-Rp7ll8BHrKB3wXaRFKhrltwZl1CiXGdibPxuWXvqGnKTnv8fqa/nvftYNuSbf+pbJWKYCXdBtYTITdAUTGGh0Q==}
dev: false
+ /@melt-ui/pp@0.3.2(@melt-ui/svelte@0.81.0)(svelte@4.2.17):
+ resolution: {integrity: sha512-xKkPvaIAFinklLXcQOpwZ8YSpqAFxykjWf8Y/fSJQwsixV/0rcFs07hJ49hJjPy5vItvw5Qa0uOjzFUbXzBypQ==}
+ peerDependencies:
+ '@melt-ui/svelte': '>= 0.29.0'
+ svelte: ^3.55.0 || ^4.0.0 || ^5.0.0-next.1
+ dependencies:
+ '@melt-ui/svelte': 0.81.0(svelte@4.2.17)
+ estree-walker: 3.0.3
+ magic-string: 0.30.10
+ svelte: 4.2.17
+ dev: true
+
/@melt-ui/svelte@0.76.2(svelte@4.2.17):
resolution: {integrity: sha512-7SbOa11tXUS95T3fReL+dwDs5FyJtCEqrqG3inRziDws346SYLsxOQ6HmX+4BkIsQh1R8U3XNa+EMmdMt38lMA==}
peerDependencies:
@@ -1723,6 +1740,20 @@ packages:
svelte: 4.2.17
dev: false
+ /@melt-ui/svelte@0.81.0(svelte@4.2.17):
+ resolution: {integrity: sha512-QWVy+kVp8CZ+ph4W780PI6rPBa3MJIUFH/E1EHYfI05QloOGVBXtrI9MlzQSIrGYtGgSGQoTbh8cPO+YtkNAwg==}
+ peerDependencies:
+ svelte: ^3.0.0 || ^4.0.0 || ^5.0.0-next.118
+ dependencies:
+ '@floating-ui/core': 1.6.2
+ '@floating-ui/dom': 1.6.5
+ '@internationalized/date': 3.5.4
+ dequal: 2.0.3
+ focus-trap: 7.5.4
+ nanoid: 5.0.7
+ svelte: 4.2.17
+ dev: true
+
/@monogrid/gainmap-js@3.0.5(three@0.164.1):
resolution: {integrity: sha512-53sCTG4FaJBaAq/tcufARtVYDMDGqyBT9i7F453pWGhZ5LqubDHDWtYoHo9VhQqMcHTEexdJqSsR58y+9HVmQA==}
peerDependencies:
@@ -3195,7 +3226,6 @@ packages:
resolution: {integrity: sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==}
dependencies:
tslib: 2.6.2
- dev: false
/@tabler/icons-svelte@3.5.0(svelte@4.2.17):
resolution: {integrity: sha512-mc5ardGEM7cnUA4/q6Mz5bmW9B6t28vAAOf4Wl6+KXiTwG00EjImfnIr3pS3Ihi9sFIiXvJPYRl4H5IHlgvJvQ==}
@@ -5851,7 +5881,6 @@ packages:
resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==}
dependencies:
tabbable: 6.2.0
- dev: false
/follow-redirects@1.15.6:
resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
@@ -7799,7 +7828,6 @@ packages:
resolution: {integrity: sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==}
engines: {node: ^18 || >=20}
hasBin: true
- dev: false
/nanostores@0.10.3:
resolution: {integrity: sha512-Nii8O1XqmawqSCf9o2aWqVxhKRN01+iue9/VEd1TiJCr9VT5XxgPFbF1Edl1XN6pwJcZRsl8Ki+z01yb/T/C2g==}
@@ -9654,7 +9682,6 @@ packages:
/tabbable@6.2.0:
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
- dev: false
/tailwind-merge@2.3.0:
resolution: {integrity: sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==}
@@ -9921,7 +9948,6 @@ packages:
/tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
requiresBuild: true
- dev: false
/tunnel-rat@0.1.2(@types/react@18.3.2)(react@18.3.1):
resolution: {integrity: sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==}
diff --git a/frontend/src/components/CreateCommunity/CreateCommunityDialog.svelte b/frontend/src/components/CreateCommunity/CreateCommunityDialog.svelte
new file mode 100644
index 0000000..ff885bb
--- /dev/null
+++ b/frontend/src/components/CreateCommunity/CreateCommunityDialog.svelte
@@ -0,0 +1,13 @@
+
+
+ You Must Generate an API Key first in order to use UniverseLM. Do so by heading to your profile