Fix overflow interactions
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
@@ -667,7 +667,7 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func RejectByDocumentIDs(
|
||||
func RejectOrRevokeByDocumentIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
@@ -676,7 +676,11 @@ func RejectByDocumentIDs(
|
||||
) error {
|
||||
q := `
|
||||
UPDATE trust_center_document_accesses
|
||||
SET status = 'REJECTED'::trust_center_document_access_status
|
||||
SET
|
||||
status = CASE
|
||||
WHEN status = 'GRANTED'::trust_center_document_access_status THEN 'REVOKED'::trust_center_document_access_status
|
||||
ELSE 'REJECTED'::trust_center_document_access_status
|
||||
END
|
||||
WHERE
|
||||
%s
|
||||
AND trust_center_access_id = @trust_center_access_id
|
||||
@@ -733,7 +737,7 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func RejectByReportIDs(
|
||||
func RejectOrRevokeByReportIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
@@ -742,7 +746,11 @@ func RejectByReportIDs(
|
||||
) error {
|
||||
q := `
|
||||
UPDATE trust_center_document_accesses
|
||||
SET status = 'REJECTED'::trust_center_document_access_status
|
||||
SET
|
||||
status = CASE
|
||||
WHEN status = 'GRANTED'::trust_center_document_access_status THEN 'REVOKED'::trust_center_document_access_status
|
||||
ELSE 'REJECTED'::trust_center_document_access_status
|
||||
END
|
||||
WHERE
|
||||
%s
|
||||
AND trust_center_access_id = @trust_center_access_id
|
||||
@@ -1044,7 +1052,7 @@ ON CONFLICT DO NOTHING
|
||||
"trust_center_document_access_entity_type": TrustCenterDocumentAccessEntityType,
|
||||
"trust_center_access_id": trustCenterAccessID,
|
||||
"report_ids": reportIDs,
|
||||
"requested": status,
|
||||
"status": status,
|
||||
"created_at": createdAt,
|
||||
"updated_at": createdAt,
|
||||
}
|
||||
@@ -1141,7 +1149,7 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func RejectByTrustCenterFileIDs(
|
||||
func RejectOrRevokeByTrustCenterFileIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
@@ -1150,7 +1158,11 @@ func RejectByTrustCenterFileIDs(
|
||||
) error {
|
||||
q := `
|
||||
UPDATE trust_center_document_accesses
|
||||
SET status = 'REJECTED'::trust_center_document_access_status
|
||||
SET
|
||||
status = CASE
|
||||
WHEN status = 'GRANTED'::trust_center_document_access_status THEN 'REVOKED'::trust_center_document_access_status
|
||||
ELSE 'REJECTED'::trust_center_document_access_status
|
||||
END
|
||||
WHERE
|
||||
%s
|
||||
AND trust_center_access_id = @trust_center_access_id
|
||||
|
||||
@@ -17,7 +17,6 @@ package trust_v1
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -25,6 +24,7 @@ import (
|
||||
|
||||
"go.gearno.de/kit/httpserver"
|
||||
"go.gearno.de/kit/log"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/slack"
|
||||
"go.probo.inc/probo/pkg/trust"
|
||||
@@ -34,8 +34,11 @@ type (
|
||||
SlackInteractivePayload struct {
|
||||
ResponseURL string `json:"response_url"`
|
||||
Actions []struct {
|
||||
ActionID string `json:"action_id"`
|
||||
Value string `json:"value"`
|
||||
ActionID string `json:"action_id"`
|
||||
Value string `json:"value"`
|
||||
SelectedOption struct {
|
||||
Value string `json:"value"`
|
||||
} `json:"selected_option"`
|
||||
} `json:"actions"`
|
||||
Container struct {
|
||||
MessageTS string `json:"message_ts"`
|
||||
@@ -49,6 +52,11 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
StatusAccept = "accept"
|
||||
StatusReject = "reject"
|
||||
)
|
||||
|
||||
func slackHandler(trustSvc *trust.Service, slackSigningSecret string, logger *log.Logger) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
@@ -102,8 +110,9 @@ func slackHandler(trustSvc *trust.Service, slackSigningSecret string, logger *lo
|
||||
httpserver.RenderJSON(w, http.StatusOK, SlackInteractiveResponse{Success: true, Message: "no action required"})
|
||||
return
|
||||
}
|
||||
|
||||
action := slackPayload.Actions[0]
|
||||
if action.Value == "" {
|
||||
if action.Value == "" && action.SelectedOption.Value == "" {
|
||||
httpserver.RenderJSON(w, http.StatusOK, SlackInteractiveResponse{Success: true, Message: "no action required"})
|
||||
return
|
||||
}
|
||||
@@ -149,9 +158,10 @@ func slackHandler(trustSvc *trust.Service, slackSigningSecret string, logger *lo
|
||||
var documentIDs []gid.GID
|
||||
var reportIDs []gid.GID
|
||||
var fileIDs []gid.GID
|
||||
var statusAction string
|
||||
|
||||
switch action.ActionID {
|
||||
case "accept_all", "reject_all":
|
||||
// accept_all, reject_all
|
||||
if strings.HasSuffix(action.ActionID, "_all") {
|
||||
currentMessageId, err := gid.ParseGID(action.Value)
|
||||
if err != nil {
|
||||
httpserver.RenderJSON(w, http.StatusBadRequest, SlackInteractiveResponse{Success: false, Message: "invalid message ID"})
|
||||
@@ -164,36 +174,57 @@ func slackHandler(trustSvc *trust.Service, slackSigningSecret string, logger *lo
|
||||
httpserver.RenderJSON(w, http.StatusInternalServerError, SlackInteractiveResponse{Success: false, Message: "internal server error"})
|
||||
return
|
||||
}
|
||||
case "accept_document", "reject_document":
|
||||
docID, err := gid.ParseGID(action.Value)
|
||||
if err != nil {
|
||||
httpserver.RenderJSON(w, http.StatusBadRequest, SlackInteractiveResponse{Success: false, Message: "invalid document ID"})
|
||||
|
||||
if strings.HasPrefix(action.ActionID, "accept_") {
|
||||
statusAction = "accept"
|
||||
} else {
|
||||
statusAction = "reject"
|
||||
}
|
||||
} else {
|
||||
var gID gid.GID
|
||||
|
||||
// handle_<document|report|file> is used in an overflow menu (a select) to choose between grant and reject on requested accesses
|
||||
if strings.HasPrefix(action.ActionID, "handle_") {
|
||||
// action value is the select option value. <accept|reject>-<ID>
|
||||
params := strings.Split(action.SelectedOption.Value, "/")
|
||||
statusAction = params[0]
|
||||
|
||||
gID, err = gid.ParseGID(params[1])
|
||||
if err != nil {
|
||||
httpserver.RenderJSON(w, http.StatusBadRequest, SlackInteractiveResponse{Success: false, Message: "invalid ID"})
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// accept_<document|report|file>, reject_<document|report|file>, revoke_<document|report|file>
|
||||
gID, err = gid.ParseGID(action.Value)
|
||||
if err != nil {
|
||||
httpserver.RenderJSON(w, http.StatusBadRequest, SlackInteractiveResponse{Success: false, Message: "invalid ID"})
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(action.ActionID, "accept_") {
|
||||
statusAction = StatusAccept
|
||||
} else {
|
||||
statusAction = StatusReject
|
||||
}
|
||||
}
|
||||
|
||||
switch gID.EntityType() {
|
||||
case coredata.DocumentEntityType:
|
||||
documentIDs = []gid.GID{gID}
|
||||
case coredata.ReportEntityType:
|
||||
reportIDs = []gid.GID{gID}
|
||||
case coredata.TrustCenterFileEntityType:
|
||||
fileIDs = []gid.GID{gID}
|
||||
default:
|
||||
logger.ErrorCtx(ctx, "unknown entity type", log.Error(err))
|
||||
httpserver.RenderJSON(w, http.StatusInternalServerError, SlackInteractiveResponse{Success: false, Message: "internal server error"})
|
||||
return
|
||||
}
|
||||
documentIDs = []gid.GID{docID}
|
||||
|
||||
case "accept_report", "reject_report":
|
||||
repID, err := gid.ParseGID(action.Value)
|
||||
if err != nil {
|
||||
httpserver.RenderJSON(w, http.StatusBadRequest, SlackInteractiveResponse{Success: false, Message: "invalid report ID"})
|
||||
return
|
||||
}
|
||||
reportIDs = []gid.GID{repID}
|
||||
|
||||
case "accept_file", "reject_file":
|
||||
fileID, err := gid.ParseGID(action.Value)
|
||||
if err != nil {
|
||||
httpserver.RenderJSON(w, http.StatusBadRequest, SlackInteractiveResponse{Success: false, Message: "invalid file ID"})
|
||||
return
|
||||
}
|
||||
fileIDs = []gid.GID{fileID}
|
||||
|
||||
default:
|
||||
httpserver.RenderJSON(w, http.StatusBadRequest, SlackInteractiveResponse{Success: false, Message: fmt.Sprintf("unknown action: %s", action.ActionID)})
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(action.ActionID, "accept_") {
|
||||
switch statusAction {
|
||||
case StatusAccept:
|
||||
if err := tenantSvc.TrustCenterAccesses.GrantByIDs(
|
||||
ctx,
|
||||
initialSlackMessage.OrganizationID,
|
||||
@@ -206,10 +237,8 @@ func slackHandler(trustSvc *trust.Service, slackSigningSecret string, logger *lo
|
||||
httpserver.RenderJSON(w, http.StatusInternalServerError, SlackInteractiveResponse{Success: false, Message: "internal server error"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(action.ActionID, "reject_") {
|
||||
if err := tenantSvc.TrustCenterAccesses.RejectByIDs(
|
||||
case StatusReject:
|
||||
if err := tenantSvc.TrustCenterAccesses.RejectOrRevokeByIDs(
|
||||
ctx,
|
||||
initialSlackMessage.OrganizationID,
|
||||
requesterEmail,
|
||||
@@ -221,6 +250,10 @@ func slackHandler(trustSvc *trust.Service, slackSigningSecret string, logger *lo
|
||||
httpserver.RenderJSON(w, http.StatusInternalServerError, SlackInteractiveResponse{Success: false, Message: "internal server error"})
|
||||
return
|
||||
}
|
||||
default:
|
||||
logger.ErrorCtx(ctx, "unknown status action access", log.Error(err))
|
||||
httpserver.RenderJSON(w, http.StatusInternalServerError, SlackInteractiveResponse{Success: false, Message: "internal server error"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := tenantSvc.SlackMessages.UpdateSlackAccessMessage(
|
||||
|
||||
@@ -62,36 +62,57 @@
|
||||
}{{range .Documents}},
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "<https://{{$.Domain}}/organizations/{{$.OrganizationID}}/documents/{{.ID}}|{{jsonEscape .Title}}>"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
"text": "<https://{{$.Domain}}/organizations/{{$.OrganizationID}}/documents/{{.ID}}|{{jsonEscape .Title}}>"
|
||||
},
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
{{if eq .Status "GRANTED"}}
|
||||
"text": "<https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/access|✓ Granted>"
|
||||
{{else if eq .Status "REJECTED"}}
|
||||
"text": "✗ Rejected"
|
||||
{{else if eq .Status "REVOKED"}}
|
||||
"text": "✗ Revoked"
|
||||
{{else}}
|
||||
"text": "Requested"
|
||||
{{end}}
|
||||
}
|
||||
],
|
||||
"accessory": {{if eq .Status "GRANTED"}}{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "✓ Granted"
|
||||
"text": "Revoke"
|
||||
},
|
||||
"url": "https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/access"
|
||||
}{{else if eq .Status "REJECTED"}}{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "✗ Rejected"
|
||||
},
|
||||
"url": "https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/access"
|
||||
}{{else if eq .Status "REVOKED"}}{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "✗ Revoked"
|
||||
},
|
||||
"url": "https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/access"
|
||||
"action_id": "reject_document",
|
||||
"value": "{{.ID}}",
|
||||
"style": "danger"
|
||||
}{{else if eq .Status "REQUESTED"}}{
|
||||
"type": "overflow",
|
||||
"options": [
|
||||
{
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Accept"
|
||||
},
|
||||
"value": "accept/{{.ID}}"
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Reject"
|
||||
},
|
||||
"value": "reject/{{.ID}}"
|
||||
}
|
||||
],
|
||||
"action_id": "handle_document"
|
||||
}{{else}}{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Accept"
|
||||
"text": "Grant"
|
||||
},
|
||||
"action_id": "accept_document",
|
||||
"value": "{{.ID}}",
|
||||
@@ -110,22 +131,57 @@
|
||||
}{{range .Reports}},
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "<https://{{$.Domain}}/organizations/{{$.OrganizationID}}/audits/{{.AuditID}}|{{jsonEscape .Title}}>"
|
||||
},
|
||||
"accessory": {{if .Granted}}{
|
||||
"fields": [
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
"text": "<https://{{$.Domain}}/organizations/{{$.OrganizationID}}/audits/{{.AuditID}}|{{jsonEscape .Title}}>"
|
||||
},
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
{{if eq .Status "GRANTED"}}
|
||||
"text": "<https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/access|✓ Granted>"
|
||||
{{else if eq .Status "REJECTED"}}
|
||||
"text": "✗ Rejected"
|
||||
{{else if eq .Status "REVOKED"}}
|
||||
"text": "✗ Revoked"
|
||||
{{else}}
|
||||
"text": "Requested"
|
||||
{{end}}
|
||||
}
|
||||
],
|
||||
"accessory": {{if eq .Status "GRANTED"}}{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "✓ Granted"
|
||||
"text": "Revoke"
|
||||
},
|
||||
"url": "https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/access"
|
||||
"action_id": "reject_report",
|
||||
"value": "{{.ID}}",
|
||||
"style": "danger"
|
||||
}{{else if eq .Status "REQUESTED"}}{
|
||||
"type": "overflow",
|
||||
"options": [
|
||||
{
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Accept"
|
||||
},
|
||||
"value": "accept/{{.ID}}"
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Reject"
|
||||
},
|
||||
"value": "reject/{{.ID}}"
|
||||
}
|
||||
],
|
||||
"action_id": "handle_report"
|
||||
}{{else}}{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Accept"
|
||||
"text": "Revoke"
|
||||
},
|
||||
"action_id": "accept_report",
|
||||
"value": "{{.ID}}",
|
||||
@@ -144,22 +200,57 @@
|
||||
}{{range .Files}},
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "<https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/files|{{jsonEscape .Name}}>{{if .Category}} ({{jsonEscape .Category}}){{end}}"
|
||||
},
|
||||
"accessory": {{if .Granted}}{
|
||||
"fields": [
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
"text": "<https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/files|{{jsonEscape .Name}}>{{if .Category}} ({{jsonEscape .Category}}){{end}}"
|
||||
},
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
{{if eq .Status "GRANTED"}}
|
||||
"text": "<https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/access|✓ Granted>"
|
||||
{{else if eq .Status "REJECTED"}}
|
||||
"text": "✗ Rejected"
|
||||
{{else if eq .Status "REVOKED"}}
|
||||
"text": "✗ Revoked"
|
||||
{{else}}
|
||||
"text": "Requested"
|
||||
{{end}}
|
||||
}
|
||||
],
|
||||
"accessory": {{if eq .Status "GRANTED"}}{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "✓ Granted"
|
||||
"text": "Revoke"
|
||||
},
|
||||
"url": "https://{{$.Domain}}/organizations/{{$.OrganizationID}}/trust-center/access"
|
||||
"action_id": "reject_file",
|
||||
"value": "{{.ID}}",
|
||||
"style": "danger"
|
||||
}{{else if eq .Status "REQUESTED"}}{
|
||||
"type": "overflow",
|
||||
"options": [
|
||||
{
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Accept"
|
||||
},
|
||||
"value": "accept/{{.ID}}"
|
||||
},
|
||||
{
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Reject"
|
||||
},
|
||||
"value": "reject/{{.ID}}"
|
||||
}
|
||||
],
|
||||
"action_id": "handle_file"
|
||||
}{{else}}{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Accept"
|
||||
"text": "Grant"
|
||||
},
|
||||
"action_id": "accept_file",
|
||||
"value": "{{.ID}}",
|
||||
|
||||
@@ -576,7 +576,7 @@ func (s *TrustCenterAccessService) sendTrustCenterAccessEmail(
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TrustCenterAccessService) RejectByIDs(
|
||||
func (s *TrustCenterAccessService) RejectOrRevokeByIDs(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
email string,
|
||||
@@ -599,20 +599,20 @@ func (s *TrustCenterAccessService) RejectByIDs(
|
||||
|
||||
if len(documentIDs) > 0 {
|
||||
shouldSendEmail = true
|
||||
if err := coredata.RejectByDocumentIDs(ctx, tx, s.svc.scope, access.ID, documentIDs); err != nil {
|
||||
return fmt.Errorf("cannot reject document accesses: %w", err)
|
||||
if err := coredata.RejectOrRevokeByDocumentIDs(ctx, tx, s.svc.scope, access.ID, documentIDs); err != nil {
|
||||
return fmt.Errorf("cannot reject/revoke document accesses: %w", err)
|
||||
}
|
||||
}
|
||||
if len(reportIDs) > 0 {
|
||||
shouldSendEmail = true
|
||||
if err := coredata.RejectByReportIDs(ctx, tx, s.svc.scope, access.ID, reportIDs); err != nil {
|
||||
return fmt.Errorf("cannot reject report accesses: %w", err)
|
||||
if err := coredata.RejectOrRevokeByReportIDs(ctx, tx, s.svc.scope, access.ID, reportIDs); err != nil {
|
||||
return fmt.Errorf("cannot reject/revoke report accesses: %w", err)
|
||||
}
|
||||
}
|
||||
if len(fileIDs) > 0 {
|
||||
shouldSendEmail = true
|
||||
if err := coredata.RejectByTrustCenterFileIDs(ctx, tx, s.svc.scope, access.ID, fileIDs); err != nil {
|
||||
return fmt.Errorf("cannot reject trust center file accesses: %w", err)
|
||||
if err := coredata.RejectOrRevokeByTrustCenterFileIDs(ctx, tx, s.svc.scope, access.ID, fileIDs); err != nil {
|
||||
return fmt.Errorf("cannot reject/revoke trust center file accesses: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user