Skip to content

Commit 80c7924

Browse files
committed
readme + remove smtp webhook reg
1 parent 127eee6 commit 80c7924

3 files changed

Lines changed: 38 additions & 106 deletions

File tree

README.md

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ Notifuse follows clean architecture principles with clear separation of concerns
5858
### Database
5959

6060
- **PostgreSQL**: Primary data storage with Squirrel query builder
61-
- **Migrations**: Database schema management and versioning
6261

6362
## 📁 Project Structure
6463

@@ -73,8 +72,6 @@ Notifuse follows clean architecture principles with clear separation of concerns
7372
├── console/ # React-based admin interface
7473
├── notification_center/ # Embeddable notification widget
7574
├── pkg/ # Public packages
76-
├── docs/ # Documentation (Mintlify)
77-
├── homepage/ # Marketing website (Astro)
7875
└── config/ # Configuration files
7976
```
8077

@@ -113,29 +110,38 @@ make build
113110
Notifuse can be configured through environment variables or configuration files:
114111

115112
```env
116-
# Database
117-
DATABASE_URL=postgres://user:password@localhost/notifuse
118-
119-
# Email Providers
120-
SENDGRID_API_KEY=your_sendgrid_key
121-
MAILGUN_API_KEY=your_mailgun_key
122-
AWS_ACCESS_KEY_ID=your_aws_key
123-
124-
# File Storage
125-
S3_BUCKET=your-bucket-name
126-
S3_REGION=us-east-1
127-
128-
# Application
129-
APP_PORT=8080
130-
APP_ENV=production
113+
# Server configuration
114+
SERVER_PORT=4000
115+
SERVER_HOST=127.0.0.1
116+
ROOT_EMAIL=your@email.com
117+
ENVIRONMENT=production
118+
API_ENDPOINT=https://your_endpoint.website.com
119+
120+
# Database configuration
121+
DB_HOST=localhost
122+
DB_PORT=5432
123+
DB_USER=postgre
124+
DB_PASSWORD=
125+
DB_PREFIX=notifuse
126+
DB_NAME=${DB_PREFIX}_system
127+
DB_SSLMODE=disable
128+
129+
# System email configuration
130+
SMTP_HOST=smtp.example.com
131+
SMTP_PORT=587
132+
SMTP_USERNAME=your-username
133+
SMTP_PASSWORD=your-password
134+
SMTP_FROM=noreply@example.com
135+
136+
# Security configuration
137+
PASETO_PRIVATE_KEY="generated_private_key_here"
138+
PASETO_PUBLIC_KEY="generated_public_key_here"
139+
SECRET_KEY="your_complex_secret_key_here"
131140
```
132141

133142
## 📚 Documentation
134143

135144
- **[Complete Documentation](https://docs.notifuse.com)** - Comprehensive guides and tutorials
136-
- **[API Reference](https://docs.notifuse.com/api-reference)** - REST API documentation
137-
- **[Self-Hosting Guide](https://docs.notifuse.com/deployment)** - Deployment and configuration
138-
- **[Developer Guide](https://docs.notifuse.com/development)** - Contributing and customization
139145

140146
## 🤝 Contributing
141147

@@ -156,7 +162,6 @@ Notifuse is released under the [Elastic License 2.0](LICENSE).
156162
- **Documentation**: [docs.notifuse.com](https://docs.notifuse.com)
157163
- **Email Support**: [hello@notifuse.com](mailto:hello@notifuse.com)
158164
- **GitHub Issues**: [Report bugs or request features](https://github.com/Notifuse/notifuse/issues)
159-
- **Community**: [Join our Discord](https://discord.gg/notifuse)
160165

161166
## 🌟 Why Choose Notifuse?
162167

@@ -169,4 +174,4 @@ Notifuse is released under the [Elastic License 2.0](LICENSE).
169174

170175
---
171176

172-
**Ready to get started?** [Try the live demo](https://demo.notifuse.com) or [deploy your own instance](https://docs.notifuse.com/deployment/docker) in minutes.
177+
**Ready to get started?** [Try the live demo](https://demo.notifuse.com) or [deploy your own instance](https://docs.notifuse.com) in minutes.

internal/service/workspace_service.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -810,8 +810,8 @@ func (s *WorkspaceService) CreateIntegration(ctx context.Context, workspaceID, n
810810
return "", err
811811
}
812812

813-
// If this is an email integration, register webhooks
814-
if integrationType == domain.IntegrationTypeEmail && s.webhookRegService != nil {
813+
// If this is an email integration, register webhooks (except for SMTP which doesn't support webhooks)
814+
if integrationType == domain.IntegrationTypeEmail && s.webhookRegService != nil && provider.Kind != domain.EmailProviderKindSMTP {
815815
// Define the events to register
816816
eventTypes := []domain.EmailEventType{
817817
domain.EmailEventDelivered,
@@ -934,8 +934,8 @@ func (s *WorkspaceService) DeleteIntegration(ctx context.Context, workspaceID, i
934934
return fmt.Errorf("integration not found")
935935
}
936936

937-
// Before removing the integration, attempt to unregister webhooks for email integrations
938-
if integration.Type == domain.IntegrationTypeEmail && s.webhookRegService != nil {
937+
// Before removing the integration, attempt to unregister webhooks for email integrations (except SMTP which doesn't support webhooks)
938+
if integration.Type == domain.IntegrationTypeEmail && s.webhookRegService != nil && integration.EmailProvider.Kind != domain.EmailProviderKindSMTP {
939939
// Try to get webhook status to check what's registered
940940
status, err := s.webhookRegService.GetWebhookStatus(ctx, workspaceID, integrationID)
941941
if err != nil {

internal/service/workspace_service_test.go

Lines changed: 6 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -778,21 +778,7 @@ func TestWorkspaceService_DeleteWorkspace(t *testing.T) {
778778
mockRepo.EXPECT().GetUserWorkspace(ctx, userID, workspaceID).Return(userWorkspace, nil).Times(2)
779779
mockRepo.EXPECT().GetByID(ctx, workspaceID).Return(workspace, nil).Times(2)
780780

781-
// For first integration
782-
webhookStatus1 := &domain.WebhookRegistrationStatus{
783-
EmailProviderKind: domain.EmailProviderKindSMTP,
784-
IsRegistered: true,
785-
}
786-
mockWebhookRegService.EXPECT().GetWebhookStatus(ctx, workspaceID, "integration-1").Return(webhookStatus1, nil)
787-
mockWebhookRegService.EXPECT().UnregisterWebhooks(ctx, workspaceID, "integration-1").Return(nil)
788-
789-
// For second integration
790-
webhookStatus2 := &domain.WebhookRegistrationStatus{
791-
EmailProviderKind: domain.EmailProviderKindSMTP,
792-
IsRegistered: true,
793-
}
794-
mockWebhookRegService.EXPECT().GetWebhookStatus(ctx, workspaceID, "integration-2").Return(webhookStatus2, nil)
795-
mockWebhookRegService.EXPECT().UnregisterWebhooks(ctx, workspaceID, "integration-2").Return(nil)
781+
// No webhook operations expected for SMTP integrations
796782

797783
// Once for each integration deletion
798784
mockRepo.EXPECT().Update(ctx, gomock.Any()).Return(nil).Times(2)
@@ -843,13 +829,7 @@ func TestWorkspaceService_DeleteWorkspace(t *testing.T) {
843829
mockRepo.EXPECT().GetUserWorkspace(ctx, userID, workspaceID).Return(userWorkspace, nil)
844830
mockRepo.EXPECT().GetByID(ctx, workspaceID).Return(workspace, nil)
845831

846-
// The integration deletion fails
847-
webhookStatus := &domain.WebhookRegistrationStatus{
848-
EmailProviderKind: domain.EmailProviderKindSMTP,
849-
IsRegistered: true,
850-
}
851-
mockWebhookRegService.EXPECT().GetWebhookStatus(ctx, workspaceID, "integration-1").Return(webhookStatus, nil)
852-
mockWebhookRegService.EXPECT().UnregisterWebhooks(ctx, workspaceID, "integration-1").Return(errors.New("webhook error"))
832+
// No webhook operations expected for SMTP integrations
853833
// The update fails
854834
mockRepo.EXPECT().Update(ctx, gomock.Any()).Return(errors.New("integration delete error"))
855835

@@ -984,25 +964,8 @@ func TestWorkspaceService_CreateIntegration(t *testing.T) {
984964
return nil
985965
})
986966

987-
// Expect webhook registration call for email integration
967+
// No webhook registration expected for SMTP provider
988968
mockConfig.APIEndpoint = "https://api.example.com"
989-
// Webhook config is provided for reference only, we use gomock.Any() since ID is random
990-
_ = &domain.WebhookRegistrationConfig{
991-
IntegrationID: "integration123", // This will be a random UUID, so use Any matcher
992-
EventTypes: []domain.EmailEventType{
993-
domain.EmailEventDelivered,
994-
domain.EmailEventBounce,
995-
domain.EmailEventComplaint,
996-
},
997-
}
998-
mockWebhookRegService.EXPECT().RegisterWebhooks(
999-
ctx,
1000-
workspaceID,
1001-
gomock.Any(), // Use Any for the config since integrationID is random
1002-
).Return(&domain.WebhookRegistrationStatus{
1003-
EmailProviderKind: domain.EmailProviderKindSMTP,
1004-
IsRegistered: true,
1005-
}, nil)
1006969

1007970
integrationID, err := service.CreateIntegration(ctx, workspaceID, integrationName, domain.IntegrationTypeEmail, provider)
1008971
require.NoError(t, err)
@@ -1328,21 +1291,7 @@ func TestWorkspaceService_DeleteIntegration(t *testing.T) {
13281291
mockRepo.EXPECT().GetUserWorkspace(ctx, userID, workspaceID).Return(expectedUserWorkspace, nil)
13291292
mockRepo.EXPECT().GetByID(ctx, workspaceID).Return(expectedWorkspace, nil)
13301293

1331-
// Expect webhook status check
1332-
webhookStatus := &domain.WebhookRegistrationStatus{
1333-
EmailProviderKind: domain.EmailProviderKindSMTP,
1334-
IsRegistered: true,
1335-
Endpoints: []domain.WebhookEndpointStatus{
1336-
{
1337-
URL: "https://api.example.com/webhooks",
1338-
Active: true,
1339-
},
1340-
},
1341-
}
1342-
mockWebhookRegService.EXPECT().GetWebhookStatus(ctx, workspaceID, integrationID).Return(webhookStatus, nil)
1343-
1344-
// Expect webhook unregistration
1345-
mockWebhookRegService.EXPECT().UnregisterWebhooks(ctx, workspaceID, integrationID).Return(nil)
1294+
// No webhook operations expected for SMTP provider
13461295

13471296
mockRepo.EXPECT().Update(ctx, gomock.Any()).DoAndReturn(func(ctx context.Context, workspace *domain.Workspace) error {
13481297
// Verify the integration was removed from the workspace
@@ -1440,25 +1389,7 @@ func TestWorkspaceService_DeleteIntegration(t *testing.T) {
14401389
mockRepo.EXPECT().GetUserWorkspace(ctx, userID, workspaceID).Return(expectedUserWorkspace, nil)
14411390
mockRepo.EXPECT().GetByID(ctx, workspaceID).Return(expectedWorkspace, nil)
14421391

1443-
// Expect webhook status check
1444-
mockWebhookRegService.EXPECT().GetWebhookStatus(ctx, workspaceID, integrationID).Return(&domain.WebhookRegistrationStatus{
1445-
EmailProviderKind: domain.EmailProviderKindSMTP,
1446-
IsRegistered: true,
1447-
Endpoints: []domain.WebhookEndpointStatus{
1448-
{
1449-
URL: "https://api.example.com/webhooks",
1450-
Active: true,
1451-
},
1452-
},
1453-
}, nil)
1454-
1455-
// Skip logger checks
1456-
1457-
// The unregistration fails
1458-
webhookError := errors.New("failed to unregister webhooks")
1459-
mockWebhookRegService.EXPECT().UnregisterWebhooks(ctx, workspaceID, integrationID).Return(webhookError)
1460-
1461-
// Skip logger checks
1392+
// No webhook operations expected for SMTP provider
14621393

14631394
mockRepo.EXPECT().Update(ctx, gomock.Any()).Return(nil)
14641395

@@ -1500,11 +1431,7 @@ func TestWorkspaceService_DeleteIntegration(t *testing.T) {
15001431
mockRepo.EXPECT().GetUserWorkspace(ctx, userID, workspaceID).Return(expectedUserWorkspace, nil)
15011432
mockRepo.EXPECT().GetByID(ctx, workspaceID).Return(expectedWorkspace, nil)
15021433

1503-
// Expect webhook status check
1504-
mockWebhookRegService.EXPECT().GetWebhookStatus(ctx, workspaceID, integrationID).Return(&domain.WebhookRegistrationStatus{
1505-
EmailProviderKind: domain.EmailProviderKindSMTP,
1506-
IsRegistered: false, // Not registered
1507-
}, nil)
1434+
// No webhook operations expected for SMTP provider
15081435

15091436
mockRepo.EXPECT().Update(ctx, gomock.Any()).DoAndReturn(func(ctx context.Context, workspace *domain.Workspace) error {
15101437
// Verify the reference was removed from settings

0 commit comments

Comments
 (0)