Compare commits

..

No commits in common. "6ad7c29a4851754e86a9ddf15acac69ba0b8528e" and "850bb89346fe49ca066c91737d5e67c20873bea0" have entirely different histories.

119 changed files with 2877 additions and 1022 deletions

View File

@ -43,7 +43,7 @@
// {inherit meta;}; // {inherit meta;};
in { in {
packages.x86_64-linux = { packages.x86_64-linux = {
materia-frontend-nodejs = dreamBuildPackage { materia-frontend = dreamBuildPackage {
module = { module = {
lib, lib,
config, config,
@ -58,7 +58,7 @@
]; ];
mkDerivation = { mkDerivation = {
src = ./workspaces/frontend; src = ./materia-web-client/src/materia-frontend;
}; };
deps = {nixpkgs, ...}: { deps = {nixpkgs, ...}: {
@ -74,22 +74,22 @@
}; };
}; };
meta = with nixpkgs.lib; { meta = with nixpkgs.lib; {
description = "Materia frontend (nodejs)"; description = "Materia frontend";
license = licenses.mit; license = licenses.mit;
maintainers = with bonLib.maintainers; [L-Nafaryus]; maintainers = with bonLib.maintainers; [L-Nafaryus];
broken = false; broken = false;
}; };
}; };
materia-frontend = dreamBuildPackage { materia-web-client = dreamBuildPackage {
extraArgs = { extraArgs = {
inherit (self.packages.x86_64-linux) materia-frontend-nodejs; inherit (self.packages.x86_64-linux) materia-frontend;
}; };
module = { module = {
config, config,
lib, lib,
dream2nix, dream2nix,
materia-frontend-nodejs, materia-frontend,
... ...
}: { }: {
imports = [dream2nix.modules.dream2nix.WIP-python-pdm]; imports = [dream2nix.modules.dream2nix.WIP-python-pdm];
@ -102,17 +102,17 @@
}; };
mkDerivation = { mkDerivation = {
src = ./workspaces/frontend; src = ./materia-web-client;
buildInputs = [ buildInputs = [
pkgs.python3.pkgs.pdm-backend pkgs.python3.pkgs.pdm-backend
]; ];
configurePhase = '' configurePhase = ''
cp -rv ${materia-frontend-nodejs}/dist ./src/materia-frontend/ cp -rv ${materia-frontend}/dist ./src/materia-frontend/
''; '';
}; };
}; };
meta = with nixpkgs.lib; { meta = with nixpkgs.lib; {
description = "Materia frontend"; description = "Materia web client";
license = licenses.mit; license = licenses.mit;
maintainers = with bonLib.maintainers; [L-Nafaryus]; maintainers = with bonLib.maintainers; [L-Nafaryus];
broken = false; broken = false;

162
materia-client/.gitignore vendored Normal file
View File

@ -0,0 +1,162 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm-project.org/#use-with-ide
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

1
materia-client/README.md Normal file
View File

@ -0,0 +1 @@
# materia-client

View File

@ -0,0 +1,20 @@
[project]
name = "materia-client"
version = "0.1.0"
description = "Default template for PDM package"
authors = [
{name = "L-Nafaryus", email = "l.nafaryus@gmail.com"},
]
dependencies = [
"httpx>=0.27.0",
]
requires-python = ">=3.11"
readme = "README.md"
license = {text = "MIT"}
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[tool.pdm]
distribution = true

View File

@ -0,0 +1,13 @@
import click
@click.group()
def client():
click.echo("Hola!")
@client.command()
def test():
pass
if __name__ == "__main__":
client()

162
materia-server/.gitignore vendored Normal file
View File

@ -0,0 +1,162 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm-project.org/#use-with-ide
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

1
materia-server/README.md Normal file
View File

@ -0,0 +1 @@
# materia-server

View File

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

1814
materia-server/pdm.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
[project]
name = "materia-server"
version = "0.1.1"
description = "Materia is a file server"
authors = [
{name = "L-Nafaryus", email = "l.nafaryus@gmail.com"},
]
dependencies = [
"fastapi<1.0.0,>=0.111.0",
"uvicorn[standard]<1.0.0,>=0.29.0",
"psycopg2-binary<3.0.0,>=2.9.9",
"toml<1.0.0,>=0.10.2",
"sqlalchemy[asyncio]<3.0.0,>=2.0.30",
"asyncpg<1.0.0,>=0.29.0",
"eventlet<1.0.0,>=0.36.1",
"bcrypt==4.1.2",
"pyjwt<3.0.0,>=2.8.0",
"requests<3.0.0,>=2.31.0",
"pillow<11.0.0,>=10.3.0",
"sqids<1.0.0,>=0.4.1",
"alembic<2.0.0,>=1.13.1",
"authlib<2.0.0,>=1.3.0",
"cryptography<43.0.0,>=42.0.7",
"redis[hiredis]<6.0.0,>=5.0.4",
"aiosmtplib<4.0.0,>=3.0.1",
"emails<1.0,>=0.6",
"pydantic-settings<3.0.0,>=2.2.1",
"email-validator<3.0.0,>=2.1.1",
"pydanclick<1.0.0,>=0.2.0",
"loguru<1.0.0,>=0.7.2",
"alembic-postgresql-enum<2.0.0,>=1.2.0",
"gunicorn>=22.0.0",
"uvicorn-worker>=0.2.0",
]
requires-python = "<3.12,>=3.10"
readme = "README.md"
license = {text = "MIT"}
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[project.scripts]
materia-server = "materia_server.main:server"
[tool.pyright]
reportGeneralTypeIssues = false
[tool.pytest.ini_options]
pythonpath = ["."]
testpaths = ["tests"]
[tool.pdm]
distribution = true
[tool.pdm.build]
includes = ["src/materia_server"]
[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"
[tool.pdm.dev-dependencies]
dev = [
"black<24.0.0,>=23.3.0",
"pytest<8.0.0,>=7.3.2",
"pyflakes<4.0.0,>=3.0.1",
"pyright<2.0.0,>=1.1.314",
"pytest-asyncio>=0.23.7",
]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,27 @@
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

@ -0,0 +1,3 @@
from materia_server.models.auth.source import LoginType, LoginSource
from materia_server.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 sqlalchemy.orm import mapped_column, Mapped, relationship
from pydantic import BaseModel, HttpUrl from pydantic import BaseModel, HttpUrl
from materia.models.base import Base from materia_server.models.base import Base
from materia.models.database import Database, Cache from materia_server.models.database import Database, Cache
from materia import security from materia_server import security
from materia.models import user from materia_server.models import user
class OAuth2Application(Base): class OAuth2Application(Base):
__tablename__ = "oauth2_application" __tablename__ = "oauth2_application"

View File

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

View File

@ -0,0 +1,2 @@
from materia_server.models.database.database import DatabaseError, DatabaseMigrationError, Database
from materia_server.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.runtime.migration import MigrationContext
from alembic.script.base import ScriptDirectory from alembic.script.base import ScriptDirectory
from materia.config import Config from materia_server.config import Config
from materia.models.base import Base from materia_server.models.base import Base
__all__ = ["Database"] __all__ = ["Database"]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,13 +1,11 @@
from fastapi import APIRouter, Depends, HTTPException, status, Response from fastapi import APIRouter, Depends, HTTPException, status, Response
from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse
from PIL import Image from PIL import Image
import io import io
from pathlib import Path
import mimetypes
from materia.routers import middleware from materia_server.routers import middleware
from materia.config import Config from materia_server.config import Config
import materia_frontend
router = APIRouter(tags=["resources"], prefix="/resources") router = APIRouter(tags=["resources"], prefix="/resources")
@ -39,18 +37,3 @@ async def avatar(
) )
return Response(content=buffer.getvalue(), media_type=Image.MIME[format]) 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,3 @@
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

View File

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

View File

View File

@ -5,7 +5,7 @@
groups = ["default", "dev"] groups = ["default", "dev"]
strategy = ["cross_platform", "inherit_metadata"] strategy = ["cross_platform", "inherit_metadata"]
lock_version = "4.4.1" lock_version = "4.4.1"
content_hash = "sha256:4122146bc4848501b79e4e97551c7835f5559cc7294aa8ec3161a9c2fd86985f" content_hash = "sha256:a13078a66bba4903a78f4696c35b0e4119ad088dccf81088aa3bf8803e650b85"
[[package]] [[package]]
name = "black" name = "black"
@ -63,14 +63,14 @@ files = [
[[package]] [[package]]
name = "exceptiongroup" name = "exceptiongroup"
version = "1.2.2" version = "1.2.1"
requires_python = ">=3.7" requires_python = ">=3.7"
summary = "Backport of PEP 654 (exception groups)" summary = "Backport of PEP 654 (exception groups)"
groups = ["dev"] groups = ["dev"]
marker = "python_version < \"3.11\"" marker = "python_version < \"3.11\""
files = [ files = [
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"},
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"},
] ]
[[package]] [[package]]
@ -110,15 +110,26 @@ files = [
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
] ]
[[package]]
name = "nodeenv"
version = "1.9.0"
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
summary = "Node.js virtual environment builder"
groups = ["dev"]
files = [
{file = "nodeenv-1.9.0-py2.py3-none-any.whl", hash = "sha256:508ecec98f9f3330b636d4448c0f1a56fc68017c68f1e7857ebc52acf0eb879a"},
{file = "nodeenv-1.9.0.tar.gz", hash = "sha256:07f144e90dae547bf0d4ee8da0ee42664a42a04e02ed68e06324348dafe4bdb1"},
]
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "24.1" version = "24.0"
requires_python = ">=3.8" requires_python = ">=3.7"
summary = "Core utilities for Python packages" summary = "Core utilities for Python packages"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
] ]
[[package]] [[package]]
@ -165,6 +176,20 @@ files = [
{file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"},
] ]
[[package]]
name = "pyright"
version = "1.1.365"
requires_python = ">=3.7"
summary = "Command line wrapper for pyright"
groups = ["dev"]
dependencies = [
"nodeenv>=1.6.0",
]
files = [
{file = "pyright-1.1.365-py3-none-any.whl", hash = "sha256:194d767a039f9034376b7ec8423841880ac6efdd061f3e283b4ad9fcd484a659"},
{file = "pyright-1.1.365.tar.gz", hash = "sha256:d7e69000939aed4bf823707086c30c84c005bdd39fac2dfb370f0e5be16c2ef2"},
]
[[package]] [[package]]
name = "pytest" name = "pytest"
version = "7.4.4" version = "7.4.4"
@ -198,14 +223,14 @@ files = [
[[package]] [[package]]
name = "typing-extensions" name = "typing-extensions"
version = "4.12.2" version = "4.12.1"
requires_python = ">=3.8" requires_python = ">=3.8"
summary = "Backported and Experimental Type Hints for Python 3.8+" summary = "Backported and Experimental Type Hints for Python 3.8+"
groups = ["dev"] groups = ["dev"]
marker = "python_version < \"3.11\"" marker = "python_version < \"3.11\""
files = [ files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.1-py3-none-any.whl", hash = "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, {file = "typing_extensions-4.12.1.tar.gz", hash = "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1"},
] ]
[[package]] [[package]]

View File

@ -1,7 +1,7 @@
[project] [project]
name = "materia-frontend" name = "materia-web-client"
version = "0.1.1" version = "0.1.1"
description = "Materia frontend" description = "Materia web client"
authors = [ authors = [
{name = "L-Nafaryus", email = "l.nafaryus@gmail.com"}, {name = "L-Nafaryus", email = "l.nafaryus@gmail.com"},
] ]
@ -23,14 +23,13 @@ dev = [
] ]
[tool.pdm.build] [tool.pdm.build]
includes = [ "src/materia_frontend" ] includes = ["src/materia_web_client", "src/materia-frontend/dist"]
[tool.pdm.scripts] [tool.pdm.scripts]
npm-install.cmd = "npm install --prefix ./" npm-install.cmd = "npm install --prefix ./src/materia-frontend"
npm-run-build.cmd = "npm run build --prefix ./" npm-run-build.cmd = "npm run build-only --prefix ./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" ]
pre_build.composite = [ "npm-install", "npm-run-build", "move-dist" ] materia-web-client.call = "materia_web_client.main:client"
materia-frontend.call = "materia_frontend.main:client"
[build-system] [build-system]
requires = ["pdm-backend"] requires = ["pdm-backend"]

View File

@ -1,12 +1,12 @@
{ {
"name": "materia-frontend", "name": "materia-frontend",
"version": "0.0.5", "version": "0.0.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "materia-frontend", "name": "materia-frontend",
"version": "0.0.5", "version": "0.0.1",
"dependencies": { "dependencies": {
"@catppuccin/tailwindcss": "^0.1.6", "@catppuccin/tailwindcss": "^0.1.6",
"autoprefixer": "^10.4.18", "autoprefixer": "^10.4.18",
@ -26,7 +26,7 @@
"npm-run-all2": "^6.1.1", "npm-run-all2": "^6.1.1",
"typescript": "~5.3.0", "typescript": "~5.3.0",
"vite": "^5.0.10", "vite": "^5.0.10",
"vue-tsc": "^2.0.29" "vue-tsc": "^1.8.25"
} }
}, },
"node_modules/@alloc/quick-lru": { "node_modules/@alloc/quick-lru": {
@ -1183,29 +1183,31 @@
} }
}, },
"node_modules/@volar/language-core": { "node_modules/@volar/language-core": {
"version": "2.4.0-alpha.18", "version": "1.11.1",
"resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.0-alpha.18.tgz", "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz",
"integrity": "sha512-JAYeJvYQQROmVRtSBIczaPjP3DX4QW1fOqW1Ebs0d3Y3EwSNRglz03dSv0Dm61dzd0Yx3WgTW3hndDnTQqgmyg==", "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/source-map": "2.4.0-alpha.18" "@volar/source-map": "1.11.1"
} }
}, },
"node_modules/@volar/source-map": { "node_modules/@volar/source-map": {
"version": "2.4.0-alpha.18", "version": "1.11.1",
"resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.0-alpha.18.tgz", "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz",
"integrity": "sha512-MTeCV9MUwwsH0sNFiZwKtFrrVZUK6p8ioZs3xFzHc2cvDXHWlYN3bChdQtwKX+FY2HG6H3CfAu1pKijolzIQ8g==", "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==",
"dev": true
},
"node_modules/@volar/typescript": {
"version": "2.4.0-alpha.18",
"resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.0-alpha.18.tgz",
"integrity": "sha512-sXh5Y8sqGUkgxpMWUGvRXggxYHAVxg0Pa1C42lQZuPDrW6vHJPR0VCK8Sr7WJsAW530HuNQT/ZIskmXtxjybMQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/language-core": "2.4.0-alpha.18", "muggle-string": "^0.3.1"
"path-browserify": "^1.0.1", }
"vscode-uri": "^3.0.8" },
"node_modules/@volar/typescript": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz",
"integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==",
"dev": true,
"dependencies": {
"@volar/language-core": "1.11.1",
"path-browserify": "^1.0.1"
} }
}, },
"node_modules/@vue/babel-helper-vue-transform-on": { "node_modules/@vue/babel-helper-vue-transform-on": {
@ -1303,35 +1305,26 @@
"@vue/shared": "3.4.21" "@vue/shared": "3.4.21"
} }
}, },
"node_modules/@vue/compiler-vue2": {
"version": "2.7.16",
"resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz",
"integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==",
"dev": true,
"dependencies": {
"de-indent": "^1.0.2",
"he": "^1.2.0"
}
},
"node_modules/@vue/devtools-api": { "node_modules/@vue/devtools-api": {
"version": "6.6.1", "version": "6.6.1",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz", "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz",
"integrity": "sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==" "integrity": "sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA=="
}, },
"node_modules/@vue/language-core": { "node_modules/@vue/language-core": {
"version": "2.0.29", "version": "1.8.27",
"resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.29.tgz", "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz",
"integrity": "sha512-o2qz9JPjhdoVj8D2+9bDXbaI4q2uZTHQA/dbyZT4Bj1FR9viZxDJnLcKVHfxdn6wsOzRgpqIzJEEmSSvgMvDTQ==", "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/language-core": "~2.4.0-alpha.18", "@volar/language-core": "~1.11.1",
"@vue/compiler-dom": "^3.4.0", "@volar/source-map": "~1.11.1",
"@vue/compiler-vue2": "^2.7.16", "@vue/compiler-dom": "^3.3.0",
"@vue/shared": "^3.4.0", "@vue/shared": "^3.3.0",
"computeds": "^0.0.1", "computeds": "^0.0.1",
"minimatch": "^9.0.3", "minimatch": "^9.0.3",
"muggle-string": "^0.4.1", "muggle-string": "^0.3.1",
"path-browserify": "^1.0.1" "path-browserify": "^1.0.1",
"vue-template-compiler": "^2.7.14"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "*" "typescript": "*"
@ -2292,9 +2285,9 @@
"dev": true "dev": true
}, },
"node_modules/muggle-string": { "node_modules/muggle-string": {
"version": "0.4.1", "version": "0.3.1",
"resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz",
"integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==",
"dev": true "dev": true
}, },
"node_modules/mz": { "node_modules/mz": {
@ -3201,12 +3194,6 @@
} }
} }
}, },
"node_modules/vscode-uri": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
"integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==",
"dev": true
},
"node_modules/vue": { "node_modules/vue": {
"version": "3.4.21", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz",
@ -3241,21 +3228,31 @@
"vue": "^3.2.0" "vue": "^3.2.0"
} }
}, },
"node_modules/vue-tsc": { "node_modules/vue-template-compiler": {
"version": "2.0.29", "version": "2.7.16",
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.29.tgz", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz",
"integrity": "sha512-MHhsfyxO3mYShZCGYNziSbc63x7cQ5g9kvijV7dRe1TTXBRLxXyL0FnXWpUF1xII2mJ86mwYpYsUmMwkmerq7Q==", "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@volar/typescript": "~2.4.0-alpha.18", "de-indent": "^1.0.2",
"@vue/language-core": "2.0.29", "he": "^1.2.0"
}
},
"node_modules/vue-tsc": {
"version": "1.8.27",
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz",
"integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==",
"dev": true,
"dependencies": {
"@volar/typescript": "~1.11.1",
"@vue/language-core": "1.8.27",
"semver": "^7.5.4" "semver": "^7.5.4"
}, },
"bin": { "bin": {
"vue-tsc": "bin/vue-tsc.js" "vue-tsc": "bin/vue-tsc.js"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=5.0.0" "typescript": "*"
} }
}, },
"node_modules/vue-tsc/node_modules/lru-cache": { "node_modules/vue-tsc/node_modules/lru-cache": {

View File

@ -1,6 +1,6 @@
{ {
"name": "materia-frontend", "name": "materia-frontend",
"version": "0.0.5", "version": "0.0.1",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
@ -29,6 +29,6 @@
"npm-run-all2": "^6.1.1", "npm-run-all2": "^6.1.1",
"typescript": "~5.3.0", "typescript": "~5.3.0",
"vite": "^5.0.10", "vite": "^5.0.10",
"vue-tsc": "^2.0.29" "vue-tsc": "^1.8.25"
} }
} }

Some files were not shown because too many files have changed in this diff Show More