rename materia_server -> materia, serve spa via backend + assets

This commit is contained in:
L-Nafaryus 2024-07-31 16:37:04 +05:00
parent d60ff09dad
commit 6ad7c29a48
Signed by: L-Nafaryus
GPG Key ID: 553C97999B363D38
51 changed files with 164 additions and 129 deletions

View File

@ -2,7 +2,7 @@
[alembic]
# path to migration scripts
script_location = ./src/materia_server/models/migrations
script_location = ./src/materia/models/migrations
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
# Uncomment the line below if you want the files to be prepended with date and time

View File

@ -1,5 +1,5 @@
[project]
name = "materia-server"
name = "materia"
version = "0.1.1"
description = "Materia is a file server"
authors = [
@ -52,7 +52,7 @@ requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project.scripts]
materia-server = "materia_server.main:server"
materia = "materia.main:main"
[tool.pyright]
reportGeneralTypeIssues = false
@ -65,14 +65,14 @@ testpaths = ["tests"]
distribution = true
[tool.pdm.build]
includes = ["src/materia_server"]
includes = ["src/materia"]
[tool.pdm.scripts]
start-server.cmd = "python ./src/materia_server/main.py {args:start --app-mode development --log-level debug}"
db-upgrade.cmd = "alembic -c ./src/materia_server/alembic.ini upgrade {args:head}"
db-downgrade.shell = "alembic -c ./src/materia_server/alembic.ini downgrade {args:base}"
db-revision.cmd = "alembic revision {args:--autogenerate}"
remove-revisions.shell = "rm -v ./src/materia_server/models/migrations/versions/*.py"
start.cmd = "python ./src/materia/main.py {args:start --app-mode development --log-level debug}"
upgrade.cmd = "alembic -c ./src/materia/alembic.ini upgrade {args:head}"
downgrade.shell = "alembic -c ./src/materia/alembic.ini downgrade {args:base}"
rev.cmd = "alembic revision {args:--autogenerate}"
rm-revs.shell = "rm -v ./src/materia/models/migrations/versions/*.py"

3
src/materia/__main__.py Normal file
View File

@ -0,0 +1,3 @@
from materia.main import main
main()

View File

@ -5,7 +5,7 @@ from loguru._logger import Logger
import logging
import inspect
from materia_server.config import Config
from materia.config import Config
class InterceptHandler(logging.Handler):
@ -69,10 +69,10 @@ def uvicorn_log_config(config: Config) -> dict:
"disable_existing_loggers": False,
"handlers": {
"default": {
"class": "materia_server._logging.InterceptHandler"
"class": "materia._logging.InterceptHandler"
},
"access": {
"class": "materia_server._logging.InterceptHandler"
"class": "materia._logging.InterceptHandler"
},
},
"loggers": {

View File

@ -0,0 +1 @@
from materia.app.app import AppContext, make_lifespan, make_application

View File

@ -14,17 +14,17 @@ import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from materia_server import config as _config
from materia_server.config import Config
from materia_server._logging import make_logger, uvicorn_log_config, Logger
from materia_server.models import (
from materia import config as _config
from materia.config import Config
from materia._logging import make_logger, uvicorn_log_config, Logger
from materia.models import (
Database,
DatabaseError,
DatabaseMigrationError,
Cache,
CacheError,
)
from materia_server import routers
from materia import routers
class AppContext(TypedDict):
@ -81,5 +81,6 @@ def make_application(config: Config, logger: Logger):
)
app.include_router(routers.api.router)
app.include_router(routers.resources.router)
app.include_router(routers.root.router)
return app

View File

@ -1,8 +1,8 @@
from os import environ
from pathlib import Path
from uvicorn.workers import UvicornWorker
from materia_server.config import Config
from materia_server._logging import uvicorn_log_config
from materia.config import Config
from materia._logging import uvicorn_log_config
class MateriaWorker(UvicornWorker):

View File

@ -21,9 +21,9 @@ def run():
options = {
"bind": "0.0.0.0:8000",
"workers": (multiprocessing.cpu_count() * 2) + 1,
"worker_class": "materia_server.app.wsgi.MateriaWorker",
"worker_class": "materia.app.wsgi.MateriaWorker",
"raw_env": ["FOO=1"],
"user": None,
"group": None
}
MateriaProcessManager("materia_server.app.app:run", options).run()
MateriaProcessManager("materia.app.app:run", options).run()

View File

@ -14,20 +14,20 @@ import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from materia_server import config as _config
from materia_server.config import Config
from materia_server._logging import make_logger, uvicorn_log_config, Logger
from materia_server.models import Database, DatabaseError, Cache
from materia_server import routers
from materia_server.app import make_application
from materia import config as _config
from materia.config import Config
from materia._logging import make_logger, uvicorn_log_config, Logger
from materia.models import Database, DatabaseError, Cache
from materia import routers
from materia.app import make_application
@click.group()
def server():
def main():
pass
@server.command()
@main.command()
@click.option("--config_path", type=Path)
@from_pydantic("application", _config.Application, prefix="app")
@from_pydantic("log", _config.Log, prefix="log")
@ -104,7 +104,7 @@ def start(application: _config.Application, config_path: Path, log: _config.Log)
pass
@server.group()
@main.group()
def config():
pass
@ -131,7 +131,7 @@ def config_create(path: Path, force: bool):
if not path.parent.exists():
logger.info("Creating directory at {}", path)
path.mkdir(parents=True)
path.parent.mkdir(parents=True)
logger.info("Writing configuration file at {}", path)
config.write(path)
@ -164,4 +164,4 @@ def config_check(path: Path):
if __name__ == "__main__":
server()
main()

View File

@ -0,0 +1,27 @@
from materia.models.auth import (
LoginType,
LoginSource,
OAuth2Application,
OAuth2Grant,
OAuth2AuthorizationCode,
)
from materia.models.database import (
Database,
DatabaseError,
DatabaseMigrationError,
Cache,
CacheError,
)
from materia.models.user import User, UserCredentials, UserInfo
from materia.models.repository import (
Repository,
RepositoryInfo,
RepositoryContent,
)
from materia.models.directory import Directory, DirectoryLink, DirectoryInfo
from materia.models.file import File, FileLink, FileInfo

View File

@ -0,0 +1,3 @@
from materia.models.auth.source import LoginType, LoginSource
from materia.models.auth.oauth2 import OAuth2Application, OAuth2Grant, OAuth2AuthorizationCode

View File

@ -8,10 +8,10 @@ from sqlalchemy import BigInteger, ExceptionContext, ForeignKey, JSON, and_, del
from sqlalchemy.orm import mapped_column, Mapped, relationship
from pydantic import BaseModel, HttpUrl
from materia_server.models.base import Base
from materia_server.models.database import Database, Cache
from materia_server import security
from materia_server.models import user
from materia.models.base import Base
from materia.models.database import Database, Cache
from materia import security
from materia.models import user
class OAuth2Application(Base):
__tablename__ = "oauth2_application"

View File

@ -6,7 +6,7 @@ from time import time
from sqlalchemy import BigInteger, Enum
from sqlalchemy.orm import Mapped, mapped_column
from materia_server.models.base import Base
from materia.models.base import Base
class LoginType(enum.Enum):

View File

@ -0,0 +1,2 @@
from materia.models.database.database import DatabaseError, DatabaseMigrationError, Database
from materia.models.database.cache import Cache, CacheError

View File

@ -18,8 +18,8 @@ from alembic.operations import Operations
from alembic.runtime.migration import MigrationContext
from alembic.script.base import ScriptDirectory
from materia_server.config import Config
from materia_server.models.base import Base
from materia.config import Config
from materia.models.base import Base
__all__ = ["Database"]

View File

@ -7,8 +7,8 @@ from sqlalchemy.orm import mapped_column, Mapped, relationship
import sqlalchemy as sa
from pydantic import BaseModel, ConfigDict
from materia_server.models.base import Base
from materia_server.models import database
from materia.models.base import Base
from materia.models import database
class Directory(Base):
@ -91,5 +91,5 @@ class DirectoryInfo(BaseModel):
used: Optional[int] = None
from materia_server.models.repository import Repository
from materia_server.models.file import File
from materia.models.repository import Repository
from materia.models.file import File

View File

@ -7,8 +7,8 @@ from sqlalchemy.orm import mapped_column, Mapped, relationship
import sqlalchemy as sa
from pydantic import BaseModel, ConfigDict
from materia_server.models.base import Base
from materia_server.models import database
from materia.models.base import Base
from materia.models import database
class File(Base):
@ -85,5 +85,5 @@ class FileInfo(BaseModel):
size: int
from materia_server.models.repository import Repository
from materia_server.models.directory import Directory
from materia.models.repository import Repository
from materia.models.directory import Directory

View File

@ -8,13 +8,13 @@ from sqlalchemy.ext.asyncio import async_engine_from_config
from alembic import context
import alembic_postgresql_enum
from materia_server.config import Config
from materia_server.models.base import Base
import materia_server.models.user
import materia_server.models.auth
import materia_server.models.repository
import materia_server.models.directory
import materia_server.models.file
from materia.config import Config
from materia.models.base import Base
import materia.models.user
import materia.models.auth
import materia.models.repository
import materia.models.directory
import materia.models.file
# this is the Alembic Config object, which provides

View File

@ -8,8 +8,8 @@ from sqlalchemy.orm.attributes import InstrumentedAttribute
import sqlalchemy as sa
from pydantic import BaseModel, ConfigDict
from materia_server.models.base import Base
from materia_server.models import database
from materia.models.base import Base
from materia.models import database
class Repository(Base):
@ -73,6 +73,6 @@ class RepositoryContent(BaseModel):
directories: list["DirectoryInfo"]
from materia_server.models.user import User
from materia_server.models.directory import Directory, DirectoryInfo
from materia_server.models.file import File, FileInfo
from materia.models.user import User
from materia.models.directory import Directory, DirectoryInfo
from materia.models.file import File, FileInfo

View File

@ -9,9 +9,9 @@ from sqlalchemy import BigInteger, Enum
from sqlalchemy.orm import mapped_column, Mapped, relationship
import sqlalchemy as sa
from materia_server.models.base import Base
from materia_server.models.auth.source import LoginType
from materia_server.models import database
from materia.models.base import Base
from materia.models.auth.source import LoginType
from materia.models import database
from loguru import logger
valid_username = re.compile(r"^[\da-zA-Z][-.\w]*$")
@ -115,4 +115,4 @@ class UserInfo(BaseModel):
avatar: Optional[str]
from materia_server.models.repository import Repository
from materia.models.repository import Repository

View File

@ -0,0 +1 @@
from materia.routers import middleware, api, resources, root

View File

@ -1,6 +1,6 @@
from fastapi import APIRouter
from materia_server.routers.api.auth import auth, oauth
from materia_server.routers.api import user, repository, directory, file
from materia.routers.api.auth import auth, oauth
from materia.routers.api import user, repository, directory, file
router = APIRouter(prefix="/api")
router.include_router(auth.router)

View File

@ -2,9 +2,9 @@
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Response, status
from materia_server import security
from materia_server.routers.middleware import Context
from materia_server.models import LoginType, User, UserCredentials
from materia import security
from materia.routers.middleware import Context
from materia.models import LoginType, User, UserCredentials
router = APIRouter(tags = ["auth"])

View File

@ -7,8 +7,8 @@ from fastapi.security.oauth2 import OAuth2PasswordRequestForm
from pydantic import BaseModel, HttpUrl
from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR
from materia_server.models import User
from materia_server.routers.middleware import Context
from materia.models import User
from materia.routers.middleware import Context
router = APIRouter(tags = ["oauth2"])

View File

@ -4,9 +4,9 @@ import shutil
from fastapi import APIRouter, Depends, HTTPException, status
from materia_server.models import User, Directory, DirectoryInfo
from materia_server.routers import middleware
from materia_server.config import Config
from materia.models import User, Directory, DirectoryInfo
from materia.routers import middleware
from materia.config import Config
router = APIRouter(tags=["directory"])

View File

@ -3,9 +3,9 @@ from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException, status, UploadFile
from materia_server.models import User, File, FileInfo, Directory
from materia_server.routers import middleware
from materia_server.config import Config
from materia.models import User, File, FileInfo, Directory
from materia.routers import middleware
from materia.config import Config
router = APIRouter(tags=["file"])

View File

@ -2,7 +2,7 @@ import shutil
from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException, status
from materia_server.models import (
from materia.models import (
User,
Repository,
RepositoryInfo,
@ -10,8 +10,8 @@ from materia_server.models import (
FileInfo,
DirectoryInfo,
)
from materia_server.routers import middleware
from materia_server.config import Config
from materia.routers import middleware
from materia.config import Config
router = APIRouter(tags=["repository"])

View File

@ -7,9 +7,9 @@ import sqlalchemy as sa
from sqids.sqids import Sqids
from PIL import Image
from materia_server.config import Config
from materia_server.models import User, UserInfo
from materia_server.routers import middleware
from materia.config import Config
from materia.models import User, UserInfo
from materia.routers import middleware
router = APIRouter(tags=["user"])

View File

@ -18,8 +18,8 @@ from fastapi.security import (
APIKeyHeader,
)
from materia_server import security
from materia_server.models import User, Repository
from materia import security
from materia.models import User, Repository
class Context:

View File

@ -1,11 +1,13 @@
from fastapi import APIRouter, Depends, HTTPException, status, Response
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from PIL import Image
import io
from pathlib import Path
import mimetypes
from materia_server.routers import middleware
from materia_server.config import Config
from materia.routers import middleware
from materia.config import Config
import materia_frontend
router = APIRouter(tags=["resources"], prefix="/resources")
@ -37,3 +39,18 @@ async def avatar(
)
return Response(content=buffer.getvalue(), media_type=Image.MIME[format])
@router.get("/assets/{filename}")
async def assets(filename: str):
path = Path(materia_frontend.__path__[0]).joinpath(
"dist", "resources", "assets", filename
)
if not path.exists():
return Response(status_code=status.HTTP_404_NOT_FOUND)
content = path.read_bytes()
mime = mimetypes.guess_type(path)[0]
return Response(content, media_type=mime)

View File

@ -0,0 +1,14 @@
from pathlib import Path
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
import materia_frontend
router = APIRouter(tags=["root"])
templates = Jinja2Templates(directory=Path(materia_frontend.__path__[0]) / "dist")
@router.get("/{spa:path}", response_class=HTMLResponse)
async def root(request: Request):
return templates.TemplateResponse("base.html", {"request": request, "view": "app"})

View File

@ -0,0 +1,3 @@
from materia.security.secret_key import generate_key, encrypt_payload
from materia.security.token import TokenClaims, generate_token, validate_token
from materia.security.password import hash_password, validate_password

View File

@ -1 +0,0 @@
from materia_server.app.app import AppContext, make_lifespan, make_application

View File

@ -1,27 +0,0 @@
from materia_server.models.auth import (
LoginType,
LoginSource,
OAuth2Application,
OAuth2Grant,
OAuth2AuthorizationCode,
)
from materia_server.models.database import (
Database,
DatabaseError,
DatabaseMigrationError,
Cache,
CacheError,
)
from materia_server.models.user import User, UserCredentials, UserInfo
from materia_server.models.repository import (
Repository,
RepositoryInfo,
RepositoryContent,
)
from materia_server.models.directory import Directory, DirectoryLink, DirectoryInfo
from materia_server.models.file import File, FileLink, FileInfo

View File

@ -1,3 +0,0 @@
from materia_server.models.auth.source import LoginType, LoginSource
from materia_server.models.auth.oauth2 import OAuth2Application, OAuth2Grant, OAuth2AuthorizationCode

View File

@ -1,2 +0,0 @@
from materia_server.models.database.database import DatabaseError, DatabaseMigrationError, Database
from materia_server.models.database.cache import Cache, CacheError

View File

@ -1 +0,0 @@
from materia_server.routers import middleware, api, resources

View File

@ -1,3 +0,0 @@
from materia_server.security.secret_key import generate_key, encrypt_payload
from materia_server.security.token import TokenClaims, generate_token, validate_token
from materia_server.security.password import hash_password, validate_password

View File

@ -1,9 +1,9 @@
import pytest_asyncio
import pytest
import os
from materia_server.config import Config
from materia_server.models import Database, User, LoginType, Repository, Directory
from materia_server import security
from materia.config import Config
from materia.models import Database, User, LoginType, Repository, Directory
from materia import security
import sqlalchemy as sa
from sqlalchemy.pool import NullPool
from dataclasses import dataclass

View File

@ -28,7 +28,7 @@ includes = [ "src/materia_frontend" ]
[tool.pdm.scripts]
npm-install.cmd = "npm install --prefix ./"
npm-run-build.cmd = "npm run build --prefix ./"
move-dist.shell = "rm -rf src/materia_frontend/dist && mv dist src/materia_frontend/"
move-dist.shell = "rm -vrf src/materia_frontend/dist && mv -v dist src/materia_frontend/ && cp -v templates/* src/materia_frontend/dist"
pre_build.composite = [ "npm-install", "npm-run-build", "move-dist" ]
materia-frontend.call = "materia_frontend.main:client"