From a2e75c377170abc69bb85015109d88a13f651c01 Mon Sep 17 00:00:00 2001 From: mueh Date: Wed, 15 Apr 2026 14:00:14 +0200 Subject: [PATCH] admin ui --- README.md | 144 +++--------------------------------------- extend.php | 3 + js/admin.js | 1 + js/package.json | 15 +++++ js/src/admin/index.js | 121 +++++++++++++++++++++++++++++++++++ js/webpack.config.js | 3 + 6 files changed, 153 insertions(+), 134 deletions(-) create mode 100644 js/admin.js create mode 100644 js/package.json create mode 100644 js/src/admin/index.js create mode 100644 js/webpack.config.js diff --git a/README.md b/README.md index 01b92aa..05a9380 100644 --- a/README.md +++ b/README.md @@ -1,147 +1,23 @@ # flarum-msteams-webhook -Spiegelt Flarum-**Web-Benachrichtigungen** (die Glocke im Forum) in den **Microsoft Teams Activity Feed**. +Diese Version enthält ein **sehr rudimentäres Admin-UI** für Flarum 1.x. -## Zielbild +## Enthalten -Diese erste Version registriert **keinen eigenen Teams-Kanal in der Flarum-UI**. Stattdessen spiegelt die Erweiterung exakt die Benachrichtigungen, die ein Benutzer bereits im **Web/Alert-Kanal** aktiviert hat, nach Teams. +- PHP-Backend für das Spiegeln von Web/Alert-Benachrichtigungen nach Microsoft Teams +- rudimentäre Settings im Flarum-Adminbereich +- JavaScript-Build-Setup für das Admin-Frontend -Das ist für Flarum 1.8.x die pragmatischste v1, weil dadurch: - -- die bestehende Flarum-Benachrichtigungslogik unverändert bleibt, -- keine Anpassung der Notification-Grid-UI notwendig ist, -- und Teams nur die Benachrichtigungen erhält, die im Forum ohnehin als Web-Alert ankommen würden. - -## Kompatibilität - -- Flarum: **^1.8** -- PHP: **^8.1** -- Getestetes Zielsystem laut Projekt-Hinweis: **Flarum 1.8.15**, **PHP 8.3.6** - -## Was die Extension macht - -1. Hängt sich per `Extend\Notification()->beforeSending(...)` in den Flarum-Notification-Flow ein. -2. Prüft für jeden Empfänger, ob die betreffende Notification im **Web-Kanal (`alert`)** aktiviert ist. -3. Löst dafür einen **Queue-Job** aus. -4. Der Queue-Job holt per **Client Credentials Flow** ein Graph-Token. -5. Anschließend wird per Microsoft Graph eine **Teams Activity Feed Notification** an den Benutzer gesendet. - -## Voraussetzungen in Microsoft 365 / Entra / Teams - -### 1) Entra App Registration - -Benötigte Konfiguration: - -- `tenant_id` -- `client_id` -- `client_secret` - -Benötigte Microsoft Graph **Application Permission**: - -- bevorzugt: `TeamsActivity.Send.User` -- alternativ: `TeamsActivity.Send` - -### 2) Teams App - -Die Ziel-Benutzer müssen die Teams-App installiert haben, für die Benachrichtigungen verschickt werden. - -Empfehlung für v1: - -- Activity Type: `systemDefault` -- Teams App ID in der Extension-Konfiguration hinterlegen - -### 3) Benutzer-Mapping - -Diese v1 unterstützt folgende Auflösungsstrategien: - -- `email` → `POST /users/{email}/teamwork/sendActivityNotification` -- `upn` → UPN aus User-Preference oder Fallback auf E-Mail -- `preference` → frei konfigurierbarer User-Preference-Key - -Wenn euer Entra-/SSO-Login bereits mit identischer E-Mail / UPN arbeitet, reicht meist `email` oder `upn`. - -## Installation - -### Composer +## Build des Admin-Frontends ```bash -composer require sbp-jm/flarum-msteams-webhook:dev-main +cd js +npm install +npm run build ``` -### Flarum Cache leeren +Danach im Flarum-Root: ```bash php flarum cache:clear ``` - -## Konfiguration - -Da diese v1 noch kein Admin-UI mitliefert, werden die Settings direkt in der Flarum-`settings`-Tabelle gepflegt. - -### Pflicht-Settings - -```sql -REPLACE INTO settings (`key`, `value`) VALUES -('sbp-jm-msteams-webhook.enabled', '1'), -('sbp-jm-msteams-webhook.tenant_id', 'DEIN-TENANT-ID'), -('sbp-jm-msteams-webhook.client_id', 'DEINE-CLIENT-ID'), -('sbp-jm-msteams-webhook.client_secret', 'DEIN-CLIENT-SECRET'), -('sbp-jm-msteams-webhook.forum_base_url', 'https://forum.example.tld'), -('sbp-jm-msteams-webhook.user_lookup_strategy', 'email'), -('sbp-jm-msteams-webhook.activity_type', 'systemDefault'), -('sbp-jm-msteams-webhook.timeout_seconds', '15'); -``` - -### Optionale Settings - -```sql -REPLACE INTO settings (`key`, `value`) VALUES -('sbp-jm-msteams-webhook.teams_app_id', 'DEINE-TEAMS-APP-ID'), -('sbp-jm-msteams-webhook.icon_id', ''), -('sbp-jm-msteams-webhook.upn_preference_key', 'sbp-jm-msteams-webhook.upn'), -('sbp-jm-msteams-webhook.user_preference_key', 'sbp-jm-msteams-webhook.target'); -``` - -## Queue / Scheduler - -Die Extension ist für asynchrone Zustellung ausgelegt. - -Empfohlen: - -```bash -php flarum queue:work -``` - -Wenn ihr bereits den **database** Queue Driver und einen aktiven Scheduler verwendet, passt diese Erweiterung sehr gut in euer bestehendes Setup. - -## Bekannte Einschränkungen der v1 - -- Noch **kein Admin-UI** zum Setzen der Settings -- Noch **kein User-UI** für persönliches Teams-Ziel / Opt-out -- Noch **keine Teams-Spalte** im Flarum-Notification-Grid -- Activity Feed setzt voraus, dass die passende Teams-App im Zielkontext installiert ist - -## Nächste sinnvolle Schritte - -1. Admin-UI für Settings ergänzen -2. User-UI für Ziel-UPN / Opt-out ergänzen -3. Optional eine echte `Teams`-Spalte im Notification Grid ergänzen -4. Test-Command (`php flarum teams:test-user `) hinzufügen -5. Persistentes Delivery-Log ergänzen - -## Projektstruktur - -```text -extend.php -src/ - Listener/ - MirrorAlertsToTeams.php - Job/ - SendTeamsActivityNotificationJob.php - Service/ - GraphTokenProvider.php - TeamsActivityNotifier.php - Support/ - NotificationPayloadFactory.php - TargetResolver.php -``` diff --git a/extend.php b/extend.php index 813d9d5..f2afe63 100644 --- a/extend.php +++ b/extend.php @@ -8,6 +8,9 @@ use SbpJm\FlarumMSTeamsWebhook\Listener\MirrorAlertsToTeams; return [ (new Extend\Locales(__DIR__ . '/locale')), + (new Extend\Frontend('admin')) + ->js(__DIR__ . '/js/dist/admin.js'), + (new Extend\Notification()) ->beforeSending(MirrorAlertsToTeams::class), ]; diff --git a/js/admin.js b/js/admin.js new file mode 100644 index 0000000..623e3f9 --- /dev/null +++ b/js/admin.js @@ -0,0 +1 @@ +import './src/admin'; diff --git a/js/package.json b/js/package.json new file mode 100644 index 0000000..a89fcad --- /dev/null +++ b/js/package.json @@ -0,0 +1,15 @@ +{ + "private": true, + "name": "@sbp-jm/flarum-msteams-webhook", + "devDependencies": { + "flarum-webpack-config": "^2.0.0", + "webpack": "^5.88.2", + "webpack-cli": "^5.1.4", + "prettier": "^3.0.3" + }, + "scripts": { + "dev": "webpack --mode development --watch", + "build": "webpack --mode production", + "format": "prettier --write src" + } +} diff --git a/js/src/admin/index.js b/js/src/admin/index.js new file mode 100644 index 0000000..c2c14bb --- /dev/null +++ b/js/src/admin/index.js @@ -0,0 +1,121 @@ +app.initializers.add('sbp-jm-msteams-webhook', function (app) { + app.extensionData + .for('sbp-jm-msteams-webhook') + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.enabled', + label: 'Teams-Spiegelung aktivieren', + help: 'Spiegelt Flarum-Web/Alert-Benachrichtigungen zusätzlich in den Microsoft Teams Activity Feed.', + type: 'boolean', + }, + 100 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.tenant_id', + label: 'Entra Tenant ID', + type: 'text', + placeholder: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + }, + 90 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.client_id', + label: 'App / Client ID', + type: 'text', + placeholder: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + }, + 80 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.client_secret', + label: 'Client Secret', + type: 'password', + }, + 70 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.forum_base_url', + label: 'Forum Base URL', + help: 'Wird für Deep Links aus Teams zurück in Flarum verwendet.', + type: 'text', + placeholder: 'https://forum.example.tld', + }, + 60 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.user_lookup_strategy', + label: 'Benutzer-Mapping', + help: 'Wie der Zielbenutzer in Microsoft Graph aufgelöst wird.', + type: 'select', + options: { + email: 'E-Mail des Flarum-Benutzers', + upn: 'UPN aus User-Preference (Fallback auf E-Mail)', + preference: 'Freier Preference-Key am Benutzer', + }, + default: 'email', + }, + 50 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.upn_preference_key', + label: 'Preference-Key für UPN', + type: 'text', + placeholder: 'sbp-jm-msteams-webhook.upn', + }, + 40 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.user_preference_key', + label: 'Preference-Key für freies Ziel', + type: 'text', + placeholder: 'sbp-jm-msteams-webhook.target', + }, + 39 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.activity_type', + label: 'Teams Activity Type', + help: 'Für die erste Version am besten systemDefault verwenden.', + type: 'text', + placeholder: 'systemDefault', + }, + 30 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.teams_app_id', + label: 'Teams App ID', + help: 'Optional, aber empfohlen wenn mehrere Apps dieselbe Entra App Registration verwenden.', + type: 'text', + }, + 20 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.icon_id', + label: 'Icon ID', + help: 'Optionales benutzerdefiniertes Activity-Icon laut Teams App Manifest.', + type: 'text', + }, + 15 + ) + .registerSetting( + { + setting: 'sbp-jm-msteams-webhook.timeout_seconds', + label: 'HTTP Timeout (Sekunden)', + type: 'number', + min: 5, + step: 1, + placeholder: '15', + }, + 10 + ); +}); diff --git a/js/webpack.config.js b/js/webpack.config.js new file mode 100644 index 0000000..fcfa77c --- /dev/null +++ b/js/webpack.config.js @@ -0,0 +1,3 @@ +const config = require('flarum-webpack-config'); + +module.exports = config();