admin ui
This commit is contained in:
parent
8f883f1922
commit
a2e75c3771
144
README.md
144
README.md
|
|
@ -1,147 +1,23 @@
|
||||||
# flarum-msteams-webhook
|
# 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:
|
## Build des Admin-Frontends
|
||||||
|
|
||||||
- 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
|
|
||||||
|
|
||||||
```bash
|
```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
|
```bash
|
||||||
php flarum cache:clear
|
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 <userId>`) 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
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ use SbpJm\FlarumMSTeamsWebhook\Listener\MirrorAlertsToTeams;
|
||||||
return [
|
return [
|
||||||
(new Extend\Locales(__DIR__ . '/locale')),
|
(new Extend\Locales(__DIR__ . '/locale')),
|
||||||
|
|
||||||
|
(new Extend\Frontend('admin'))
|
||||||
|
->js(__DIR__ . '/js/dist/admin.js'),
|
||||||
|
|
||||||
(new Extend\Notification())
|
(new Extend\Notification())
|
||||||
->beforeSending(MirrorAlertsToTeams::class),
|
->beforeSending(MirrorAlertsToTeams::class),
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
import './src/admin';
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
const config = require('flarum-webpack-config');
|
||||||
|
|
||||||
|
module.exports = config();
|
||||||
Loading…
Reference in New Issue