-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplugin.py
More file actions
94 lines (74 loc) · 3.19 KB
/
Copy pathplugin.py
File metadata and controls
94 lines (74 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# app/plugins/example/plugin.py
"""Flask-AAS Plugin API v1 adapter for the reference plugin."""
from pathlib import Path
from typing import Any
from sqlalchemy import inspect
from app.core.extensions import db
from app.plugins import ApplicationPlugin, PluginConfiguration, load_plugin_manifest
from app.plugins.navigation import register_plugin_navigation
from . import models as example_models # noqa: F401 - register model metadata
from .cli import cli as example_cli
from .models import ExampleSettings, get_example_settings
from .routes import example_bp
class ExamplePlugin(ApplicationPlugin):
"""Small but complete reference implementation of a Flask-AAS plugin."""
manifest = load_plugin_manifest(Path(__file__).with_name("plugin.toml"))
plugin_id = manifest.plugin_id
name = manifest.name
version = manifest.version
api_version = manifest.api_version
def validate_config(self) -> PluginConfiguration:
"""Require a settings row and plugin-managed secret before normal access."""
endpoint = "example.settings"
if not inspect(db.engine).has_table(ExampleSettings.__tablename__):
return PluginConfiguration(
configured=False,
reason="Example plugin database schema is not installed.",
admin_endpoint=endpoint,
)
settings = get_example_settings()
if settings is None:
return PluginConfiguration(
configured=False,
reason="Example plugin configuration has not been completed.",
admin_endpoint=endpoint,
)
if not settings.heading or not settings.heading.strip():
return PluginConfiguration(
configured=False,
reason="Example public heading must not be empty.",
admin_endpoint=endpoint,
)
if not settings.managed_secret:
return PluginConfiguration(
configured=False,
reason="Example managed secret is missing.",
admin_endpoint=endpoint,
)
return PluginConfiguration(configured=True, admin_endpoint=endpoint)
def clear_secrets(self) -> None:
"""Clear only the secret owned by this plugin on disable."""
if not inspect(db.engine).has_table(ExampleSettings.__tablename__):
return
settings = get_example_settings()
if settings is not None:
settings.managed_secret = None
def get_cli(self):
"""Expose plugin-owned commands through the generic host dispatcher."""
return example_cli
def register(self, app: Any) -> None:
"""Register the plugin's Flask surfaces and ordinary navigation link."""
app.register_blueprint(example_bp)
navigation_label = self.manifest.navigation_label or self.name
register_plugin_navigation(
app,
plugin_id=self.plugin_id,
label=navigation_label,
endpoint="example.index",
)
@app.context_processor
def example_plugin_template_context():
return {
"example_navigation_label": navigation_label,
}
plugin = ExamplePlugin()