with test command

This commit is contained in:
mueh 2026-04-15 14:31:59 +02:00
parent a2e75c3771
commit b81487c6f6
8 changed files with 140 additions and 11 deletions

View File

@ -1,12 +1,9 @@
# flarum-msteams-webhook
Diese Version enthält ein **sehr rudimentäres Admin-UI** für Flarum 1.x.
Diese Version enthält:
## Enthalten
- 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
- rudimentäres Admin-UI für Flarum 1.x
- Test-Command `php flarum teams:test-user <flarumUserId>`
## Build des Admin-Frontends

View File

@ -23,7 +23,7 @@
},
"autoload": {
"psr-4": {
"SbpJm\\FlarumMSTeamsWebhook\\": "src/"
"SbpJm\FlarumMSTeamsWebhook\": "src/"
}
},
"extra": {

View File

@ -3,6 +3,7 @@
declare(strict_types=1);
use Flarum\Extend;
use SbpJm\FlarumMSTeamsWebhook\Console\TestTeamsUserCommand;
use SbpJm\FlarumMSTeamsWebhook\Listener\MirrorAlertsToTeams;
return [
@ -11,6 +12,9 @@ return [
(new Extend\Frontend('admin'))
->js(__DIR__ . '/js/dist/admin.js'),
(new Extend\Console())
->command(TestTeamsUserCommand::class),
(new Extend\Notification())
->beforeSending(MirrorAlertsToTeams::class),
];

View File

@ -1,4 +1,6 @@
app.initializers.add('sbp-jm-msteams-webhook', function (app) {
import app from 'flarum/admin/app';
app.initializers.add('sbp-jm-msteams-webhook', function () {
app.extensionData
.for('sbp-jm-msteams-webhook')
.registerSetting(
@ -53,7 +55,7 @@ app.initializers.add('sbp-jm-msteams-webhook', function (app) {
help: 'Wie der Zielbenutzer in Microsoft Graph aufgelöst wird.',
type: 'select',
options: {
email: 'E-Mail des Flarum-Benutzers',
email: 'E-Mail des Flarum-Benutzers / UPN wenn identisch',
upn: 'UPN aus User-Preference (Fallback auf E-Mail)',
preference: 'Freier Preference-Key am Benutzer',
},
@ -83,7 +85,7 @@ app.initializers.add('sbp-jm-msteams-webhook', function (app) {
{
setting: 'sbp-jm-msteams-webhook.activity_type',
label: 'Teams Activity Type',
help: 'Für die erste Version am besten systemDefault verwenden.',
help: 'Für den Schnelltest am besten systemDefault verwenden.',
type: 'text',
placeholder: 'systemDefault',
},

View File

@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
namespace SbpJm\FlarumMSTeamsWebhook\Console;
use Flarum\Console\AbstractCommand;
use Flarum\User\User;
use SbpJm\FlarumMSTeamsWebhook\Notification\TestActivityBlueprint;
use SbpJm\FlarumMSTeamsWebhook\Service\TeamsActivityNotifier;
use SbpJm\FlarumMSTeamsWebhook\Support\TargetResolver;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
class TestTeamsUserCommand extends AbstractCommand
{
public function __construct(
protected TeamsActivityNotifier $notifier,
protected TargetResolver $targetResolver
) {
parent::__construct();
}
protected function configure(): void
{
$this
->setName('teams:test-user')
->setDescription('Sends a test Microsoft Teams activity feed notification to a Flarum user.')
->addArgument('flarumUserId', InputArgument::REQUIRED, 'The numeric Flarum user ID')
->addOption('target', null, InputOption::VALUE_OPTIONAL, 'Override the resolved Microsoft Graph target (UPN or Entra user ID)')
->addOption('show-target', null, InputOption::VALUE_NONE, 'Only show the resolved Microsoft Graph target, do not send anything');
}
protected function fire(): int
{
$userId = (int) $this->input->getArgument('flarumUserId');
$user = User::query()->find($userId);
if (!$user instanceof User) {
$this->error('Flarum user not found: ' . $userId);
return 1;
}
$resolvedTarget = $this->targetResolver->resolve($user);
$overrideTarget = $this->input->getOption('target');
$target = is_string($overrideTarget) && trim($overrideTarget) !== '' ? trim($overrideTarget) : $resolvedTarget;
$this->info('Flarum user: #' . $user->id . ' (' . ($user->username ?? $user->display_name ?? 'unknown') . ')');
$this->info('Email: ' . ($user->email ?? ''));
$this->info('Resolved Graph target: ' . ($target ?? '[none]'));
if ($this->input->getOption('show-target')) {
return $target ? 0 : 1;
}
if ($target === null) {
$this->error('No Microsoft Graph target could be resolved. Check user_lookup_strategy and related settings.');
return 1;
}
try {
$blueprint = new TestActivityBlueprint($user);
$this->notifier->notifyToTarget($user, $blueprint, $target);
$this->info('Test notification sent successfully.');
return 0;
} catch (\Throwable $e) {
$this->error('Sending failed: ' . $e->getMessage());
return 1;
}
}
}

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace SbpJm\FlarumMSTeamsWebhook\Notification;
use Flarum\Notification\Blueprint\BlueprintInterface;
use Flarum\User\User;
class TestActivityBlueprint implements BlueprintInterface
{
public function __construct(protected User $recipient)
{
}
public function getSubject()
{
return null;
}
public function getFromUser(): ?User
{
return $this->recipient;
}
public function getData(): ?array
{
return [
'test' => true,
];
}
public static function getType(): string
{
return 'teamsTest';
}
public static function getSubjectModel(): ?string
{
return null;
}
}

View File

@ -31,6 +31,11 @@ class TeamsActivityNotifier
return;
}
$this->notifyToTarget($user, $blueprint, $target);
}
public function notifyToTarget(User $user, BlueprintInterface $blueprint, string $target): void
{
$payload = $this->payloadFactory->make($user, $blueprint);
$token = $this->tokenProvider->getAccessToken();

View File

@ -63,6 +63,10 @@ class NotificationPayloadFactory
protected function buildPreviewText(BlueprintInterface $blueprint): string
{
if ($blueprint::getType() === 'teamsTest') {
return 'Flarum ➜ Teams Test erfolgreich angestoßen';
}
$actor = $blueprint->getFromUser();
$actorName = $actor instanceof User ? (string) ($actor->display_name ?? $actor->username ?? 'Jemand') : 'Jemand';
$type = $blueprint::getType();