Mealie anbinden: Passwort einmal, danach nur noch ein Dauertoken
Unter Einstellungen gibt es jetzt eine Karte "Mealie (Rezepte)": Adresse, Benutzername, Passwort. Vorrania meldet sich damit EINMAL an (POST /api/auth/token), laesst sich von Mealie ueber POST /api/users/api-tokens ein Dauertoken ausstellen und verwirft das Passwort sofort - es steht in keiner Zeile der Datenbank, in keiner Antwort und in keinem Fehlertext. Wer sein Passwort gar nicht erst eintippen will, haekelt "Ich gebe lieber selbst ein Token ein" an. Das Token liegt NICHT in den Einstellungen: GET /settings liefert jedem angemeldeten Nutzer alle Zeilen im Klartext. Eine Ausschlussliste dort waere beim naechsten Geheimnis vergessen, deshalb eine eigene Tabelle ohne jeden Leseweg - setzen, loeschen, und die Auskunft "ist gesetzt". Was keinen Ausgang hat, kann nicht durchrutschen. Ein Test prueft genau das. Der Dienst folgt services/oidc.py, nicht off.py: Bei Open Food Facts ist "kein Treffer" der Normalfall und wird still zu None, hier ist "Mealie antwortet nicht" ein Fehler, den der Nutzer sehen muss. Die Kennungen trennen auch, was verschieden ist - ein falsches Passwort (400) ist etwas anderes als ein weggetretener Server (502). Mealie 1.x legt die Haushalts-Routen unter /api/groups/, 2.x unter /api/households/. Erkannt wird das zur Laufzeit mit einer Anfrage und dann eine Stunde gepuffert; ueber die Versionsnummer waere es unzuverlaessig, die melden Installationen uneinheitlich. Rezeptliste und -abgleich kommen als Naechstes; dies ist der Teil, mit dem sich der Server ueberhaupt erst verbinden laesst. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
37ab1ba47d
commit
7d8a54a3fc
@@ -790,6 +790,31 @@ class Setting(Base):
|
||||
value: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
|
||||
|
||||
class IntegrationSecret(Base):
|
||||
"""Zugangsgeheimnis für einen externen Dienst (heute: das Mealie-Dauertoken).
|
||||
|
||||
Bewusst **nicht** in :class:`Setting`: ``GET /settings`` liefert jedem
|
||||
angemeldeten Nutzer alle Zeilen im Klartext. Eine Ausschlussliste dort wäre
|
||||
beim nächsten Geheimnis vergessen. Diese Tabelle hat deshalb überhaupt
|
||||
keinen Leseweg nach außen — setzen, löschen, und eine Auskunft „ist
|
||||
gesetzt". Was keinen Ausgang hat, kann nicht durchrutschen.
|
||||
|
||||
Anders als bei :class:`ApiToken` muss der Klartext erhalten bleiben: Wir
|
||||
legen ihn einem fremden Dienst vor, ein Hash nützte dort nichts. Er liegt
|
||||
damit unverschlüsselt in der Datenbank — eine Verschlüsselung wäre Theater,
|
||||
solange der Schlüssel daneben läge. Der Schutz ist: kein Leseweg, nur Admin
|
||||
beim Setzen, nie in einer Antwort.
|
||||
"""
|
||||
|
||||
__tablename__ = "integration_secrets"
|
||||
|
||||
service: Mapped[str] = mapped_column(String(32), primary_key=True)
|
||||
secret: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=_now, onupdate=_now
|
||||
)
|
||||
|
||||
|
||||
class Shop(Base):
|
||||
"""Bezugsquelle / Geschäft, aus dem ein Gegenstand stammt ("gekauft bei").
|
||||
|
||||
|
||||
Reference in New Issue
Block a user