initial commit
This commit is contained in:
commit
b5727508bb
24 changed files with 321 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
__pycache__/
|
||||
message.sqlite3
|
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"cSpell.words": [
|
||||
"corsheaders",
|
||||
"TAUTH",
|
||||
"TCOMMON"
|
||||
]
|
||||
}
|
19
config.py
Normal file
19
config.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from typing import Literal
|
||||
|
||||
DEBUG = True
|
||||
|
||||
# DON'T PUT A TRAILING SLASH ON URLS!
|
||||
# Use a local url for faster communication for INTERNAL urls.
|
||||
# ---------------------------------------
|
||||
tCOMMON_URL_PUBLIC = "http://localhost:8888"
|
||||
tCOMMON_URL_INTERNAL = "http://localhost:8888"
|
||||
|
||||
# This token should match the tokens set in the config.py files for other services
|
||||
tCOMMON_TOKEN = "Secret tCommon-specific token"
|
||||
|
||||
ENABLED_APPLICATIONS: dict[str, Literal[False] | None | tuple[str, str, str]] = {
|
||||
# The tokens set here should match the tokens in other services. If they don't, the service will refuse to start.
|
||||
# "service": ("token", "internal_url", "public_url")
|
||||
"auth": ("Secret tAuth-specific token", "http://localhost:8000", "http://localhost:8000"),
|
||||
"message": ("Secret tMessage-specific token", "http://localhost:8001", "http://localhost:8001")
|
||||
}
|
14
manage.py
Executable file
14
manage.py
Executable file
|
@ -0,0 +1,14 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tcommon.settings")
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError("Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?") from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
django
|
||||
django-cors-headers
|
||||
requests
|
0
tcommon/__init__.py
Normal file
0
tcommon/__init__.py
Normal file
6
tcommon/asgi.py
Normal file
6
tcommon/asgi.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tcommon.settings")
|
||||
application = get_asgi_application()
|
37
tcommon/settings.py
Normal file
37
tcommon/settings.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
from pathlib import Path
|
||||
|
||||
from config import DEBUG # noqa: F401
|
||||
from config import tCOMMON_TOKEN as SECRET_KEY # noqa: F401
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
STATIC_DIR = BASE_DIR / "tcommon/static"
|
||||
ALLOWED_HOSTS = ["*"]
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"corsheaders"
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
"corsheaders.middleware.CorsMiddleware",
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware"
|
||||
]
|
||||
|
||||
ROOT_URLCONF = "tcommon.urls"
|
||||
WSGI_APPLICATION = "tcommon.wsgi.application"
|
||||
LANGUAGE_CODE = "en-us"
|
||||
TIME_ZONE = "UTC"
|
||||
USE_I18N = True
|
||||
USE_TZ = True
|
||||
|
||||
CORS_ALLOW_ALL_ORIGINS = True
|
||||
CORS_URLS_REGEX = r"^/static/.+$"
|
101
tcommon/static/css/base.css
Normal file
101
tcommon/static/css/base.css
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* Colors */
|
||||
html { --rosewater: #f5e0dc; --flamingo: #f2cdcd; --pink: #f5c2e7; --mauve: #cba6f7; --red: #f38ba8; --maroon: #eba0ac; --peach: #fab387; --yellow: #f9e2af; --green: #a6e3a1; --teal: #94e2d5; --sky: #89dceb; --sapphire: #74c7ec; --blue: #89b4fa; --lavender: #b4befe; --text: #cdd6f4; --subtext1: #bac2de; --subtext0: #a6adc8; --overlay2: #9399b2; --overlay1: #7f849c; --overlay0: #6c7086; --surface2: #585b70; --surface1: #45475a; --surface0: #313244; --base: #1e1e2e; --mantle: #181825; --crust: #11111b; --base-low-op: #1e1e2ed0 }
|
||||
html[data-light] { --rosewater: #dc8a78; --flamingo: #dd7878; --pink: #ea76cb; --mauve: #8839ef; --red: #d20f39; --maroon: #e64553; --peach: #fe640b; --yellow: #df8e1d; --green: #40a02b; --teal: #179299; --sky: #04a5e5; --sapphire: #209fb5; --blue: #1e66f5; --lavender: #7287fd; --text: #4c4f69; --subtext1: #5c5f77; --subtext0: #6c6f85; --overlay2: #7c7f93; --overlay1: #8c8fa1; --overlay0: #9ca0b0; --surface2: #acb0be; --surface1: #bcc0cc; --surface0: #ccd0da; --base: #eff1f5; --mantle: #e6e9ef; --crust: #dce0e8; --base-low-op: #eff1f5b0}
|
||||
|
||||
/* Font */
|
||||
@font-face { font-family: 'DejaVu Sans'; font-style: normal; font-weight: 400; font-display: block; src: url("/static/font/DejaVuSans.ttf") format("truetype"); }
|
||||
@font-face { font-family: 'DejaVu Sans'; font-style: normal; font-weight: 700; font-display: block; src: url("/static/font/DejaVuSans-Bold.ttf") format("truetype"); }
|
||||
@font-face { font-family: 'DejaVu Sans'; font-style: italic; font-weight: 400; font-display: block; src: url("/static/font/DejaVuSans-Oblique.ttf") format("truetype"); }
|
||||
@font-face { font-family: 'DejaVu Sans'; font-style: italic; font-weight: 700; font-display: block; src: url("/static/font/DejaVuSans-BoldOblique.ttf") format("truetype"); }
|
||||
@font-face { font-family: 'DejaVu Sans'; font-style: normal; font-weight: 200; font-display: block; src: url("/static/font/DejaVuSans-ExtraLight.ttf") format("truetype"); }
|
||||
@font-face { font-family: "Ubuntu Mono"; font-style: normal; font-weight: 400; font-display: block; src: url("/static/font/UbuntuMono-Regular.ttf") format("truetype"); }
|
||||
@font-face { font-family: "Ubuntu Mono"; font-style: italic; font-weight: 400; font-display: block; src: url("/static/font/UbuntuMono-Italic.ttf") format("truetype"); }
|
||||
@font-face { font-family: "Ubuntu Mono"; font-style: normal; font-weight: 700; font-display: block; src: url("/static/font/UbuntuMono-Bold.ttf") format("truetype"); }
|
||||
@font-face { font-family: "Ubuntu Mono"; font-style: italic; font-weight: 700; font-display: block; src: url("/static/font/UbuntuMono-BoldItalic.ttf") format("truetype"); }
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
background-color: var(--base);
|
||||
color: var(--text);
|
||||
font-family: "DejaVu Sans";
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
font-family: "Ubuntu Mono"
|
||||
}
|
||||
|
||||
small, i {
|
||||
color: var(--subtext0);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
a:link,
|
||||
a:visited {
|
||||
color: var(--accent);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
input:not(
|
||||
[type="submit"]
|
||||
) {
|
||||
background-color: var(--mantle);
|
||||
color: var(--text);
|
||||
font-family: "DejaVu Sans";
|
||||
outline: 1px solid var(--surface0);
|
||||
padding: 4px 6px;
|
||||
border: none;
|
||||
margin: 2px 0;
|
||||
border-radius: 4px;
|
||||
transition: outline-color 0.25s, background-color 0.25s;
|
||||
}
|
||||
|
||||
input:not(
|
||||
[type="submit"]
|
||||
):focus {
|
||||
outline-color: var(--accent);
|
||||
background-color: var(--crust);
|
||||
transition: outline-color 0.1s, background-color 0.1s;
|
||||
}
|
||||
|
||||
input[type="submit"],
|
||||
button {
|
||||
background-color: var(--mantle);
|
||||
color: var(--text);
|
||||
font-family: "DejaVu Sans";
|
||||
outline: 1px solid var(--surface0);
|
||||
padding: 4px 12px;
|
||||
min-width: 75px;
|
||||
border: none;
|
||||
margin: 2px 0;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: outline-color 0.25s, background-color 0.25s;
|
||||
}
|
||||
|
||||
input[type="submit"]:focus,
|
||||
button:focus {
|
||||
outline-color: var(--accent);
|
||||
transition: outline-color 0.1s;
|
||||
}
|
||||
|
||||
input[type="submit"]:active,
|
||||
button:active {
|
||||
background-color: var(--crust);
|
||||
transition: background-color 0.1s;
|
||||
}
|
||||
|
||||
|
||||
#container {
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
width: calc(100vw - 20px);
|
||||
max-width: calc(100vw - 20px);
|
||||
}
|
BIN
tcommon/static/font/DejaVuSans-Bold.ttf
Normal file
BIN
tcommon/static/font/DejaVuSans-Bold.ttf
Normal file
Binary file not shown.
BIN
tcommon/static/font/DejaVuSans-BoldOblique.ttf
Normal file
BIN
tcommon/static/font/DejaVuSans-BoldOblique.ttf
Normal file
Binary file not shown.
BIN
tcommon/static/font/DejaVuSans-ExtraLight.ttf
Normal file
BIN
tcommon/static/font/DejaVuSans-ExtraLight.ttf
Normal file
Binary file not shown.
BIN
tcommon/static/font/DejaVuSans-Oblique.ttf
Normal file
BIN
tcommon/static/font/DejaVuSans-Oblique.ttf
Normal file
Binary file not shown.
BIN
tcommon/static/font/DejaVuSans.ttf
Normal file
BIN
tcommon/static/font/DejaVuSans.ttf
Normal file
Binary file not shown.
BIN
tcommon/static/font/UbuntuMono-Bold.ttf
Normal file
BIN
tcommon/static/font/UbuntuMono-Bold.ttf
Normal file
Binary file not shown.
BIN
tcommon/static/font/UbuntuMono-BoldItalic.ttf
Normal file
BIN
tcommon/static/font/UbuntuMono-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
tcommon/static/font/UbuntuMono-Italic.ttf
Normal file
BIN
tcommon/static/font/UbuntuMono-Italic.ttf
Normal file
Binary file not shown.
BIN
tcommon/static/font/UbuntuMono-Regular.ttf
Normal file
BIN
tcommon/static/font/UbuntuMono-Regular.ttf
Normal file
Binary file not shown.
30
tcommon/static/js/theme.js
Normal file
30
tcommon/static/js/theme.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
let _themeMM = matchMedia("(prefers-color-scheme: light)");
|
||||
let light, useAutoTheme;
|
||||
// {% if theme == "auto" %}
|
||||
light = _themeMM.matches;
|
||||
useAutoTheme = true;
|
||||
// {% else %}
|
||||
// {% if theme == "light" %}
|
||||
light = true;
|
||||
// {% else %}
|
||||
light = false;
|
||||
// {% endif %}
|
||||
useAutoTheme = false;
|
||||
// {% endif %}
|
||||
|
||||
function setTheme() {
|
||||
if (light) {
|
||||
document.documentElement.setAttribute("data-light", "");
|
||||
} else {
|
||||
document.documentElement.removeAttribute("data-light");
|
||||
}
|
||||
}
|
||||
|
||||
_themeMM.addEventListener("change", function() {
|
||||
if (useAutoTheme) {
|
||||
light = _themeMM.matches;
|
||||
setTheme();
|
||||
}
|
||||
});
|
||||
|
||||
setTheme();
|
8
tcommon/urls.py
Normal file
8
tcommon/urls.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
from django.urls import include, path
|
||||
|
||||
from .views import initialize
|
||||
|
||||
urlpatterns = [
|
||||
path("api/initialize/", initialize),
|
||||
path("static/", include("tcommon.views.static"))
|
||||
]
|
1
tcommon/views/__init__.py
Normal file
1
tcommon/views/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
from .api import initialize # noqa: F401
|
52
tcommon/views/api.py
Normal file
52
tcommon/views/api.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
import json
|
||||
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.http import HttpResponse
|
||||
|
||||
from config import (DEBUG, ENABLED_APPLICATIONS, tCOMMON_TOKEN,
|
||||
tCOMMON_URL_INTERNAL, tCOMMON_URL_PUBLIC)
|
||||
|
||||
|
||||
def initialize(request: WSGIRequest) -> HttpResponse:
|
||||
if request.GET.get("token") != tCOMMON_TOKEN:
|
||||
return HttpResponse(
|
||||
json.dumps({
|
||||
"success": False
|
||||
}),
|
||||
content_type="application/json",
|
||||
status=401
|
||||
)
|
||||
|
||||
resp = {
|
||||
"debug": DEBUG,
|
||||
"success": True,
|
||||
"services": {
|
||||
"common": {
|
||||
"url": {
|
||||
"pub": tCOMMON_URL_PUBLIC,
|
||||
"int": tCOMMON_URL_INTERNAL
|
||||
},
|
||||
"token": tCOMMON_TOKEN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for service in [
|
||||
"auth", "message"
|
||||
]:
|
||||
if service in ENABLED_APPLICATIONS and isinstance(s := ENABLED_APPLICATIONS[service], tuple):
|
||||
resp["services"][service] = {
|
||||
"url": {
|
||||
"pub": s[2],
|
||||
"int": s[1],
|
||||
},
|
||||
"token": s[0]
|
||||
}
|
||||
else:
|
||||
resp["services"][service] = None
|
||||
|
||||
return HttpResponse(
|
||||
json.dumps(resp),
|
||||
content_type="application/json",
|
||||
status=200
|
||||
)
|
35
tcommon/views/static.py
Normal file
35
tcommon/views/static.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
from django.http import HttpResponse
|
||||
from django.urls import path
|
||||
|
||||
from tcommon.settings import STATIC_DIR
|
||||
|
||||
|
||||
def get_static_serve(path: str, content_type: str):
|
||||
def x(request):
|
||||
return HttpResponse(
|
||||
open(STATIC_DIR / path, "rb").read(),
|
||||
content_type=content_type
|
||||
)
|
||||
|
||||
x.__name__ = path
|
||||
return x
|
||||
|
||||
file_associations = {
|
||||
"js": "text/javascript",
|
||||
"css": "text/css",
|
||||
"ttf": "font/ttf"
|
||||
}
|
||||
|
||||
urlpatterns = [path(i, get_static_serve(i, file_associations[i.split(".")[-1]])) for i in [
|
||||
"css/base.css",
|
||||
"js/theme.js",
|
||||
"font/DejaVuSans-Bold.ttf",
|
||||
"font/DejaVuSans-BoldItalic.ttf",
|
||||
"font/DejaVuSans-Italic.ttf",
|
||||
"font/DejaVuSans-Oblique.ttf",
|
||||
"font/DejaVuSans.ttf",
|
||||
"font/UbuntuMono-Bold.ttf",
|
||||
"font/UbuntuMono-BoldItalic.ttf",
|
||||
"font/UbuntuMono-Italic.ttf",
|
||||
"font/UbuntuMono-Regular.ttf"
|
||||
]]
|
6
tcommon/wsgi.py
Normal file
6
tcommon/wsgi.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tcommon.settings")
|
||||
application = get_wsgi_application()
|
Loading…
Reference in a new issue