feat: add mattermost notification provider

Add comprehensive Mattermost integration as a new notification provider:

## Backend Implementation:
- Add `mattermost` to notificationType enum and database schema
- Create mattermost table with webhookUrl, channel, username fields
- Implement CRUD operations: createMattermostNotification, updateMattermostNotification
- Add API routes: createMattermost, updateMattermost, testMattermostConnection
- Add sendMattermostNotification utility with proper payload formatting

## Frontend Implementation:
- Add MattermostIcon component with provided SVG logo
- Extend notification form with Mattermost schema validation
- Add webhook URL (required), channel and username (optional) form fields
- Integrate test connection functionality
- Add Mattermost to provider selection UI

## Notification Integration:
- Integrate across all notification types:
  - Build success/error notifications
  - Database backup notifications
  - Docker cleanup notifications
  - Dokploy restart notifications
  - Server threshold alerts
- Format messages using Markdown for Mattermost compatibility
- Handle optional channel (#prefix) and username override
- Graceful fallback for empty optional fields

## Features:
- Webhook-based messaging to Mattermost channels
- Optional channel targeting and custom username display
- Consistent formatting with other notification providers
- Full CRUD support with proper validation
- Test connection capability

Closes: Support for Mattermost team communication platform

# Conflicts:
#	apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx
#	apps/dokploy/components/icons/notification-icons.tsx
#	apps/dokploy/server/api/routers/notification.ts
#	packages/server/src/db/schema/notification.ts
#	packages/server/src/services/notification.ts
#	packages/server/src/utils/notifications/build-error.ts
#	packages/server/src/utils/notifications/build-success.ts
#	packages/server/src/utils/notifications/database-backup.ts
#	packages/server/src/utils/notifications/docker-cleanup.ts
#	packages/server/src/utils/notifications/dokploy-restart.ts
#	packages/server/src/utils/notifications/server-threshold.ts
#	packages/server/src/utils/notifications/utils.ts
This commit is contained in:
Hootan
2025-09-29 18:46:25 +02:00
parent dadef000d5
commit a0c87358eb
12 changed files with 459 additions and 14 deletions

View File

@@ -12,6 +12,7 @@ export const notificationType = pgEnum("notificationType", [
"email",
"gotify",
"ntfy",
"mattermost",
"lark",
]);
@@ -49,6 +50,9 @@ export const notifications = pgTable("notification", {
ntfyId: text("ntfyId").references(() => ntfy.ntfyId, {
onDelete: "cascade",
}),
mattermostId: text("mattermostId").references(() => mattermost.mattermostId, {
onDelete: "cascade",
}),
larkId: text("larkId").references(() => lark.larkId, {
onDelete: "cascade",
}),
@@ -120,6 +124,16 @@ export const ntfy = pgTable("ntfy", {
priority: integer("priority").notNull().default(3),
});
export const mattermost = pgTable("mattermost", {
mattermostId: text("mattermostId")
.notNull()
.primaryKey()
.$defaultFn(() => nanoid()),
webhookUrl: text("webhookUrl").notNull(),
channel: text("channel"),
username: text("username"),
});
export const lark = pgTable("lark", {
larkId: text("larkId")
.notNull()
@@ -153,6 +167,10 @@ export const notificationsRelations = relations(notifications, ({ one }) => ({
fields: [notifications.ntfyId],
references: [ntfy.ntfyId],
}),
mattermost: one(mattermost, {
fields: [notifications.mattermostId],
references: [mattermost.mattermostId],
}),
lark: one(lark, {
fields: [notifications.larkId],
references: [lark.larkId],
@@ -349,6 +367,49 @@ export const apiTestNtfyConnection = apiCreateNtfy.pick({
priority: true,
});
export const apiCreateMattermost = notificationsSchema
.pick({
appBuildError: true,
databaseBackup: true,
dokployRestart: true,
name: true,
appDeploy: true,
dockerCleanup: true,
serverThreshold: true,
})
.extend({
webhookUrl: z.string().min(1),
channel: z.string().optional(),
username: z.string().optional(),
})
.required({
name: true,
webhookUrl: true,
appBuildError: true,
databaseBackup: true,
dokployRestart: true,
appDeploy: true,
dockerCleanup: true,
serverThreshold: true,
});
export const apiUpdateMattermost = apiCreateMattermost.partial().extend({
notificationId: z.string().min(1),
mattermostId: z.string().min(1),
organizationId: z.string().optional(),
});
export const apiTestMattermostConnection = apiCreateMattermost
.pick({
webhookUrl: true,
channel: true,
username: true,
})
.extend({
channel: z.string().optional(),
username: z.string().optional(),
});
export const apiFindOneNotification = notificationsSchema
.pick({
notificationId: true,