Compare commits
No commits in common. "devel" and "master" have entirely different histories.
1
.gitignore
vendored
@ -1,7 +1,6 @@
|
||||
/result*
|
||||
/repl-result*
|
||||
temp/
|
||||
.tmp
|
||||
|
||||
dist/
|
||||
/.venv
|
||||
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
@ -15,7 +15,7 @@
|
||||
<strong><em>Materia is a simple and fast cloud storage</em></strong>
|
||||
</p>
|
||||
|
||||
**Documentation**: [https://materia.elnafo.ru/docs](https://materia.elnafo.ru/docs)
|
||||
**Documentation**: [https://storage.elnafo.ru/docs](https://storage.elnafo.ru/docs)
|
||||
|
||||
**Source**: [https://vcs.elnafo.ru/L-Nafaryus/materia](https://vcs.elnafo.ru/L-Nafaryus/materia)
|
||||
|
||||
@ -148,4 +148,4 @@ pdm build
|
||||
|
||||
## License
|
||||
|
||||
**materia** is licensed under the terms of the [MIT License](https://vcs.elnafo.ru/L-Nafaryus/materia/src/branch/master/LICENSE).
|
||||
**materia** is licensed under the terms of the [MIT License](LICENSE).
|
1
docs/reference/app.md
Normal file
@ -0,0 +1 @@
|
||||
::: materia.app
|
1
docs/reference/core.md
Normal file
@ -0,0 +1 @@
|
||||
::: materia.core
|
1
docs/reference/models.md
Normal file
@ -0,0 +1 @@
|
||||
::: materia.models
|
1
docs/reference/routers.md
Normal file
@ -0,0 +1 @@
|
||||
::: materia.routers
|
1
docs/reference/security.md
Normal file
@ -0,0 +1 @@
|
||||
::: materia.security
|
1
docs/reference/tasks.md
Normal file
@ -0,0 +1 @@
|
||||
::: materia.tasks
|
16
flake.lock
@ -207,21 +207,6 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-std": {
|
||||
"locked": {
|
||||
"lastModified": 1710870712,
|
||||
"narHash": "sha256-e+7MJF2gsgTBuOWv4mCimSP0D9+naeFSw9a7N3yEmv4=",
|
||||
"owner": "chessai",
|
||||
"repo": "nix-std",
|
||||
"rev": "31bbc925750cc9d8f828fe55cee1a2bd985e0c00",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "chessai",
|
||||
"repo": "nix-std",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-mailserver": {
|
||||
"inputs": {
|
||||
"blobs": "blobs",
|
||||
@ -452,7 +437,6 @@
|
||||
"inputs": {
|
||||
"bonfire": "bonfire",
|
||||
"dream2nix": "dream2nix",
|
||||
"nix-std": "nix-std",
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
}
|
||||
},
|
||||
|
547
flake.nix
@ -8,7 +8,6 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
bonfire.url = "github:L-Nafaryus/bonfire";
|
||||
nix-std.url = "github:chessai/nix-std";
|
||||
};
|
||||
|
||||
outputs = {
|
||||
@ -16,7 +15,6 @@
|
||||
nixpkgs,
|
||||
dream2nix,
|
||||
bonfire,
|
||||
nix-std,
|
||||
...
|
||||
}: let
|
||||
system = "x86_64-linux";
|
||||
@ -45,6 +43,45 @@
|
||||
// {inherit meta;};
|
||||
in {
|
||||
packages.x86_64-linux = {
|
||||
materia-server = dreamBuildPackage {
|
||||
module = {
|
||||
config,
|
||||
lib,
|
||||
dream2nix,
|
||||
...
|
||||
}: {
|
||||
imports = [dream2nix.modules.dream2nix.WIP-python-pdm];
|
||||
|
||||
pdm.lockfile = ./pdm.lock;
|
||||
pdm.pyproject = ./pyproject.toml;
|
||||
|
||||
deps = _: {
|
||||
python = pkgs.python312;
|
||||
};
|
||||
|
||||
mkDerivation = {
|
||||
src = ./.;
|
||||
buildInputs = [
|
||||
pkgs.python312.pkgs.pdm-backend
|
||||
];
|
||||
nativeBuildInputs = [
|
||||
pkgs.python312.pkgs.wrapPython
|
||||
];
|
||||
configurePhase = ''
|
||||
${lib.getExe pkgs.mkdocs} build -d src/materia/docs/
|
||||
'';
|
||||
# TODO: include docs
|
||||
};
|
||||
};
|
||||
meta = with nixpkgs.lib; {
|
||||
description = "Materia";
|
||||
license = licenses.mit;
|
||||
maintainers = with bonLib.maintainers; [L-Nafaryus];
|
||||
broken = false;
|
||||
mainProgram = "materia";
|
||||
};
|
||||
};
|
||||
|
||||
materia-frontend-vue = dreamBuildPackage {
|
||||
module = {
|
||||
lib,
|
||||
@ -60,7 +97,11 @@
|
||||
];
|
||||
|
||||
mkDerivation = {
|
||||
src = ./packages/frontend;
|
||||
src = ./workspaces/frontend;
|
||||
configurePhase = ''
|
||||
${self.packages.x86_64-linux.materia-server}/bin/materia export openapi --path ./
|
||||
npm run openapi
|
||||
'';
|
||||
};
|
||||
|
||||
deps = {nixpkgs, ...}: {
|
||||
@ -76,8 +117,7 @@
|
||||
};
|
||||
};
|
||||
meta = with nixpkgs.lib; {
|
||||
description = "Materia is a simple and fast cloud storage (vue)";
|
||||
homepage = "https://materia.elnafo.ru";
|
||||
description = "Materia frontend (nodejs)";
|
||||
license = licenses.mit;
|
||||
maintainers = with bonLib.maintainers; [L-Nafaryus];
|
||||
broken = false;
|
||||
@ -97,128 +137,70 @@
|
||||
}: {
|
||||
imports = [dream2nix.modules.dream2nix.WIP-python-pdm];
|
||||
|
||||
pdm.lockfile = ./pdm.lock;
|
||||
pdm.pyproject = ./packages/frontend/pyproject.toml;
|
||||
pdm.lockfile = ./workspaces/frontend/pdm.lock;
|
||||
pdm.pyproject = ./workspaces/frontend/pyproject.toml;
|
||||
|
||||
deps = _: {
|
||||
python = pkgs.python312;
|
||||
};
|
||||
|
||||
mkDerivation = {
|
||||
src = ./packages/frontend;
|
||||
src = ./workspaces/frontend;
|
||||
buildInputs = [
|
||||
pkgs.python312.pkgs.pdm-backend
|
||||
];
|
||||
configurePhase = ''
|
||||
mkdir -p target/materia_frontend
|
||||
cp -rv ${materia-frontend-vue}/dist/* ./target/materia_frontend/
|
||||
cp -rv templates ./target/materia_frontend/
|
||||
touch target/materia_frontend/__init__.py
|
||||
cp -rv ${materia-frontend-vue}/dist ./src/materia_frontend/
|
||||
'';
|
||||
};
|
||||
};
|
||||
meta = with nixpkgs.lib; {
|
||||
description = "Materia is a simple and fast cloud storage (frontend)";
|
||||
homepage = "https://materia.elnafo.ru";
|
||||
description = "Materia frontend";
|
||||
license = licenses.mit;
|
||||
maintainers = with bonLib.maintainers; [L-Nafaryus];
|
||||
broken = false;
|
||||
};
|
||||
};
|
||||
|
||||
materia-server = pkgs.callPackage ({
|
||||
withFrontend ? true,
|
||||
withDocs ? true,
|
||||
...
|
||||
}:
|
||||
dreamBuildPackage {
|
||||
extraArgs = {
|
||||
inherit (self.packages.x86_64-linux) materia-frontend materia-docs;
|
||||
};
|
||||
module = {
|
||||
config,
|
||||
lib,
|
||||
dream2nix,
|
||||
materia-frontend,
|
||||
materia-docs,
|
||||
...
|
||||
}: {
|
||||
imports = [dream2nix.modules.dream2nix.WIP-python-pdm];
|
||||
|
||||
pdm.lockfile = ./pdm.lock;
|
||||
pdm.pyproject = ./packages/server/pyproject.toml;
|
||||
|
||||
deps = _: {
|
||||
python = pkgs.python312;
|
||||
};
|
||||
|
||||
mkDerivation = {
|
||||
src = ./packages/server;
|
||||
buildInputs = [
|
||||
pkgs.python312.pkgs.pdm-backend
|
||||
];
|
||||
nativeBuildInputs = [
|
||||
pkgs.python312.pkgs.wrapPython
|
||||
];
|
||||
propagatedBuildInputs =
|
||||
lib.optionals withFrontend [
|
||||
materia-frontend
|
||||
]
|
||||
++ lib.optionals withDocs [materia-docs];
|
||||
};
|
||||
};
|
||||
meta = with nixpkgs.lib; {
|
||||
description = "Materia is a simple and fast cloud storage";
|
||||
homepage = "https://materia.elnafo.ru";
|
||||
license = licenses.mit;
|
||||
maintainers = with bonLib.maintainers; [L-Nafaryus];
|
||||
broken = false;
|
||||
mainProgram = "materia";
|
||||
};
|
||||
}) {};
|
||||
|
||||
materia-docs = dreamBuildPackage {
|
||||
materia = dreamBuildPackage {
|
||||
extraArgs = {
|
||||
materia-server = self.packages.x86_64-linux.materia-server.override {
|
||||
withFrontend = false;
|
||||
withDocs = false;
|
||||
};
|
||||
inherit (self.packages.x86_64-linux) materia-frontend;
|
||||
};
|
||||
module = {
|
||||
config,
|
||||
lib,
|
||||
dream2nix,
|
||||
materia-server,
|
||||
materia-frontend,
|
||||
...
|
||||
}: {
|
||||
imports = [dream2nix.modules.dream2nix.WIP-python-pdm];
|
||||
|
||||
pdm.lockfile = ./pdm.lock;
|
||||
pdm.pyproject = ./packages/docs/pyproject.toml;
|
||||
pdm.pyproject = ./pyproject.toml;
|
||||
|
||||
deps = _: {
|
||||
python = pkgs.python312;
|
||||
};
|
||||
|
||||
mkDerivation = {
|
||||
src = ./packages/docs;
|
||||
src = ./.;
|
||||
buildInputs = [
|
||||
pkgs.python312.pkgs.pdm-backend
|
||||
];
|
||||
nativeBuildInputs = [pkgs.mkdocs materia-server];
|
||||
configurePhase = ''
|
||||
mkdir -p target/materia_docs
|
||||
mkdocs build
|
||||
touch target/materia_docs/__init__.py
|
||||
'';
|
||||
nativeBuildInputs = [
|
||||
pkgs.python312.pkgs.wrapPython
|
||||
];
|
||||
propagatedBuildInputs = [
|
||||
materia-frontend
|
||||
];
|
||||
};
|
||||
};
|
||||
meta = with nixpkgs.lib; {
|
||||
description = "Materia is a simple and fast cloud storage (docs)";
|
||||
homepage = "https://materia.elnafo.ru";
|
||||
description = "Materia";
|
||||
license = licenses.mit;
|
||||
maintainers = with bonLib.maintainers; [L-Nafaryus];
|
||||
broken = false;
|
||||
mainProgram = "materia";
|
||||
};
|
||||
};
|
||||
|
||||
@ -242,7 +224,7 @@
|
||||
pathsToLink = ["/bin" "/etc" "/"];
|
||||
paths = with pkgs; [
|
||||
bash
|
||||
self.packages.x86_64-linux.materia-server
|
||||
self.packages.x86_64-linux.materia
|
||||
entryPoint
|
||||
];
|
||||
};
|
||||
@ -275,406 +257,5 @@
|
||||
# greenlet requires libstdc++
|
||||
LD_LIBRARY_PATH = nixpkgs.lib.makeLibraryPath [pkgs.stdenv.cc.cc];
|
||||
};
|
||||
|
||||
nixosModules = rec {
|
||||
materia = {
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.services.materia;
|
||||
in {
|
||||
options.services.materia = {
|
||||
enable = mkEnableOption "Enables the Materia service";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = self.packages.x86_64-linux.materia-server;
|
||||
description = "The package to use.";
|
||||
};
|
||||
|
||||
application = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
mode = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
working_directory = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/materia";
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {
|
||||
user = "materia";
|
||||
group = "materia";
|
||||
mode = "production";
|
||||
working_directory = "/var/lib/materia";
|
||||
};
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
scheme = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
};
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {
|
||||
scheme = "http";
|
||||
address = "127.0.0.1";
|
||||
port = 54601;
|
||||
domain = "localhost";
|
||||
};
|
||||
};
|
||||
|
||||
database = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
backend = mkOption {
|
||||
type = types.str;
|
||||
default = "postgresql";
|
||||
};
|
||||
scheme = mkOption {
|
||||
type = types.str;
|
||||
default = "postgresql+asyncpg";
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 5432;
|
||||
};
|
||||
name = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "materia";
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "materia";
|
||||
};
|
||||
password = mkOption {
|
||||
type = types.nullOr (types.oneOf [types.str types.path]);
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {
|
||||
backend = "postgresql";
|
||||
scheme = "postgresql+asyncpg";
|
||||
address = "127.0.0.1";
|
||||
port = 5432;
|
||||
name = "materia";
|
||||
user = "materia";
|
||||
password = null;
|
||||
};
|
||||
};
|
||||
|
||||
cache = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
backend = mkOption {
|
||||
type = types.str;
|
||||
default = "redis";
|
||||
};
|
||||
scheme = mkOption {
|
||||
type = types.str;
|
||||
default = "redis";
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 6379;
|
||||
};
|
||||
database = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = 0;
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "materia";
|
||||
};
|
||||
password = mkOption {
|
||||
type = types.nullOr (types.oneOf [types.str types.path]);
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {
|
||||
backed = "redis";
|
||||
scheme = "redis";
|
||||
address = "127.0.0.1";
|
||||
port = 6379;
|
||||
database = 0;
|
||||
user = "materia";
|
||||
password = null;
|
||||
};
|
||||
};
|
||||
|
||||
security = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
secret_key = mkOption {
|
||||
type = types.nullOr (types.oneOf [types.str types.path]);
|
||||
};
|
||||
password_min_length = mkOption {
|
||||
type = types.int;
|
||||
};
|
||||
password_hash_algo = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
cookie_http_only = mkOption {
|
||||
type = types.bool;
|
||||
};
|
||||
cookie_access_token_name = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
cookie_refresh_token_name = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {
|
||||
secret_key = null;
|
||||
password_min_length = 8;
|
||||
password_hash_algo = "bcrypt";
|
||||
cookie_http_only = true;
|
||||
cookie_access_token_name = "materia_at";
|
||||
cookie_refresh_token_name = "materia_rt";
|
||||
};
|
||||
};
|
||||
|
||||
oauth2 = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
enabled = mkOption {
|
||||
type = types.bool;
|
||||
};
|
||||
jwt_signing_algo = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
jwt_singing_key = mkOption {
|
||||
type = types.nullOr (types.oneOf [types.str types.path]);
|
||||
};
|
||||
jwt_secret = mkOption {
|
||||
type = types.nullOr (types.oneOf [types.str types.path]);
|
||||
};
|
||||
access_token_lifetime = mkOption {
|
||||
type = types.int;
|
||||
};
|
||||
refresh_token_lifetime = mkOption {
|
||||
type = types.int;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {
|
||||
enabled = true;
|
||||
jwt_signing_algo = "HS256";
|
||||
jwt_singing_key = null;
|
||||
jwt_secret = "changeme";
|
||||
access_token_lifetime = 3600;
|
||||
refresh_token_lifetime = 730 * 60;
|
||||
};
|
||||
};
|
||||
|
||||
mailer = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
scheme = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
};
|
||||
helo = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
cert_file = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
};
|
||||
key_file = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
};
|
||||
sender = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
password = mkOption {
|
||||
type = types.nullOr (types.oneOf [types.str types.path]);
|
||||
default = null;
|
||||
};
|
||||
plain_text = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
|
||||
cron = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
workers_count = mkOption {
|
||||
type = types.int;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {
|
||||
workers_count = 1;
|
||||
};
|
||||
};
|
||||
|
||||
repository = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
capacity = mkOption {
|
||||
type = types.int;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {capacity = 5368709120;};
|
||||
};
|
||||
|
||||
misc = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
enable_client = mkOption {
|
||||
type = types.bool;
|
||||
};
|
||||
enable_docs = mkOption {
|
||||
type = types.bool;
|
||||
};
|
||||
enable_api_docs = mkOption {
|
||||
type = types.bool;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {
|
||||
enable_client = true;
|
||||
enable_docs = true;
|
||||
enable_api_docs = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users.users.materia = {
|
||||
description = "Materia service user";
|
||||
home = cfg.application.working_directory;
|
||||
createHome = true;
|
||||
isSystemUser = true;
|
||||
group = "materia";
|
||||
};
|
||||
users.groups.materia = {};
|
||||
|
||||
systemd.services.materia = {
|
||||
description = "Materia service";
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target"];
|
||||
|
||||
serviceConfig = {
|
||||
Restart = "always";
|
||||
ExecStart = "${lib.getExe cfg.package} start";
|
||||
User = "materia";
|
||||
WorkingDirectory = cfg.application.working_directory;
|
||||
};
|
||||
|
||||
preStart = let
|
||||
toTOML = nix-std.lib.serde.toTOML;
|
||||
configFile = pkgs.writeText "config.toml" ''
|
||||
${toTOML {inherit (cfg) application server database cache security oauth2 mailer cron repository misc;}}
|
||||
'';
|
||||
in ''
|
||||
ln -sf ${configFile} ${cfg.application.working_directory}/config.toml
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nixosConfigurations.materia = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
self.nixosModules.materia
|
||||
({
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
boot.isContainer = true;
|
||||
|
||||
networking.hostName = "materia";
|
||||
networking.useDHCP = false;
|
||||
|
||||
services.redis.servers.materia = {
|
||||
enable = true;
|
||||
port = 6379;
|
||||
databases = 1;
|
||||
};
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
enableTCPIP = true;
|
||||
authentication = ''
|
||||
host materia all 127.0.0.1/32 trust
|
||||
'';
|
||||
initialScript = pkgs.writeText "init" ''
|
||||
CREATE ROLE materia WITH LOGIN PASSWORD 'test';
|
||||
CREATE DATABASE materia OWNER materia;
|
||||
'';
|
||||
ensureDatabases = ["materia"];
|
||||
};
|
||||
|
||||
services.materia = {
|
||||
enable = true;
|
||||
cache.port = config.services.redis.servers.materia.port;
|
||||
database.password = "test";
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
})
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
docs_dir: src
|
||||
site_dir: target/materia_docs
|
||||
|
||||
site_name: Materia Documentation
|
||||
site_description: Materia cloud storage
|
||||
#site_url:
|
||||
@ -56,7 +53,7 @@ plugins:
|
||||
- mkdocstrings:
|
||||
handlers:
|
||||
python:
|
||||
paths: [../server/src] # search packages in the src folder
|
||||
paths: [src] # search packages in the src folder
|
||||
options:
|
||||
extensions:
|
||||
- griffe_typingdoc
|
||||
@ -79,6 +76,18 @@ plugins:
|
||||
filters:
|
||||
- '!^_'
|
||||
|
||||
nav:
|
||||
- Materia: index.md
|
||||
- Reference:
|
||||
- reference/index.md
|
||||
- reference/app.md
|
||||
- reference/core.md
|
||||
- reference/models.md
|
||||
- reference/routers.md
|
||||
- reference/security.md
|
||||
- reference/tasks.md
|
||||
- API: api.md
|
||||
|
||||
markdown_extensions:
|
||||
# Python Markdown
|
||||
abbr:
|
||||
@ -122,20 +131,3 @@ markdown_extensions:
|
||||
pymdownx.blocks.details:
|
||||
pymdownx.blocks.tab:
|
||||
alternate_style: True
|
||||
|
||||
nav:
|
||||
- Usage:
|
||||
- Introduction: index.md
|
||||
- usage/getting-started.md
|
||||
- Reference:
|
||||
- reference/index.md
|
||||
- reference/app.md
|
||||
- reference/core.md
|
||||
- reference/models.md
|
||||
- reference/routers.md
|
||||
- reference/security.md
|
||||
- reference/tasks.md
|
||||
- Development:
|
||||
- devel/contrib.md
|
||||
- devel/local.md
|
||||
- API: api.md
|
1
packages/docs/.gitignore
vendored
@ -1 +0,0 @@
|
||||
/target
|
@ -1,40 +0,0 @@
|
||||
[project]
|
||||
name = "materia-docs"
|
||||
version = "0.1.1"
|
||||
description = "Materia documentation"
|
||||
authors = [
|
||||
{name = "L-Nafaryus", email = "l.nafaryus@gmail.com"},
|
||||
]
|
||||
dependencies = [
|
||||
"mkdocs-material>=9.5.38",
|
||||
"mkdocstrings-python>=1.11.1",
|
||||
"griffe-typingdoc>=0.2.7",
|
||||
"pymdown-extensions>=10.11",
|
||||
"black<24.0.0,>=23.3.0",
|
||||
]
|
||||
requires-python = ">=3.12,<3.13"
|
||||
license = {text = "MIT"}
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://materia.elnafo.ru"
|
||||
Repository = "https://github.com/L-Nafaryus/materia"
|
||||
Documentation = "https://materia.elnafo.ru/docs"
|
||||
|
||||
[build-system]
|
||||
requires = ["pdm-backend"]
|
||||
build-backend = "pdm.backend"
|
||||
|
||||
[tool.pdm]
|
||||
distribution = true
|
||||
|
||||
[tool.pdm.build]
|
||||
package-dir = "target"
|
||||
includes = ["target/materia_docs"]
|
||||
|
||||
[tool.pdm.scripts]
|
||||
# mkdocs creates "target/materia_docs"
|
||||
mkdocs-build.cmd = "mkdocs build"
|
||||
top-level.shell = "touch target/materia_docs/__init__.py"
|
||||
pre_build.composite = [ "mkdocs-build", "top-level" ]
|
||||
|
||||
doc.cmd = "mkdocs serve"
|
@ -1,58 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
First off, thanks for taking the time to contribute! Contributions include but are not restricted to:
|
||||
|
||||
- Reporting bugs
|
||||
- Contributing to code
|
||||
- Writing tests
|
||||
- Writing documentation
|
||||
|
||||
The following is a set of guidelines for contributing.
|
||||
|
||||
## A recommended flow of contributing to an Open Source project
|
||||
|
||||
This section is for beginners to OSS. If you are an experienced OSS developer, you can skip
|
||||
this section.
|
||||
|
||||
1. First, fork this project to your own namespace using the fork button at the top right of the repository page.
|
||||
2. Clone the **upstream** repository to local:
|
||||
```sh
|
||||
git clone https://github.com/L-Nafaryus/materia.git
|
||||
# Or if you prefer SSH clone:
|
||||
git clone git@github.com:L-Nafaryus/materia.git
|
||||
```
|
||||
3. Add the fork as a new remote:
|
||||
```sh
|
||||
git remote add fork https://github.com/yourname/materia.git
|
||||
git fetch fork
|
||||
```
|
||||
where `fork` is the remote name of the fork repository.
|
||||
|
||||
/// tip
|
||||
|
||||
1. Don't modify code on the master branch, the master branch should always keep track of origin/master.
|
||||
|
||||
To update master branch to date:
|
||||
|
||||
```sh
|
||||
git pull origin master
|
||||
# In rare cases that your local master branch diverges from the remote master:
|
||||
git fetch origin && git reset --hard master
|
||||
```
|
||||
|
||||
2. Create a new branch based on the up-to-date master branch for new patches.
|
||||
3. Create a Pull Request from that patch branch.
|
||||
|
||||
///
|
||||
|
||||
## Local development
|
||||
|
||||
See [Local development](./local.md)
|
||||
|
||||
## Code style
|
||||
|
||||
*Soon*
|
||||
|
||||
## Realease
|
||||
|
||||
*Soon*
|
@ -1,3 +0,0 @@
|
||||
# Local development
|
||||
|
||||
*Soon*
|
@ -1 +0,0 @@
|
||||
::: materia_server.app
|
@ -1 +0,0 @@
|
||||
::: materia_server.core
|
@ -1 +0,0 @@
|
||||
::: materia_server.models
|
@ -1 +0,0 @@
|
||||
::: materia_server.routers
|
@ -1 +0,0 @@
|
||||
::: materia_server.security
|
@ -1 +0,0 @@
|
||||
::: materia_server.tasks
|
@ -1 +0,0 @@
|
||||
# Getting started
|
@ -1,35 +0,0 @@
|
||||
[project]
|
||||
name = "materia-frontend"
|
||||
version = "0.1.2"
|
||||
description = "Materia is a simple and fast cloud storage (frontend)"
|
||||
authors = [
|
||||
{name = "L-Nafaryus", email = "l.nafaryus@gmail.com"},
|
||||
]
|
||||
requires-python = ">=3.12,<3.13"
|
||||
license = {text = "MIT"}
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://materia.elnafo.ru"
|
||||
Repository = "https://github.com/L-Nafaryus/materia"
|
||||
Documentation = "https://materia.elnafo.ru/docs"
|
||||
|
||||
[build-system]
|
||||
requires = ["pdm-backend"]
|
||||
build-backend = "pdm.backend"
|
||||
|
||||
[tool.pdm]
|
||||
distribution = true
|
||||
|
||||
[tool.pdm.build]
|
||||
package-dir = "target"
|
||||
includes = ["target/materia_frontend"]
|
||||
|
||||
[tool.pdm.scripts]
|
||||
npm-install.cmd = "npm install"
|
||||
openapi-client.cmd = "npm run openapi"
|
||||
npm-build.cmd = "npm run simple-build -- --outDir target/materia_frontend"
|
||||
top-level.shell = "touch target/materia_frontend/__init__.py"
|
||||
copy-templates.shell = "cp -r ./templates target/materia_frontend/"
|
||||
pre_build.composite = [ "npm-install", "openapi-client", "npm-build", "top-level", "copy-templates" ]
|
||||
|
||||
openapi-json.cmd = "pdm run -p ../server python -m materia_server export openapi --path ./openapi.json"
|
18
packages/server/.gitignore
vendored
@ -1,18 +0,0 @@
|
||||
/result*
|
||||
/repl-result*
|
||||
temp/
|
||||
|
||||
dist/
|
||||
/.venv
|
||||
__pycache__/
|
||||
*.egg-info
|
||||
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build
|
||||
|
||||
.pytest_cache
|
||||
.coverage
|
||||
|
||||
/site
|
||||
src/materia/docs
|
@ -1,114 +0,0 @@
|
||||
[project]
|
||||
name = "materia-server"
|
||||
version = "0.1.1"
|
||||
description = "Materia is a simple and fast cloud storage"
|
||||
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",
|
||||
"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",
|
||||
"httpx>=0.27.0",
|
||||
"cryptography>=43.0.0",
|
||||
"python-multipart>=0.0.9",
|
||||
"jinja2>=3.1.4",
|
||||
"aiofiles>=24.1.0",
|
||||
"aioshutil>=1.5",
|
||||
"Celery>=5.4.0",
|
||||
"streaming-form-data>=1.16.0",
|
||||
]
|
||||
requires-python = ">=3.12,<3.13"
|
||||
license = {text = "MIT"}
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://materia.elnafo.ru"
|
||||
Repository = "https://github.com/L-Nafaryus/materia"
|
||||
Documentation = "https://materia.elnafo.ru/docs"
|
||||
|
||||
[project.optional-dependencies]
|
||||
docs = [
|
||||
]
|
||||
frontend = [
|
||||
#"materia-frontend>=0.1.1",
|
||||
]
|
||||
all = [
|
||||
#"materia[frontend]",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["pdm-backend"]
|
||||
build-backend = "pdm.backend"
|
||||
|
||||
[project.scripts]
|
||||
materia = "materia_server.app.cli:cli"
|
||||
|
||||
[tool.pyright]
|
||||
reportGeneralTypeIssues = false
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
pythonpath = ["."]
|
||||
testpaths = ["tests"]
|
||||
|
||||
[tool.pdm]
|
||||
distribution = true
|
||||
|
||||
[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",
|
||||
"asgi-lifespan>=2.1.0",
|
||||
"pytest-cov>=5.0.0",
|
||||
]
|
||||
|
||||
[tool.pdm.build]
|
||||
package-dir = "src"
|
||||
includes = ["src/materia_server"]
|
||||
|
||||
[tool.pdm.scripts]
|
||||
start.cmd = "python ./src/materia/main.py {args:start --app-mode development --log-level debug}"
|
||||
setup.cmd = "psql -U postgres -h 127.0.0.1 -p 54320 -d postgres -c 'create role materia login;' -c 'create database materia owner materia;'"
|
||||
teardown.cmd = "psql -U postgres -h 127.0.0.1 -p 54320 -d postgres -c 'drop database materia;' -c 'drop role materia;'"
|
||||
rev.cmd = "alembic revision {args:--autogenerate}"
|
||||
upgrade.cmd = "alembic upgrade {args:head}"
|
||||
downgrade.cmd = "alembic downgrade {args:base}"
|
||||
remove-revs.shell = "rm -v ./src/materia/models/migrations/versions/*.py"
|
||||
|
||||
test.cmd = "pytest"
|
||||
coverage.cmd = "pytest --cov=src/materia_server"
|
||||
|
||||
[tool.pdm.resolution]
|
||||
respect-source-order = true
|
||||
|
||||
[[tool.pdm.source]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.org/simple"
|
||||
|
||||
[[tool.pdm.source]]
|
||||
name = "elnafo-vcs"
|
||||
url = "https://vcs.elnafo.ru/api/packages/L-Nafaryus/pypi"
|
||||
verify_ssl = true
|
@ -1,3 +0,0 @@
|
||||
from materia_server.app import cli
|
||||
|
||||
cli()
|
@ -1,2 +0,0 @@
|
||||
from materia_server.app.app import Context, Application
|
||||
from materia_server.app.cli import cli
|
@ -1,13 +0,0 @@
|
||||
from materia_server.core.logging import Logger, LoggerInstance, LogLevel, LogMode
|
||||
from materia_server.core.database import (
|
||||
DatabaseError,
|
||||
DatabaseMigrationError,
|
||||
Database,
|
||||
SessionMaker,
|
||||
SessionContext,
|
||||
ConnectionContext,
|
||||
)
|
||||
from materia_server.core.filesystem import FileSystem, FileSystemError, TemporaryFileTarget
|
||||
from materia_server.core.config import Config
|
||||
from materia_server.core.cache import Cache, CacheError
|
||||
from materia_server.core.cron import Cron, CronError
|
@ -1,3 +0,0 @@
|
||||
from materia_server.models.auth.source import LoginType, LoginSource
|
||||
|
||||
# from materia_server.models.auth.oauth2 import OAuth2Application, OAuth2Grant, OAuth2AuthorizationCode
|
@ -1 +0,0 @@
|
||||
from materia_server.routers import middleware, api, client, docs, api_docs
|
@ -1,40 +0,0 @@
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/api/docs", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def rapidoc(request: Request):
|
||||
return f"""
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
|
||||
<script
|
||||
type="module"
|
||||
src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"
|
||||
></script>
|
||||
</head>
|
||||
<body>
|
||||
<rapi-doc
|
||||
spec-url="{request.app.openapi_url}"
|
||||
theme = "dark"
|
||||
show-header = "false"
|
||||
show-info = "true"
|
||||
allow-authentication = "true"
|
||||
allow-server-selection = "true"
|
||||
allow-api-list-style-selection = "true"
|
||||
theme = "dark"
|
||||
render-style = "focused"
|
||||
bg-color="#1e2129"
|
||||
primary-color="#a47bea"
|
||||
regular-font="Roboto"
|
||||
mono-font="Roboto Mono"
|
||||
show-method-in-nav-bar="as-colored-text">
|
||||
<img slot="logo" style="display: none"/>
|
||||
</rapi-doc>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
@ -1,33 +0,0 @@
|
||||
from pathlib import Path
|
||||
from fastapi import APIRouter, Request, Response, status
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
import mimetypes
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
try:
|
||||
import materia_frontend
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
else:
|
||||
|
||||
templates = Jinja2Templates(
|
||||
directory=Path(materia_frontend.__path__[0], "templates")
|
||||
)
|
||||
|
||||
@router.get("/assets/{filename}")
|
||||
async def assets(filename: str, include_in_schema=False):
|
||||
path = Path(materia_frontend.__path__[0]).joinpath("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)
|
||||
|
||||
@router.get("/{spa:path}", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def root(request: Request):
|
||||
return templates.TemplateResponse(request, "base.html", {"view": "app"})
|
@ -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
|
@ -1 +0,0 @@
|
||||
from materia_server.tasks.file import remove_cache_file
|
@ -5,14 +5,66 @@ description = "Materia is a simple and fast cloud storage"
|
||||
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",
|
||||
"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",
|
||||
"httpx>=0.27.0",
|
||||
"cryptography>=43.0.0",
|
||||
"python-multipart>=0.0.9",
|
||||
"jinja2>=3.1.4",
|
||||
"aiofiles>=24.1.0",
|
||||
"aioshutil>=1.5",
|
||||
"Celery>=5.4.0",
|
||||
"streaming-form-data>=1.16.0",
|
||||
]
|
||||
requires-python = ">=3.12,<3.13"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
|
||||
[project.optional-dependencies]
|
||||
docs = [
|
||||
"mkdocs-material>=9.5.38",
|
||||
"mkdocstrings-python>=1.11.1",
|
||||
"griffe-typingdoc>=0.2.7",
|
||||
"pymdown-extensions>=10.11",
|
||||
]
|
||||
frontend = [
|
||||
"materia-frontend>=0.1.1",
|
||||
]
|
||||
all = [
|
||||
"materia[docs,frontend]",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["pdm-backend"]
|
||||
build-backend = "pdm.backend"
|
||||
|
||||
[project.scripts]
|
||||
|
||||
materia = "materia.app.cli:cli"
|
||||
|
||||
[tool.pyright]
|
||||
reportGeneralTypeIssues = false
|
||||
|
||||
@ -21,15 +73,34 @@ pythonpath = ["."]
|
||||
testpaths = ["tests"]
|
||||
|
||||
[tool.pdm]
|
||||
distribution = false
|
||||
distribution = true
|
||||
|
||||
[tool.pdm.dev-dependencies]
|
||||
dev = [
|
||||
"-e file:///${PROJECT_ROOT}/packages/server",
|
||||
"-e file:///${PROJECT_ROOT}/packages/frontend",
|
||||
"-e file:///${PROJECT_ROOT}/packages/docs",
|
||||
"-e file:///${PROJECT_ROOT}/workspaces/frontend",
|
||||
"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",
|
||||
"asgi-lifespan>=2.1.0",
|
||||
"pytest-cov>=5.0.0",
|
||||
]
|
||||
|
||||
[tool.pdm.build]
|
||||
includes = ["src/materia"]
|
||||
|
||||
[tool.pdm.scripts]
|
||||
start.cmd = "python ./src/materia/main.py {args:start --app-mode development --log-level debug}"
|
||||
setup.cmd = "psql -U postgres -h 127.0.0.1 -p 54320 -d postgres -c 'create role materia login;' -c 'create database materia owner materia;'"
|
||||
teardown.cmd = "psql -U postgres -h 127.0.0.1 -p 54320 -d postgres -c 'drop database materia;' -c 'drop role materia;'"
|
||||
rev.cmd = "alembic revision {args:--autogenerate}"
|
||||
upgrade.cmd = "alembic upgrade {args:head}"
|
||||
downgrade.cmd = "alembic downgrade {args:base}"
|
||||
remove-revs.shell = "rm -v ./src/materia/models/migrations/versions/*.py"
|
||||
docs.shell = "pdm run mkdocs build -d src/materia/docs/"
|
||||
pre_build.composite = [ "docs" ]
|
||||
|
||||
[tool.pdm.resolution]
|
||||
respect-source-order = true
|
||||
|
||||
|
3
src/materia/__main__.py
Normal file
@ -0,0 +1,3 @@
|
||||
from materia.app import cli
|
||||
|
||||
cli()
|
2
src/materia/app/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from materia.app.app import Context, Application
|
||||
from materia.app.cli import cli
|
@ -9,7 +9,7 @@ from fastapi import FastAPI
|
||||
from fastapi.routing import APIRoute
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from materia_server.core import (
|
||||
from materia.core import (
|
||||
Config,
|
||||
Logger,
|
||||
LoggerInstance,
|
||||
@ -17,8 +17,8 @@ from materia_server.core import (
|
||||
Cache,
|
||||
Cron,
|
||||
)
|
||||
from materia_server import routers
|
||||
from materia_server.core.misc import optional, optional_string
|
||||
from materia import routers
|
||||
from materia.core.misc import optional, optional_string
|
||||
|
||||
|
||||
class Context(TypedDict):
|
||||
@ -66,6 +66,13 @@ class Application:
|
||||
app.logger.error(" ".join(e.args))
|
||||
sys.exit()
|
||||
|
||||
try:
|
||||
import materia_frontend
|
||||
except ModuleNotFoundError:
|
||||
app.logger.warning(
|
||||
"`materia_frontend` is not installed. No user interface will be served."
|
||||
)
|
||||
|
||||
return app
|
||||
|
||||
def prepare_logger(self):
|
||||
@ -127,25 +134,10 @@ class Application:
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
self.backend.include_router(routers.docs.router)
|
||||
self.backend.include_router(routers.api.router)
|
||||
if self.config.misc.enable_api_docs:
|
||||
self.backend.include_router(routers.api_docs.router)
|
||||
if self.config.misc.enable_docs:
|
||||
try:
|
||||
import materia_docs
|
||||
except ModuleNotFoundError:
|
||||
self.logger.error(
|
||||
"The `misc.enable_docs` option was enabled but the `materia_docs` package was not found."
|
||||
)
|
||||
self.backend.include_router(routers.docs.router)
|
||||
if self.config.misc.enable_client:
|
||||
try:
|
||||
import materia_frontend
|
||||
except ModuleNotFoundError:
|
||||
self.logger.error(
|
||||
"The `misc.enable_client` option was enabled but the `materia_frontend` package was not found."
|
||||
)
|
||||
self.backend.include_router(routers.client.router)
|
||||
self.backend.include_router(routers.resources.router)
|
||||
self.backend.include_router(routers.root.router)
|
||||
|
||||
for route in self.backend.routes:
|
||||
if isinstance(route, APIRoute):
|
||||
@ -175,5 +167,5 @@ class Application:
|
||||
self.logger.info("Exiting...")
|
||||
sys.exit()
|
||||
except Exception as e:
|
||||
self.logger.exception(" ".join(e.args), backtrace=False)
|
||||
self.logger.error(" ".join(e.args))
|
||||
sys.exit()
|
@ -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):
|
@ -1,9 +1,9 @@
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import click
|
||||
from materia_server.core.config import Config
|
||||
from materia_server.core.logging import Logger
|
||||
from materia_server.app import Application
|
||||
from materia.core.config import Config
|
||||
from materia.core.logging import Logger
|
||||
from materia.app import Application
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
@ -42,6 +42,7 @@ def start(config: Path, debug: bool):
|
||||
config = Config.open(config_path)
|
||||
except Exception as e:
|
||||
logger.error("Failed to read configuration file: {}", e)
|
||||
else:
|
||||
logger.info("Using the default configuration.")
|
||||
config = Config()
|
||||
else:
|
||||
@ -133,9 +134,6 @@ def export_openapi(path: Path):
|
||||
path = path.resolve()
|
||||
logger = Logger.new()
|
||||
config = Config()
|
||||
config.misc.enable_client = False
|
||||
config.misc.enable_docs = False
|
||||
config.misc.enable_api_docs = False
|
||||
app = Application(config)
|
||||
app.prepare_server()
|
||||
|
13
src/materia/core/__init__.py
Normal file
@ -0,0 +1,13 @@
|
||||
from materia.core.logging import Logger, LoggerInstance, LogLevel, LogMode
|
||||
from materia.core.database import (
|
||||
DatabaseError,
|
||||
DatabaseMigrationError,
|
||||
Database,
|
||||
SessionMaker,
|
||||
SessionContext,
|
||||
ConnectionContext,
|
||||
)
|
||||
from materia.core.filesystem import FileSystem, FileSystemError, TemporaryFileTarget
|
||||
from materia.core.config import Config
|
||||
from materia.core.cache import Cache, CacheError
|
||||
from materia.core.cron import Cron, CronError
|
@ -3,7 +3,7 @@ from typing import Any, AsyncGenerator, Self
|
||||
from pydantic import RedisDsn
|
||||
from redis import asyncio as aioredis
|
||||
from redis.asyncio.client import Pipeline
|
||||
from materia_server.core.logging import Logger
|
||||
from materia.core.logging import Logger
|
||||
|
||||
|
||||
class CacheError(Exception):
|
@ -110,7 +110,7 @@ class OAuth2(BaseModel):
|
||||
# check if signing algo need a key or generate it | HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, EdDSA
|
||||
jwt_signing_key: Optional[Union[str, Path]] = None
|
||||
jwt_secret: Optional[Union[str, Path]] = (
|
||||
"changeme" # None # only for HS256, HS384, HS512 | generate
|
||||
"changeme" # None # only for HS256, HS384, HS512 | generate
|
||||
)
|
||||
access_token_lifetime: int = 3600
|
||||
refresh_token_lifetime: int = 730 * 60
|
||||
@ -136,9 +136,9 @@ class Mailer(BaseModel):
|
||||
cert_file: Optional[Path] = None
|
||||
key_file: Optional[Path] = None
|
||||
|
||||
sender: Optional[NameEmail] = None
|
||||
from_: Optional[NameEmail] = None
|
||||
user: Optional[str] = None
|
||||
password: Optional[Union[str, Path]] = None
|
||||
password: Optional[str] = None
|
||||
plain_text: bool = False
|
||||
|
||||
|
||||
@ -150,12 +150,6 @@ class Repository(BaseModel):
|
||||
capacity: int = 5 << 30
|
||||
|
||||
|
||||
class Misc(BaseModel):
|
||||
enable_client: bool = True
|
||||
enable_docs: bool = True
|
||||
enable_api_docs: bool = False
|
||||
|
||||
|
||||
class Config(BaseSettings, env_prefix="materia_", env_nested_delimiter="__"):
|
||||
application: Application = Application()
|
||||
log: Log = Log()
|
||||
@ -167,7 +161,6 @@ class Config(BaseSettings, env_prefix="materia_", env_nested_delimiter="__"):
|
||||
mailer: Mailer = Mailer()
|
||||
cron: Cron = Cron()
|
||||
repository: Repository = Repository()
|
||||
misc: Misc = Misc()
|
||||
|
||||
@staticmethod
|
||||
def open(path: Path) -> Self | None:
|
@ -2,7 +2,7 @@ from typing import Optional, Self
|
||||
from celery import Celery
|
||||
from pydantic import RedisDsn
|
||||
from threading import Thread
|
||||
from materia_server.core.logging import Logger
|
||||
from materia.core.logging import Logger
|
||||
|
||||
|
||||
class CronError(Exception):
|
@ -18,7 +18,7 @@ from alembic.runtime.migration import MigrationContext
|
||||
from alembic.script.base import ScriptDirectory
|
||||
import alembic_postgresql_enum
|
||||
from fastapi import HTTPException
|
||||
from materia_server.core.logging import Logger
|
||||
from materia.core.logging import Logger
|
||||
|
||||
|
||||
class DatabaseError(Exception):
|
||||
@ -111,7 +111,7 @@ class Database:
|
||||
await session.close()
|
||||
|
||||
def run_sync_migrations(self, connection: Connection):
|
||||
from materia_server.models.base import Base
|
||||
from materia.models.base import Base
|
||||
|
||||
aconfig = AlembicConfig()
|
||||
aconfig.set_main_option("sqlalchemy.url", str(self.url))
|
||||
@ -142,7 +142,7 @@ class Database:
|
||||
await connection.run_sync(self.run_sync_migrations) # type: ignore
|
||||
|
||||
def rollback_sync_migrations(self, connection: Connection):
|
||||
from materia_server.models.base import Base
|
||||
from materia.models.base import Base
|
||||
|
||||
aconfig = AlembicConfig()
|
||||
aconfig.set_main_option("sqlalchemy.url", str(self.url))
|
@ -8,7 +8,7 @@ import re
|
||||
from tempfile import NamedTemporaryFile
|
||||
from streaming_form_data.targets import BaseTarget
|
||||
from uuid import uuid4
|
||||
from materia_server.core.misc import optional
|
||||
from materia.core.misc import optional
|
||||
|
||||
|
||||
valid_path = re.compile(r"^/(.*/)*([^/]*)$")
|
@ -109,8 +109,8 @@ class Logger:
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"handlers": {
|
||||
"default": {"class": "materia_server.core.logging.InterceptHandler"},
|
||||
"access": {"class": "materia_server.core.logging.InterceptHandler"},
|
||||
"default": {"class": "materia.core.logging.InterceptHandler"},
|
||||
"access": {"class": "materia.core.logging.InterceptHandler"},
|
||||
},
|
||||
"loggers": {
|
||||
"uvicorn": {
|
@ -1,18 +1,18 @@
|
||||
from materia_server.models.auth import (
|
||||
from materia.models.auth import (
|
||||
LoginType,
|
||||
LoginSource,
|
||||
# OAuth2Application,
|
||||
# OAuth2Grant,
|
||||
# OAuth2AuthorizationCode,
|
||||
)
|
||||
from materia_server.models.user import User, UserCredentials, UserInfo
|
||||
from materia_server.models.repository import (
|
||||
from materia.models.user import User, UserCredentials, UserInfo
|
||||
from materia.models.repository import (
|
||||
Repository,
|
||||
RepositoryInfo,
|
||||
RepositoryContent,
|
||||
RepositoryError,
|
||||
)
|
||||
from materia_server.models.directory import (
|
||||
from materia.models.directory import (
|
||||
Directory,
|
||||
DirectoryLink,
|
||||
DirectoryInfo,
|
||||
@ -21,7 +21,7 @@ from materia_server.models.directory import (
|
||||
DirectoryRename,
|
||||
DirectoryCopyMove,
|
||||
)
|
||||
from materia_server.models.file import (
|
||||
from materia.models.file import (
|
||||
File,
|
||||
FileLink,
|
||||
FileInfo,
|
3
src/materia/models/auth/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
from materia.models.auth.source import LoginType, LoginSource
|
||||
|
||||
# from materia.models.auth.oauth2 import OAuth2Application, OAuth2Grant, OAuth2AuthorizationCode
|
@ -8,9 +8,9 @@ from sqlalchemy import BigInteger, ForeignKey, JSON, and_, select
|
||||
from sqlalchemy.orm import mapped_column, Mapped, relationship
|
||||
from pydantic import BaseModel, HttpUrl
|
||||
|
||||
from materia_server.models.base import Base
|
||||
from materia_server.core import Database, Cache
|
||||
from materia_server import security
|
||||
from materia.models.base import Base
|
||||
from materia.core import Database, Cache
|
||||
from materia import security
|
||||
|
||||
|
||||
class OAuth2Application(Base):
|
@ -4,7 +4,7 @@ from time import time
|
||||
from sqlalchemy import BigInteger
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from materia_server.models.base import Base
|
||||
from materia.models.base import Base
|
||||
|
||||
|
||||
class LoginType(enum.Enum):
|
@ -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.core import SessionContext, Config, FileSystem
|
||||
from materia.models.base import Base
|
||||
from materia.core import SessionContext, Config, FileSystem
|
||||
|
||||
|
||||
class DirectoryError(Exception):
|
||||
@ -306,5 +306,5 @@ class DirectoryCopyMove(BaseModel):
|
||||
force: Optional[bool] = False
|
||||
|
||||
|
||||
from materia_server.models.repository import Repository
|
||||
from materia_server.models.file import File, FileInfo
|
||||
from materia.models.repository import Repository
|
||||
from materia.models.file import File, FileInfo
|
@ -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.core import SessionContext, Config, FileSystem
|
||||
from materia.models.base import Base
|
||||
from materia.core import SessionContext, Config, FileSystem
|
||||
|
||||
|
||||
class FileError(Exception):
|
||||
@ -273,5 +273,5 @@ class FileCopyMove(BaseModel):
|
||||
force: Optional[bool] = False
|
||||
|
||||
|
||||
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
|
@ -8,13 +8,13 @@ from sqlalchemy.ext.asyncio import async_engine_from_config
|
||||
from alembic import context
|
||||
import alembic_postgresql_enum
|
||||
|
||||
from materia_server.core 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.core 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
|
@ -8,8 +8,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.core import SessionContext, Config
|
||||
from materia.models.base import Base
|
||||
from materia.core import SessionContext, Config
|
||||
|
||||
|
||||
class RepositoryError(Exception):
|
||||
@ -126,6 +126,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
|
@ -11,10 +11,10 @@ from PIL import Image
|
||||
from sqids.sqids import Sqids
|
||||
from aiofiles import os as async_os
|
||||
|
||||
from materia_server import security
|
||||
from materia_server.models.base import Base
|
||||
from materia_server.models.auth.source import LoginType
|
||||
from materia_server.core import SessionContext, Config, FileSystem
|
||||
from materia import security
|
||||
from materia.models.base import Base
|
||||
from materia.models.auth.source import LoginType
|
||||
from materia.core import SessionContext, Config, FileSystem
|
||||
|
||||
valid_username = re.compile(r"^[\da-zA-Z][-.\w]*$")
|
||||
invalid_username = re.compile(r"[-._]{2,}|[-._]$")
|
||||
@ -222,4 +222,4 @@ class UserInfo(BaseModel):
|
||||
avatar: Optional[str]
|
||||
|
||||
|
||||
from materia_server.models.repository import Repository
|
||||
from materia.models.repository import Repository
|
1
src/materia/routers/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from materia.routers import middleware, api, resources, root, docs
|
@ -1,6 +1,6 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from materia_server.routers.api.auth import auth, oauth
|
||||
from materia_server.routers.api import docs, user, repository, directory, file, avatar
|
||||
from materia.routers.api.auth import auth, oauth
|
||||
from materia.routers.api import docs, user, repository, directory, file
|
||||
|
||||
router = APIRouter(prefix="/api")
|
||||
router.include_router(docs.router)
|
||||
@ -10,7 +10,6 @@ router.include_router(user.router)
|
||||
router.include_router(repository.router)
|
||||
router.include_router(directory.router)
|
||||
router.include_router(file.router)
|
||||
router.include_router(avatar.router)
|
||||
|
||||
|
||||
@router.get("/api/{catchall:path}", status_code=404, include_in_schema=False)
|
@ -1,9 +1,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"])
|
||||
|
@ -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"])
|
@ -1,6 +1,6 @@
|
||||
from pathlib import Path
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from materia_server.models import (
|
||||
from materia.models import (
|
||||
User,
|
||||
Directory,
|
||||
DirectoryInfo,
|
||||
@ -10,8 +10,8 @@ from materia_server.models import (
|
||||
DirectoryCopyMove,
|
||||
Repository,
|
||||
)
|
||||
from materia_server.core import SessionContext, Config, FileSystem
|
||||
from materia_server.routers import middleware
|
||||
from materia.core import SessionContext, Config, FileSystem
|
||||
from materia.routers import middleware
|
||||
|
||||
router = APIRouter(tags=["directory"])
|
||||
|
@ -11,7 +11,7 @@ from fastapi import (
|
||||
Form,
|
||||
)
|
||||
from fastapi.responses import JSONResponse
|
||||
from materia_server.models import (
|
||||
from materia.models import (
|
||||
User,
|
||||
File,
|
||||
FileInfo,
|
||||
@ -20,20 +20,20 @@ from materia_server.models import (
|
||||
FileRename,
|
||||
FileCopyMove,
|
||||
)
|
||||
from materia_server.core import (
|
||||
from materia.core import (
|
||||
SessionContext,
|
||||
Config,
|
||||
FileSystem,
|
||||
TemporaryFileTarget,
|
||||
Database,
|
||||
)
|
||||
from materia_server.routers import middleware
|
||||
from materia_server.routers.api.directory import validate_target_directory
|
||||
from materia.routers import middleware
|
||||
from materia.routers.api.directory import validate_target_directory
|
||||
from streaming_form_data import StreamingFormDataParser
|
||||
from streaming_form_data.targets import ValueTarget
|
||||
from starlette.requests import ClientDisconnect
|
||||
from aiofiles import ospath as async_path
|
||||
from materia_server.tasks import remove_cache_file
|
||||
from materia.tasks import remove_cache_file
|
||||
|
||||
router = APIRouter(tags=["file"])
|
||||
|
@ -1,5 +1,5 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from materia_server.models import (
|
||||
from materia.models import (
|
||||
User,
|
||||
Repository,
|
||||
RepositoryInfo,
|
||||
@ -7,7 +7,7 @@ from materia_server.models import (
|
||||
FileInfo,
|
||||
DirectoryInfo,
|
||||
)
|
||||
from materia_server.routers import middleware
|
||||
from materia.routers import middleware
|
||||
|
||||
|
||||
router = APIRouter(tags=["repository"])
|
@ -1,8 +1,8 @@
|
||||
import uuid
|
||||
import io
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, UploadFile
|
||||
from materia_server.models import User, UserInfo
|
||||
from materia_server.routers import middleware
|
||||
from materia.models import User, UserInfo
|
||||
from materia.routers import middleware
|
||||
|
||||
|
||||
router = APIRouter(tags=["user"])
|
@ -1,23 +1,22 @@
|
||||
from fastapi import APIRouter, Request, status, HTTPException, Depends
|
||||
from fastapi.responses import FileResponse, RedirectResponse
|
||||
from fastapi import APIRouter, Request, Response, status, HTTPException, Depends
|
||||
from fastapi.responses import HTMLResponse, FileResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
import mimetypes
|
||||
from pathlib import Path
|
||||
from materia_server.core.misc import optional
|
||||
from materia_server.routers import middleware
|
||||
from materia.core.misc import optional
|
||||
from materia.routers import middleware
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
try:
|
||||
import materia_docs
|
||||
except ModuleNotFoundError:
|
||||
from materia import docs as materia_docs
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
|
||||
@router.get("/docs", include_in_schema=False)
|
||||
async def docs_root():
|
||||
return RedirectResponse(url="/docs/")
|
||||
|
||||
@router.get("/docs/{catchall:path}", include_in_schema=False)
|
||||
async def docs(request: Request, ctx: middleware.Context = Depends()):
|
||||
docs_directory = Path(materia_docs.__path__[0]).resolve()
|
@ -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:
|
@ -1,14 +1,16 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Response
|
||||
from PIL import Image
|
||||
import io
|
||||
from pathlib import Path
|
||||
import mimetypes
|
||||
|
||||
from materia_server.routers import middleware
|
||||
from materia_server.core import Config
|
||||
from materia.routers import middleware
|
||||
from materia.core import Config
|
||||
|
||||
router = APIRouter(tags=["avatar"], prefix="/avatar")
|
||||
router = APIRouter(tags=["resources"], prefix="/resources")
|
||||
|
||||
|
||||
@router.get("/{avatar_id}")
|
||||
@router.get("/avatars/{avatar_id}")
|
||||
async def avatar(
|
||||
avatar_id: str, format: str = "png", ctx: middleware.Context = Depends()
|
||||
):
|
||||
@ -35,3 +37,24 @@ async def avatar(
|
||||
)
|
||||
|
||||
return Response(content=buffer.getvalue(), media_type=Image.MIME[format])
|
||||
|
||||
|
||||
try:
|
||||
import materia_frontend
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
else:
|
||||
|
||||
@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)
|
19
src/materia/routers/root.py
Normal file
@ -0,0 +1,19 @@
|
||||
from pathlib import Path
|
||||
from fastapi import APIRouter, Request, HTTPException
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
|
||||
router = APIRouter(tags=["root"])
|
||||
|
||||
try:
|
||||
import materia_frontend
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
else:
|
||||
|
||||
templates = Jinja2Templates(directory=Path(materia_frontend.__path__[0]) / "dist")
|
||||
|
||||
@router.get("/{spa:path}", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def root(request: Request):
|
||||
# raise HTTPException(404)
|
||||
return templates.TemplateResponse(request, "base.html", {"view": "app"})
|
3
src/materia/security/__init__.py
Normal 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
|
1
src/materia/tasks/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from materia.tasks.file import remove_cache_file
|
@ -1,10 +1,10 @@
|
||||
from materia_server.core import Cron, CronError, SessionContext, Config, Database
|
||||
from materia.core import Cron, CronError, SessionContext, Config, Database
|
||||
from celery import shared_task
|
||||
from fastapi import UploadFile
|
||||
from materia_server.models import File
|
||||
from materia.models import File
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from materia_server.core import FileSystem, Config
|
||||
from materia.core import FileSystem, Config
|
||||
|
||||
|
||||
@shared_task(name="remove_cache_file")
|
0
tests/__init__.py
Normal file
@ -1,12 +1,12 @@
|
||||
import pytest_asyncio
|
||||
from materia_server.models import (
|
||||
from materia.models import (
|
||||
User,
|
||||
LoginType,
|
||||
)
|
||||
from materia_server.models.base import Base
|
||||
from materia_server import security
|
||||
from materia_server.app import Application
|
||||
from materia_server.core import Config, Database, Cache, Cron
|
||||
from materia.models.base import Base
|
||||
from materia import security
|
||||
from materia.app import Application
|
||||
from materia.core import Config, Database, Cache, Cron
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.pool import NullPool
|
||||
from httpx import AsyncClient, ASGITransport, Cookies
|
@ -1,5 +1,5 @@
|
||||
import pytest
|
||||
from materia_server.core import Config
|
||||
from materia.core import Config
|
||||
from httpx import AsyncClient, Cookies
|
||||
from io import BytesIO
|
||||
|
@ -1,15 +1,15 @@
|
||||
import pytest_asyncio
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from materia_server.models import (
|
||||
from materia.models import (
|
||||
User,
|
||||
Repository,
|
||||
Directory,
|
||||
RepositoryError,
|
||||
File,
|
||||
)
|
||||
from materia_server.core import Config, SessionContext
|
||||
from materia_server import security
|
||||
from materia.core import Config, SessionContext
|
||||
from materia import security
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.orm.session import make_transient
|
||||
from sqlalchemy import inspect
|
@ -11,6 +11,5 @@ node_modules/
|
||||
*.mjs
|
||||
*.log
|
||||
|
||||
#openapi.json
|
||||
/target
|
||||
openapi.json
|
||||
src/client
|