Add slack integration
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -34,6 +34,7 @@ type (
|
||||
proboSvc *probo.Service
|
||||
encryptionKey cipher.EncryptionKey
|
||||
tokenSecret string
|
||||
hostname string
|
||||
auth *auth.Service
|
||||
html2pdfConverter *html2pdf.Converter
|
||||
fileManager *filemanager.Service
|
||||
@@ -47,6 +48,7 @@ type (
|
||||
proboSvc *probo.Service
|
||||
encryptionKey cipher.EncryptionKey
|
||||
tokenSecret string
|
||||
hostname string
|
||||
auth *auth.Service
|
||||
html2pdfConverter *html2pdf.Converter
|
||||
fileManager *filemanager.Service
|
||||
@@ -66,6 +68,7 @@ func NewService(
|
||||
pgClient *pg.Client,
|
||||
s3Client *s3.Client,
|
||||
bucket string,
|
||||
hostname string,
|
||||
encryptionKey cipher.EncryptionKey,
|
||||
tokenSecret string,
|
||||
auth *auth.Service,
|
||||
@@ -78,6 +81,7 @@ func NewService(
|
||||
bucket: bucket,
|
||||
encryptionKey: encryptionKey,
|
||||
tokenSecret: tokenSecret,
|
||||
hostname: hostname,
|
||||
auth: auth,
|
||||
html2pdfConverter: html2pdfConverter,
|
||||
fileManager: fileManagerService,
|
||||
@@ -93,6 +97,7 @@ func (s *Service) WithTenant(tenantID gid.TenantID) *TenantService {
|
||||
proboSvc: s.proboSvc,
|
||||
encryptionKey: s.encryptionKey,
|
||||
tokenSecret: s.tokenSecret,
|
||||
hostname: s.hostname,
|
||||
auth: s.auth,
|
||||
html2pdfConverter: s.html2pdfConverter,
|
||||
fileManager: s.fileManager,
|
||||
|
||||
24
pkg/trust/templates.go
Normal file
24
pkg/trust/templates.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package trust
|
||||
|
||||
import (
|
||||
"embed"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed templates/*.tmpl
|
||||
Templates embed.FS
|
||||
)
|
||||
7
pkg/trust/templates/access-request.txt.tmpl
Normal file
7
pkg/trust/templates/access-request.txt.tmpl
Normal file
@@ -0,0 +1,7 @@
|
||||
*New Trust Center Access Request*
|
||||
|
||||
*Organization:* {{.OrganizationName}}
|
||||
*Requested by:* {{.RequesterName}}
|
||||
*Email:* {{.RequesterEmail}}
|
||||
|
||||
<{{.ConsoleUrl}}|View Access Requests>
|
||||
@@ -15,22 +15,28 @@
|
||||
package trust
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/auth"
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/auth"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
var (
|
||||
accessRequestTemplate = template.Must(template.ParseFS(Templates, "templates/access-request.txt.tmpl"))
|
||||
)
|
||||
|
||||
type (
|
||||
TrustCenterAccessService struct {
|
||||
svc *TenantService
|
||||
svc *TenantService
|
||||
auth *auth.Service
|
||||
}
|
||||
|
||||
@@ -45,6 +51,7 @@ type (
|
||||
|
||||
const (
|
||||
TokenTypeTrustCenterAccess = "trust_center_access"
|
||||
TrustCenterAccessURLFormat = "https://%s/organizations/%s/trust-center/access"
|
||||
)
|
||||
|
||||
func (s TrustCenterAccessService) ValidateToken(
|
||||
@@ -74,9 +81,9 @@ func (s TrustCenterAccessService) Request(
|
||||
now := time.Now()
|
||||
|
||||
var access *coredata.TrustCenterAccess
|
||||
var trustCenter *coredata.TrustCenter
|
||||
|
||||
err := s.svc.pg.WithTx(ctx, func(tx pg.Conn) error {
|
||||
var trustCenter *coredata.TrustCenter
|
||||
var organizationID gid.GID
|
||||
trustCenter = &coredata.TrustCenter{}
|
||||
if err := trustCenter.LoadByID(ctx, tx, s.svc.scope, req.TrustCenterID); err != nil {
|
||||
@@ -168,6 +175,10 @@ func (s TrustCenterAccessService) Request(
|
||||
return fmt.Errorf("cannot bulk insert trust center report accesses: %w", err)
|
||||
}
|
||||
|
||||
if err := s.queueSlackNotification(ctx, tx, organizationID, access.Name, access.Email); err != nil {
|
||||
return fmt.Errorf("cannot queue slack notification: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -330,3 +341,42 @@ func filterExistingIDs(allIDs []gid.GID, existingIDs []gid.GID) []gid.GID {
|
||||
|
||||
return newIDs
|
||||
}
|
||||
|
||||
func (s TrustCenterAccessService) queueSlackNotification(
|
||||
ctx context.Context,
|
||||
tx pg.Conn,
|
||||
organizationID gid.GID,
|
||||
requesterName string,
|
||||
requesterEmail string,
|
||||
) error {
|
||||
var organization coredata.Organization
|
||||
if err := organization.LoadByID(ctx, tx, s.svc.scope, organizationID); err != nil {
|
||||
return fmt.Errorf("cannot load organization: %w", err)
|
||||
}
|
||||
|
||||
consoleURL := fmt.Sprintf(TrustCenterAccessURLFormat, s.svc.hostname, organizationID)
|
||||
|
||||
data := struct {
|
||||
OrganizationName string
|
||||
RequesterName string
|
||||
RequesterEmail string
|
||||
ConsoleUrl string
|
||||
}{
|
||||
OrganizationName: organization.Name,
|
||||
RequesterName: requesterName,
|
||||
RequesterEmail: requesterEmail,
|
||||
ConsoleUrl: consoleURL,
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := accessRequestTemplate.Execute(&buf, data); err != nil {
|
||||
return fmt.Errorf("failed to execute template: %w", err)
|
||||
}
|
||||
|
||||
slackMessage := coredata.NewSlackMessage(s.svc.scope, organizationID, buf.String())
|
||||
if err := slackMessage.Insert(ctx, tx, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert slack message: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user