mdb-engine 0.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mdb_engine/README.md +144 -0
- mdb_engine/__init__.py +37 -0
- mdb_engine/auth/README.md +631 -0
- mdb_engine/auth/__init__.py +128 -0
- mdb_engine/auth/casbin_factory.py +199 -0
- mdb_engine/auth/casbin_models.py +46 -0
- mdb_engine/auth/config_defaults.py +71 -0
- mdb_engine/auth/config_helpers.py +213 -0
- mdb_engine/auth/cookie_utils.py +158 -0
- mdb_engine/auth/decorators.py +350 -0
- mdb_engine/auth/dependencies.py +747 -0
- mdb_engine/auth/helpers.py +64 -0
- mdb_engine/auth/integration.py +578 -0
- mdb_engine/auth/jwt.py +225 -0
- mdb_engine/auth/middleware.py +241 -0
- mdb_engine/auth/oso_factory.py +323 -0
- mdb_engine/auth/provider.py +570 -0
- mdb_engine/auth/restrictions.py +271 -0
- mdb_engine/auth/session_manager.py +477 -0
- mdb_engine/auth/token_lifecycle.py +213 -0
- mdb_engine/auth/token_store.py +289 -0
- mdb_engine/auth/users.py +1516 -0
- mdb_engine/auth/utils.py +614 -0
- mdb_engine/cli/__init__.py +13 -0
- mdb_engine/cli/commands/__init__.py +7 -0
- mdb_engine/cli/commands/generate.py +105 -0
- mdb_engine/cli/commands/migrate.py +83 -0
- mdb_engine/cli/commands/show.py +70 -0
- mdb_engine/cli/commands/validate.py +63 -0
- mdb_engine/cli/main.py +41 -0
- mdb_engine/cli/utils.py +92 -0
- mdb_engine/config.py +217 -0
- mdb_engine/constants.py +160 -0
- mdb_engine/core/README.md +542 -0
- mdb_engine/core/__init__.py +42 -0
- mdb_engine/core/app_registration.py +392 -0
- mdb_engine/core/connection.py +243 -0
- mdb_engine/core/engine.py +749 -0
- mdb_engine/core/index_management.py +162 -0
- mdb_engine/core/manifest.py +2793 -0
- mdb_engine/core/seeding.py +179 -0
- mdb_engine/core/service_initialization.py +355 -0
- mdb_engine/core/types.py +413 -0
- mdb_engine/database/README.md +522 -0
- mdb_engine/database/__init__.py +31 -0
- mdb_engine/database/abstraction.py +635 -0
- mdb_engine/database/connection.py +387 -0
- mdb_engine/database/scoped_wrapper.py +1721 -0
- mdb_engine/embeddings/README.md +184 -0
- mdb_engine/embeddings/__init__.py +62 -0
- mdb_engine/embeddings/dependencies.py +193 -0
- mdb_engine/embeddings/service.py +759 -0
- mdb_engine/exceptions.py +167 -0
- mdb_engine/indexes/README.md +651 -0
- mdb_engine/indexes/__init__.py +21 -0
- mdb_engine/indexes/helpers.py +145 -0
- mdb_engine/indexes/manager.py +895 -0
- mdb_engine/memory/README.md +451 -0
- mdb_engine/memory/__init__.py +30 -0
- mdb_engine/memory/service.py +1285 -0
- mdb_engine/observability/README.md +515 -0
- mdb_engine/observability/__init__.py +42 -0
- mdb_engine/observability/health.py +296 -0
- mdb_engine/observability/logging.py +161 -0
- mdb_engine/observability/metrics.py +297 -0
- mdb_engine/routing/README.md +462 -0
- mdb_engine/routing/__init__.py +73 -0
- mdb_engine/routing/websockets.py +813 -0
- mdb_engine/utils/__init__.py +7 -0
- mdb_engine-0.1.6.dist-info/METADATA +213 -0
- mdb_engine-0.1.6.dist-info/RECORD +75 -0
- mdb_engine-0.1.6.dist-info/WHEEL +5 -0
- mdb_engine-0.1.6.dist-info/entry_points.txt +2 -0
- mdb_engine-0.1.6.dist-info/licenses/LICENSE +661 -0
- mdb_engine-0.1.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Generate command for CLI.
|
|
3
|
+
|
|
4
|
+
Generates a template manifest.json file.
|
|
5
|
+
|
|
6
|
+
This module is part of MDB_ENGINE - MongoDB Engine.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
|
|
15
|
+
from ...core.manifest import CURRENT_SCHEMA_VERSION
|
|
16
|
+
from ..utils import save_manifest_file
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@click.command()
|
|
20
|
+
@click.option(
|
|
21
|
+
"--slug",
|
|
22
|
+
"-s",
|
|
23
|
+
prompt="App slug",
|
|
24
|
+
help="App slug (lowercase alphanumeric, underscores, hyphens)",
|
|
25
|
+
)
|
|
26
|
+
@click.option(
|
|
27
|
+
"--name",
|
|
28
|
+
"-n",
|
|
29
|
+
prompt="App name",
|
|
30
|
+
help="Human-readable app name",
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
"--description",
|
|
34
|
+
"-d",
|
|
35
|
+
default="",
|
|
36
|
+
help="App description",
|
|
37
|
+
)
|
|
38
|
+
@click.option(
|
|
39
|
+
"--output",
|
|
40
|
+
"-o",
|
|
41
|
+
default="manifest.json",
|
|
42
|
+
type=click.Path(path_type=Path),
|
|
43
|
+
help="Output file path (default: manifest.json)",
|
|
44
|
+
)
|
|
45
|
+
@click.option(
|
|
46
|
+
"--minimal",
|
|
47
|
+
"-m",
|
|
48
|
+
is_flag=True,
|
|
49
|
+
help="Generate minimal template (basic fields only)",
|
|
50
|
+
)
|
|
51
|
+
def generate(
|
|
52
|
+
slug: str,
|
|
53
|
+
name: str,
|
|
54
|
+
description: str,
|
|
55
|
+
output: Path,
|
|
56
|
+
minimal: bool,
|
|
57
|
+
) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Generate a template manifest.json file.
|
|
60
|
+
|
|
61
|
+
Examples:
|
|
62
|
+
mdb generate --slug my-app --name "My App"
|
|
63
|
+
mdb generate --slug my-app --name "My App" --output custom.json
|
|
64
|
+
mdb generate --slug my-app --name "My App" --minimal
|
|
65
|
+
"""
|
|
66
|
+
try:
|
|
67
|
+
# Validate slug format
|
|
68
|
+
if not slug or not all(c.isalnum() or c in ("_", "-") for c in slug):
|
|
69
|
+
raise click.ClickException(
|
|
70
|
+
"Invalid slug format. Use lowercase alphanumeric, underscores, or hyphens."
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Generate template manifest
|
|
74
|
+
manifest: Dict[str, Any] = {
|
|
75
|
+
"schema_version": CURRENT_SCHEMA_VERSION,
|
|
76
|
+
"slug": slug,
|
|
77
|
+
"name": name,
|
|
78
|
+
"status": "draft",
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if description:
|
|
82
|
+
manifest["description"] = description
|
|
83
|
+
|
|
84
|
+
if not minimal:
|
|
85
|
+
# Add common sections
|
|
86
|
+
manifest["auth"] = {
|
|
87
|
+
"policy": {
|
|
88
|
+
"provider": "casbin",
|
|
89
|
+
"required": False,
|
|
90
|
+
"allow_anonymous": True,
|
|
91
|
+
"authorization": {
|
|
92
|
+
"model": "rbac",
|
|
93
|
+
"link_users_roles": True,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
manifest["managed_indexes"] = {}
|
|
98
|
+
manifest["websockets"] = {}
|
|
99
|
+
|
|
100
|
+
# Save manifest
|
|
101
|
+
save_manifest_file(output, manifest)
|
|
102
|
+
click.echo(click.style(f"✅ Generated manifest template: {output}", fg="green"))
|
|
103
|
+
sys.exit(0)
|
|
104
|
+
except click.ClickException:
|
|
105
|
+
raise
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Migrate command for CLI.
|
|
3
|
+
|
|
4
|
+
Migrates a manifest to a target schema version.
|
|
5
|
+
|
|
6
|
+
This module is part of MDB_ENGINE - MongoDB Engine.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
|
|
14
|
+
from ...core.manifest import CURRENT_SCHEMA_VERSION, migrate_manifest
|
|
15
|
+
from ..utils import load_manifest_file, save_manifest_file
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.command()
|
|
19
|
+
@click.argument("manifest_file", type=click.Path(exists=True, path_type=Path))
|
|
20
|
+
@click.option(
|
|
21
|
+
"--target-version",
|
|
22
|
+
"-t",
|
|
23
|
+
default=CURRENT_SCHEMA_VERSION,
|
|
24
|
+
help=f"Target schema version (default: {CURRENT_SCHEMA_VERSION})",
|
|
25
|
+
)
|
|
26
|
+
@click.option(
|
|
27
|
+
"--output",
|
|
28
|
+
"-o",
|
|
29
|
+
type=click.Path(path_type=Path),
|
|
30
|
+
help="Output file path (default: stdout)",
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
"--in-place",
|
|
34
|
+
"-i",
|
|
35
|
+
is_flag=True,
|
|
36
|
+
help="Update manifest file in place",
|
|
37
|
+
)
|
|
38
|
+
def migrate(
|
|
39
|
+
manifest_file: Path,
|
|
40
|
+
target_version: str,
|
|
41
|
+
output: Path | None,
|
|
42
|
+
in_place: bool,
|
|
43
|
+
) -> None:
|
|
44
|
+
"""
|
|
45
|
+
Migrate a manifest.json file to a target schema version.
|
|
46
|
+
|
|
47
|
+
MANIFEST_FILE: Path to manifest.json file to migrate
|
|
48
|
+
|
|
49
|
+
Examples:
|
|
50
|
+
mdb migrate manifest.json
|
|
51
|
+
mdb migrate manifest.json --target-version 2.0 --output manifest.v2.json
|
|
52
|
+
mdb migrate manifest.json --in-place
|
|
53
|
+
"""
|
|
54
|
+
try:
|
|
55
|
+
# Load manifest
|
|
56
|
+
manifest = load_manifest_file(manifest_file)
|
|
57
|
+
|
|
58
|
+
# Migrate
|
|
59
|
+
migrated_manifest = migrate_manifest(manifest, target_version=target_version)
|
|
60
|
+
|
|
61
|
+
# Determine output
|
|
62
|
+
if in_place:
|
|
63
|
+
output_path = manifest_file
|
|
64
|
+
elif output:
|
|
65
|
+
output_path = output
|
|
66
|
+
else:
|
|
67
|
+
# Output to stdout
|
|
68
|
+
import json
|
|
69
|
+
|
|
70
|
+
click.echo(json.dumps(migrated_manifest, indent=2, ensure_ascii=False))
|
|
71
|
+
sys.exit(0)
|
|
72
|
+
|
|
73
|
+
# Save to file
|
|
74
|
+
save_manifest_file(output_path, migrated_manifest)
|
|
75
|
+
click.echo(
|
|
76
|
+
click.style(
|
|
77
|
+
f"✅ Migrated manifest to version {target_version}: {output_path}",
|
|
78
|
+
fg="green",
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
sys.exit(0)
|
|
82
|
+
except click.ClickException:
|
|
83
|
+
raise
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Show command for CLI.
|
|
3
|
+
|
|
4
|
+
Displays manifest information.
|
|
5
|
+
|
|
6
|
+
This module is part of MDB_ENGINE - MongoDB Engine.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
|
|
14
|
+
from ...core.manifest import ManifestValidator
|
|
15
|
+
from ..utils import format_manifest_output, load_manifest_file
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.command()
|
|
19
|
+
@click.argument("manifest_file", type=click.Path(exists=True, path_type=Path))
|
|
20
|
+
@click.option(
|
|
21
|
+
"--format",
|
|
22
|
+
"-f",
|
|
23
|
+
type=click.Choice(["json", "yaml", "pretty"], case_sensitive=False),
|
|
24
|
+
default="json",
|
|
25
|
+
help="Output format (default: json)",
|
|
26
|
+
)
|
|
27
|
+
@click.option(
|
|
28
|
+
"--validate",
|
|
29
|
+
"-v",
|
|
30
|
+
is_flag=True,
|
|
31
|
+
help="Validate manifest before showing",
|
|
32
|
+
)
|
|
33
|
+
def show(manifest_file: Path, format: str, validate: bool) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Display manifest information.
|
|
36
|
+
|
|
37
|
+
MANIFEST_FILE: Path to manifest.json file to display
|
|
38
|
+
|
|
39
|
+
Examples:
|
|
40
|
+
mdb show manifest.json
|
|
41
|
+
mdb show manifest.json --format pretty
|
|
42
|
+
mdb show manifest.json --format yaml --validate
|
|
43
|
+
"""
|
|
44
|
+
try:
|
|
45
|
+
# Load manifest
|
|
46
|
+
manifest = load_manifest_file(manifest_file)
|
|
47
|
+
|
|
48
|
+
# Validate if requested
|
|
49
|
+
if validate:
|
|
50
|
+
validator = ManifestValidator()
|
|
51
|
+
is_valid, error_message, error_paths = validator.validate(manifest)
|
|
52
|
+
if not is_valid:
|
|
53
|
+
click.echo(
|
|
54
|
+
click.style(
|
|
55
|
+
f"⚠️ Warning: Manifest is invalid: {error_message}",
|
|
56
|
+
fg="yellow",
|
|
57
|
+
),
|
|
58
|
+
err=True,
|
|
59
|
+
)
|
|
60
|
+
if error_paths:
|
|
61
|
+
click.echo("Error paths:", err=True)
|
|
62
|
+
for path in error_paths:
|
|
63
|
+
click.echo(f" - {path}", err=True)
|
|
64
|
+
|
|
65
|
+
# Format and display
|
|
66
|
+
output = format_manifest_output(manifest, format.lower())
|
|
67
|
+
click.echo(output)
|
|
68
|
+
sys.exit(0)
|
|
69
|
+
except click.ClickException:
|
|
70
|
+
raise
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Validate command for CLI.
|
|
3
|
+
|
|
4
|
+
Validates a manifest against the schema.
|
|
5
|
+
|
|
6
|
+
This module is part of MDB_ENGINE - MongoDB Engine.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
|
|
14
|
+
from ...core.manifest import ManifestValidator
|
|
15
|
+
from ..utils import load_manifest_file
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.command()
|
|
19
|
+
@click.argument("manifest_file", type=click.Path(exists=True, path_type=Path))
|
|
20
|
+
@click.option(
|
|
21
|
+
"--verbose",
|
|
22
|
+
"-v",
|
|
23
|
+
is_flag=True,
|
|
24
|
+
help="Show detailed validation errors",
|
|
25
|
+
)
|
|
26
|
+
def validate(manifest_file: Path, verbose: bool) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Validate a manifest.json file against the schema.
|
|
29
|
+
|
|
30
|
+
MANIFEST_FILE: Path to manifest.json file to validate
|
|
31
|
+
|
|
32
|
+
Examples:
|
|
33
|
+
mdb validate manifest.json
|
|
34
|
+
mdb validate path/to/manifest.json --verbose
|
|
35
|
+
"""
|
|
36
|
+
try:
|
|
37
|
+
# Load manifest
|
|
38
|
+
manifest = load_manifest_file(manifest_file)
|
|
39
|
+
|
|
40
|
+
# Validate
|
|
41
|
+
validator = ManifestValidator()
|
|
42
|
+
is_valid, error_message, error_paths = validator.validate(manifest)
|
|
43
|
+
|
|
44
|
+
if is_valid:
|
|
45
|
+
click.echo(
|
|
46
|
+
click.style(f"✅ Manifest '{manifest_file}' is valid!", fg="green")
|
|
47
|
+
)
|
|
48
|
+
sys.exit(0)
|
|
49
|
+
else:
|
|
50
|
+
click.echo(
|
|
51
|
+
click.style(f"❌ Manifest '{manifest_file}' is invalid!", fg="red")
|
|
52
|
+
)
|
|
53
|
+
if error_message:
|
|
54
|
+
click.echo(click.style(f"Error: {error_message}", fg="red"))
|
|
55
|
+
if error_paths and verbose:
|
|
56
|
+
click.echo("\nError paths:")
|
|
57
|
+
for path in error_paths:
|
|
58
|
+
click.echo(f" - {path}")
|
|
59
|
+
sys.exit(1)
|
|
60
|
+
except click.ClickException:
|
|
61
|
+
raise
|
|
62
|
+
except (FileNotFoundError, ValueError, KeyError) as e:
|
|
63
|
+
raise click.ClickException(str(e))
|
mdb_engine/cli/main.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Main CLI entry point for MDB_ENGINE.
|
|
3
|
+
|
|
4
|
+
This module provides the command-line interface for manifest management.
|
|
5
|
+
|
|
6
|
+
This module is part of MDB_ENGINE - MongoDB Engine.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
|
|
11
|
+
from .commands.generate import generate
|
|
12
|
+
from .commands.migrate import migrate
|
|
13
|
+
from .commands.show import show
|
|
14
|
+
from .commands.validate import validate
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.group()
|
|
18
|
+
@click.version_option(version="0.1.6", prog_name="mdb")
|
|
19
|
+
def cli() -> None:
|
|
20
|
+
"""
|
|
21
|
+
MDB_ENGINE CLI - Manifest management tool.
|
|
22
|
+
|
|
23
|
+
Manage your MDB_ENGINE manifests with validation, migration, and generation.
|
|
24
|
+
"""
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Register commands
|
|
29
|
+
cli.add_command(validate)
|
|
30
|
+
cli.add_command(migrate)
|
|
31
|
+
cli.add_command(generate)
|
|
32
|
+
cli.add_command(show)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def main() -> None:
|
|
36
|
+
"""Entry point for the CLI."""
|
|
37
|
+
cli()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
main()
|
mdb_engine/cli/utils.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions for CLI commands.
|
|
3
|
+
|
|
4
|
+
This module provides shared utilities for CLI operations.
|
|
5
|
+
|
|
6
|
+
This module is part of MDB_ENGINE - MongoDB Engine.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def load_manifest_file(file_path: Path) -> Dict[str, Any]:
|
|
17
|
+
"""
|
|
18
|
+
Load a manifest JSON file.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
file_path: Path to manifest.json file
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Manifest dictionary
|
|
25
|
+
|
|
26
|
+
Raises:
|
|
27
|
+
click.ClickException: If file doesn't exist or is invalid JSON
|
|
28
|
+
"""
|
|
29
|
+
if not file_path.exists():
|
|
30
|
+
raise click.ClickException(f"Manifest file not found: {file_path}")
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
34
|
+
return json.load(f)
|
|
35
|
+
except json.JSONDecodeError as e:
|
|
36
|
+
raise click.ClickException(f"Invalid JSON in manifest file: {e}")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def save_manifest_file(file_path: Path, manifest: Dict[str, Any]) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Save a manifest dictionary to a JSON file.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
file_path: Path to save manifest.json file
|
|
45
|
+
manifest: Manifest dictionary
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
click.ClickException: If file cannot be written
|
|
49
|
+
"""
|
|
50
|
+
try:
|
|
51
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
52
|
+
json.dump(manifest, f, indent=2, ensure_ascii=False)
|
|
53
|
+
except OSError as e:
|
|
54
|
+
raise click.ClickException(f"Failed to write manifest file: {e}")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def format_manifest_output(manifest: Dict[str, Any], format_type: str) -> str:
|
|
58
|
+
"""
|
|
59
|
+
Format manifest for output.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
manifest: Manifest dictionary
|
|
63
|
+
format_type: Output format ('json', 'yaml', 'pretty')
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Formatted string representation
|
|
67
|
+
"""
|
|
68
|
+
if format_type == "json":
|
|
69
|
+
return json.dumps(manifest, indent=2, ensure_ascii=False)
|
|
70
|
+
elif format_type == "yaml":
|
|
71
|
+
try:
|
|
72
|
+
import yaml
|
|
73
|
+
|
|
74
|
+
return yaml.dump(manifest, default_flow_style=False, sort_keys=False)
|
|
75
|
+
except ImportError:
|
|
76
|
+
click.echo(
|
|
77
|
+
"Warning: PyYAML not installed. Falling back to JSON format.",
|
|
78
|
+
err=True,
|
|
79
|
+
)
|
|
80
|
+
return json.dumps(manifest, indent=2, ensure_ascii=False)
|
|
81
|
+
elif format_type == "pretty":
|
|
82
|
+
# Pretty print with key information
|
|
83
|
+
lines = []
|
|
84
|
+
lines.append(f"Schema Version: {manifest.get('schema_version', '2.0')}")
|
|
85
|
+
lines.append(f"Slug: {manifest.get('slug', 'N/A')}")
|
|
86
|
+
lines.append(f"Name: {manifest.get('name', 'N/A')}")
|
|
87
|
+
lines.append(f"Status: {manifest.get('status', 'draft')}")
|
|
88
|
+
if manifest.get("description"):
|
|
89
|
+
lines.append(f"Description: {manifest.get('description')}")
|
|
90
|
+
return "\n".join(lines)
|
|
91
|
+
else:
|
|
92
|
+
return json.dumps(manifest, indent=2, ensure_ascii=False)
|
mdb_engine/config.py
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration management for MDB_ENGINE.
|
|
3
|
+
|
|
4
|
+
This module provides optional configuration management using Pydantic.
|
|
5
|
+
It's designed to be non-breaking - the MongoDBEngine can still be used
|
|
6
|
+
with direct parameters as before.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from pydantic import BaseSettings, Field
|
|
14
|
+
|
|
15
|
+
PYDANTIC_AVAILABLE = True
|
|
16
|
+
except ImportError:
|
|
17
|
+
PYDANTIC_AVAILABLE = False
|
|
18
|
+
|
|
19
|
+
# Create a dummy BaseSettings for when Pydantic is not available
|
|
20
|
+
class BaseSettings:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class EngineConfig:
|
|
25
|
+
"""
|
|
26
|
+
MongoDB Engine configuration.
|
|
27
|
+
|
|
28
|
+
This class provides configuration management with environment variable
|
|
29
|
+
support. It's optional - MongoDBEngine can still be initialized with
|
|
30
|
+
direct parameters for backward compatibility.
|
|
31
|
+
|
|
32
|
+
Example:
|
|
33
|
+
# Using environment variables
|
|
34
|
+
config = EngineConfig()
|
|
35
|
+
engine = MongoDBEngine(
|
|
36
|
+
mongo_uri=config.mongo_uri,
|
|
37
|
+
db_name=config.db_name
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Or using direct parameters (backward compatible)
|
|
41
|
+
engine = MongoDBEngine(
|
|
42
|
+
mongo_uri="mongodb://localhost:27017",
|
|
43
|
+
db_name="my_db"
|
|
44
|
+
)
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
mongo_uri: Optional[str] = None,
|
|
50
|
+
db_name: Optional[str] = None,
|
|
51
|
+
max_pool_size: Optional[int] = None,
|
|
52
|
+
min_pool_size: Optional[int] = None,
|
|
53
|
+
server_selection_timeout_ms: Optional[int] = None,
|
|
54
|
+
authz_cache_ttl: Optional[int] = None,
|
|
55
|
+
):
|
|
56
|
+
"""
|
|
57
|
+
Initialize configuration.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
mongo_uri: MongoDB connection URI (defaults to MONGO_URI env var)
|
|
61
|
+
db_name: Database name (defaults to DB_NAME env var)
|
|
62
|
+
max_pool_size: Maximum connection pool size (defaults to 50 or MONGO_MAX_POOL_SIZE)
|
|
63
|
+
min_pool_size: Minimum connection pool size (defaults to 10 or MONGO_MIN_POOL_SIZE)
|
|
64
|
+
server_selection_timeout_ms: Server selection timeout in ms (defaults to 5000)
|
|
65
|
+
authz_cache_ttl: Authorization cache TTL in seconds (defaults to 300)
|
|
66
|
+
"""
|
|
67
|
+
self.mongo_uri = mongo_uri or os.getenv("MONGO_URI", "")
|
|
68
|
+
self.db_name = db_name or os.getenv("DB_NAME", "")
|
|
69
|
+
self.max_pool_size = max_pool_size or int(
|
|
70
|
+
os.getenv("MONGO_MAX_POOL_SIZE", "50")
|
|
71
|
+
)
|
|
72
|
+
self.min_pool_size = min_pool_size or int(
|
|
73
|
+
os.getenv("MONGO_MIN_POOL_SIZE", "10")
|
|
74
|
+
)
|
|
75
|
+
self.server_selection_timeout_ms = server_selection_timeout_ms or int(
|
|
76
|
+
os.getenv("MONGO_SERVER_SELECTION_TIMEOUT_MS", "5000")
|
|
77
|
+
)
|
|
78
|
+
self.authz_cache_ttl = authz_cache_ttl or int(
|
|
79
|
+
os.getenv("AUTHZ_CACHE_TTL", "300")
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def validate(self) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Validate configuration values.
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
ValueError: If required configuration is missing or invalid
|
|
88
|
+
"""
|
|
89
|
+
if not self.mongo_uri:
|
|
90
|
+
raise ValueError(
|
|
91
|
+
"mongo_uri is required (set MONGO_URI environment variable or pass directly)"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if not self.db_name:
|
|
95
|
+
raise ValueError(
|
|
96
|
+
"db_name is required (set DB_NAME environment variable or pass directly)"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
if self.max_pool_size < 1:
|
|
100
|
+
raise ValueError(f"max_pool_size must be >= 1, got {self.max_pool_size}")
|
|
101
|
+
|
|
102
|
+
if self.min_pool_size < 1:
|
|
103
|
+
raise ValueError(f"min_pool_size must be >= 1, got {self.min_pool_size}")
|
|
104
|
+
|
|
105
|
+
if self.min_pool_size > self.max_pool_size:
|
|
106
|
+
raise ValueError(
|
|
107
|
+
f"min_pool_size ({self.min_pool_size}) cannot be greater than "
|
|
108
|
+
f"max_pool_size ({self.max_pool_size})"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if self.server_selection_timeout_ms < 1000:
|
|
112
|
+
raise ValueError(
|
|
113
|
+
f"server_selection_timeout_ms must be >= 1000, got "
|
|
114
|
+
f"{self.server_selection_timeout_ms}"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
if self.authz_cache_ttl < 0:
|
|
118
|
+
raise ValueError(
|
|
119
|
+
f"authz_cache_ttl must be >= 0, got {self.authz_cache_ttl}"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# Pydantic-based configuration (optional, only if Pydantic is available)
|
|
124
|
+
if PYDANTIC_AVAILABLE:
|
|
125
|
+
|
|
126
|
+
class EngineConfigPydantic(BaseSettings):
|
|
127
|
+
"""
|
|
128
|
+
Pydantic-based configuration with automatic validation.
|
|
129
|
+
|
|
130
|
+
This is an optional alternative to EngineConfig that provides
|
|
131
|
+
automatic validation and type checking via Pydantic.
|
|
132
|
+
|
|
133
|
+
Usage:
|
|
134
|
+
config = EngineConfigPydantic()
|
|
135
|
+
engine = MongoDBEngine(
|
|
136
|
+
mongo_uri=config.mongo_uri,
|
|
137
|
+
db_name=config.db_name
|
|
138
|
+
)
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
mongo_uri: str = Field(
|
|
142
|
+
..., env="MONGO_URI", description="MongoDB connection URI"
|
|
143
|
+
)
|
|
144
|
+
db_name: str = Field(..., env="DB_NAME", description="Database name")
|
|
145
|
+
max_pool_size: int = Field(
|
|
146
|
+
50,
|
|
147
|
+
env="MONGO_MAX_POOL_SIZE",
|
|
148
|
+
ge=1,
|
|
149
|
+
description="Maximum connection pool size",
|
|
150
|
+
)
|
|
151
|
+
min_pool_size: int = Field(
|
|
152
|
+
10,
|
|
153
|
+
env="MONGO_MIN_POOL_SIZE",
|
|
154
|
+
ge=1,
|
|
155
|
+
description="Minimum connection pool size",
|
|
156
|
+
)
|
|
157
|
+
server_selection_timeout_ms: int = Field(
|
|
158
|
+
5000,
|
|
159
|
+
env="MONGO_SERVER_SELECTION_TIMEOUT_MS",
|
|
160
|
+
ge=1000,
|
|
161
|
+
description="Server selection timeout in milliseconds",
|
|
162
|
+
)
|
|
163
|
+
authz_cache_ttl: int = Field(
|
|
164
|
+
300,
|
|
165
|
+
env="AUTHZ_CACHE_TTL",
|
|
166
|
+
ge=0,
|
|
167
|
+
description="Authorization cache TTL in seconds",
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
class Config:
|
|
171
|
+
env_file = ".env"
|
|
172
|
+
case_sensitive = False
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ============================================================================
|
|
176
|
+
# DEMO MODE CONSTANTS
|
|
177
|
+
# ============================================================================
|
|
178
|
+
|
|
179
|
+
DEMO_ENABLED: bool = os.getenv("DEMO_ENABLED", "false").lower() == "true"
|
|
180
|
+
"""Whether demo mode is enabled."""
|
|
181
|
+
|
|
182
|
+
DEMO_EMAIL_DEFAULT: str = os.getenv("DEMO_EMAIL_DEFAULT", "demo@example.com")
|
|
183
|
+
"""Default email for demo user."""
|
|
184
|
+
|
|
185
|
+
DEMO_PASSWORD_DEFAULT: str = os.getenv("DEMO_PASSWORD_DEFAULT", "demo123")
|
|
186
|
+
"""Default password for demo user."""
|
|
187
|
+
|
|
188
|
+
# MongoDB connection defaults (for backward compatibility)
|
|
189
|
+
MONGO_URI: str = os.getenv("MONGO_URI", "")
|
|
190
|
+
"""MongoDB connection URI (from environment variable)."""
|
|
191
|
+
|
|
192
|
+
DB_NAME: str = os.getenv("DB_NAME", "")
|
|
193
|
+
"""Database name (from environment variable)."""
|
|
194
|
+
|
|
195
|
+
# ============================================================================
|
|
196
|
+
# TOKEN MANAGEMENT CONFIGURATION
|
|
197
|
+
# ============================================================================
|
|
198
|
+
|
|
199
|
+
# Token lifetimes (can be overridden via environment variables)
|
|
200
|
+
ACCESS_TOKEN_TTL: int = int(os.getenv("ACCESS_TOKEN_TTL", "900")) # 15 minutes
|
|
201
|
+
"""Access token TTL in seconds (default: 900 / 15 minutes)."""
|
|
202
|
+
|
|
203
|
+
REFRESH_TOKEN_TTL: int = int(os.getenv("REFRESH_TOKEN_TTL", "604800")) # 7 days
|
|
204
|
+
"""Refresh token TTL in seconds (default: 604800 / 7 days)."""
|
|
205
|
+
|
|
206
|
+
TOKEN_ROTATION_ENABLED: bool = (
|
|
207
|
+
os.getenv("TOKEN_ROTATION_ENABLED", "true").lower() == "true"
|
|
208
|
+
)
|
|
209
|
+
"""Whether to rotate refresh tokens on each use (default: true)."""
|
|
210
|
+
|
|
211
|
+
MAX_SESSIONS_PER_USER: int = int(os.getenv("MAX_SESSIONS_PER_USER", "10"))
|
|
212
|
+
"""Maximum number of concurrent sessions per user (default: 10)."""
|
|
213
|
+
|
|
214
|
+
SESSION_INACTIVITY_TIMEOUT: int = int(
|
|
215
|
+
os.getenv("SESSION_INACTIVITY_TIMEOUT", "1800")
|
|
216
|
+
) # 30 minutes
|
|
217
|
+
"""Session inactivity timeout in seconds (default: 1800 / 30 minutes)."""
|