mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-24 07:39:41 +02:00
feat(backend): ✨ start multi-tenant support (WIP) (#680)
* fix ts types * feat(code-generation): ♻️ update code-generation formats * new scope * add step button * fix linter error * update code-generation tags * feat(backend): ✨ start multi-tenant support * feat(backend): ✨ group invitation token generation and signup * refactor(backend): ♻️ move group admin actions to admin router * set url base to include `/admin` * feat(frontend): ✨ generate user sign-up links * test(backend): ✅ refactor test-suite to further decouple tests (WIP) * feat(backend): 🐛 assign owner on backup import for recipes * fix(backend): 🐛 assign recipe owner on migration from other service Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
parent
3c504e7048
commit
bdaf758712
90 changed files with 1793 additions and 949 deletions
60
dev/scripts/all_recipes_stress_test.py
Normal file
60
dev/scripts/all_recipes_stress_test.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
import json
|
||||
import random
|
||||
import string
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
def random_string(length: int) -> str:
|
||||
return "".join(random.choice(string.ascii_lowercase) for _ in range(length))
|
||||
|
||||
|
||||
def payload_factory() -> dict:
|
||||
return {"name": random_string(15)}
|
||||
|
||||
|
||||
def login(username="changeme@email.com", password="MyPassword"):
|
||||
|
||||
payload = {"username": username, "password": password}
|
||||
r = requests.post("http://localhost:9000/api/auth/token", payload)
|
||||
|
||||
# Bearer
|
||||
token = json.loads(r.text).get("access_token")
|
||||
return {"Authorization": f"Bearer {token}"}
|
||||
|
||||
|
||||
def populate_data(token):
|
||||
for _ in range(300):
|
||||
payload = payload_factory()
|
||||
r = requests.post("http://localhost:9000/api/recipes", json=payload, headers=token)
|
||||
|
||||
if r.status_code != 201:
|
||||
print(f"Error: {r.status_code}")
|
||||
print(r.text)
|
||||
exit()
|
||||
|
||||
else:
|
||||
print(f"Created recipe: {payload}")
|
||||
|
||||
|
||||
def time_request(url, headers):
|
||||
start = time.time()
|
||||
_ = requests.get(url, headers=headers)
|
||||
end = time.time()
|
||||
print(end - start)
|
||||
|
||||
|
||||
def main():
|
||||
print("Starting...")
|
||||
token = login()
|
||||
# populate_data(token)
|
||||
|
||||
for _ in range(10):
|
||||
time_request("http://localhost:9000/api/recipes", token)
|
||||
|
||||
print("Finished...")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
58
dev/scripts/gen_global_componenets.py
Normal file
58
dev/scripts/gen_global_componenets.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
from pathlib import Path
|
||||
|
||||
from jinja2 import Template
|
||||
|
||||
template = """// This Code is auto generated by gen_global_componenets.py
|
||||
{% for name in global %} import {{ name }} from "@/components/global/{{ name }}.vue";
|
||||
{% endfor %}
|
||||
{% for name in layout %} import {{ name }} from "@/components/layout/{{ name }}.vue";
|
||||
{% endfor %}
|
||||
|
||||
declare module "vue" {
|
||||
export interface GlobalComponents {
|
||||
// Global Components
|
||||
{% for name in global %} {{ name }}: typeof {{ name }};
|
||||
{% endfor %} // Layout Components
|
||||
{% for name in layout %} {{ name }}: typeof {{ name }};
|
||||
{% endfor %}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
"""
|
||||
|
||||
project_dir = Path(__file__).parent.parent.parent
|
||||
|
||||
destination_file = project_dir / "frontend" / "types" / "components.d.ts"
|
||||
|
||||
component_paths = {
|
||||
"global": project_dir / "frontend" / "components" / "global",
|
||||
"layout": project_dir / "frontend" / "components" / "Layout",
|
||||
}
|
||||
|
||||
|
||||
def render_template(template: str, data: dict) -> None:
|
||||
template = Template(template)
|
||||
|
||||
return template.render(**data)
|
||||
|
||||
|
||||
def build_data(component_paths: dict) -> dict:
|
||||
data = {}
|
||||
for name, path in component_paths.items():
|
||||
components = []
|
||||
for component in path.glob("*.vue"):
|
||||
components.append(component.stem)
|
||||
data[name] = components
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def write_template(text: str) -> None:
|
||||
destination_file.write_text(text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
data = build_data(component_paths)
|
||||
text = render_template(template, build_data(component_paths))
|
||||
write_template(text)
|
|
@ -1,38 +0,0 @@
|
|||
from pathlib import Path
|
||||
from pprint import pprint
|
||||
|
||||
PROJECT_DIR = Path(__file__).parent.parent.parent
|
||||
|
||||
|
||||
datetime_dir = PROJECT_DIR / "frontend" / "lang" / "dateTimeFormats"
|
||||
locales_dir = PROJECT_DIR / "datetime" / "lang" / "messages"
|
||||
|
||||
|
||||
"""
|
||||
{
|
||||
code: "en-US",
|
||||
file: "en-US.json",
|
||||
}
|
||||
|
||||
"en-US": require("./lang/dateTimeFormats/en-US.json"),
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
print("Starting...")
|
||||
|
||||
all_langs = []
|
||||
for match in datetime_dir.glob("*.json"):
|
||||
print(f'"{match.stem}": require("./lang/dateTimeFormats/{match.name}"),')
|
||||
|
||||
all_langs.append({"code": match.stem, "file": match.name})
|
||||
|
||||
print("\n\n\n--------- All Languages -----------")
|
||||
pprint(all_langs)
|
||||
|
||||
print("Finished...")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Add table
Add a link
Reference in a new issue