Files
sendico/api/server/internal/server/accountapiimp/delete.go
Stephan D 49b86efecb
Some checks failed
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/fx/1 Pipeline failed
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/fx/2 Pipeline failed
fx build fix
2025-11-08 00:30:29 +01:00

124 lines
5.0 KiB
Go

package accountapiimp
import (
"errors"
"net/http"
"github.com/tech/sendico/pkg/api/http/response"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mservice"
"github.com/tech/sendico/pkg/mutil/mzap"
"github.com/tech/sendico/server/interface/api/sresponse"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/zap"
)
func (a *AccountAPI) deleteProfile(r *http.Request, account *model.Account, token *sresponse.TokenData) http.HandlerFunc {
ctx := r.Context()
// Get the current organization from the request context
orgRef, err := a.getCurrentOrganizationRef(r)
if err != nil {
a.logger.Warn("Failed to get current organization", zap.Error(err), mzap.StorableRef(account))
return response.BadRequest(a.logger, a.Name(), "invalid_organization_context", "Invalid organization context")
}
// Get the organization
var org model.Organization
if err := a.odb.Get(ctx, *account.GetID(), orgRef, &org); err != nil {
a.logger.Error("Failed to fetch organization", zap.Error(err), mzap.StorableRef(account))
return response.Auto(a.logger, a.Name(), err)
}
// Delete the account (this will check if it's the only member)
if err := a.accService.DeleteAccount(ctx, &org, account.ID); err != nil {
if errors.Is(err, merrors.ErrInvalidArg) {
a.logger.Warn("Cannot delete account - validation failed", zap.Error(err), mzap.StorableRef(account))
return response.BadRequest(a.logger, a.Name(), "validation_failed", err.Error())
}
a.logger.Error("Failed to delete account", zap.Error(err), mzap.StorableRef(account))
return response.Auto(a.logger, a.Name(), err)
}
a.logger.Info("Account deleted successfully", mzap.StorableRef(account))
return response.Success(a.logger)
}
func (a *AccountAPI) deleteOrganization(r *http.Request, account *model.Account, token *sresponse.TokenData) http.HandlerFunc {
ctx := r.Context()
// Get the current organization from the request context
orgRef, err := a.getCurrentOrganizationRef(r)
if err != nil {
a.logger.Warn("Failed to get current organization", zap.Error(err), mzap.StorableRef(account))
return response.BadRequest(a.logger, a.Name(), "invalid_organization_context", "Invalid organization context")
}
// Get the organization
var org model.Organization
if err := a.odb.Get(ctx, *account.GetID(), orgRef, &org); err != nil {
a.logger.Error("Failed to fetch organization", zap.Error(err), mzap.StorableRef(account))
return response.Auto(a.logger, a.Name(), err)
}
// Delete the organization and all its data
if err := a.accService.DeleteOrganization(ctx, &org); err != nil {
a.logger.Error("Failed to delete organization", zap.Error(err), mzap.StorableRef(&org))
return response.Auto(a.logger, a.Name(), err)
}
a.logger.Info("Organization deleted successfully", mzap.StorableRef(&org))
return response.Success(a.logger)
}
func (a *AccountAPI) deleteAll(r *http.Request, account *model.Account, token *sresponse.TokenData) http.HandlerFunc {
ctx := r.Context()
// Get the current organization from the request context
orgRef, err := a.getCurrentOrganizationRef(r)
if err != nil {
a.logger.Warn("Failed to get current organization", zap.Error(err), mzap.StorableRef(account))
return response.BadRequest(a.logger, a.Name(), "invalid_organization_context", "Invalid organization context")
}
// Get the organization
var org model.Organization
if err := a.odb.Get(ctx, *account.GetID(), orgRef, &org); err != nil {
a.logger.Error("Failed to fetch organization", zap.Error(err), mzap.StorableRef(account))
return response.Auto(a.logger, a.Name(), err)
}
// Get organization permission reference
var orgPolicy model.PolicyDescription
if err := a.plcdb.GetBuiltInPolicy(ctx, mservice.Organizations, &orgPolicy); err != nil {
a.logger.Error("Failed to fetch organization policy", zap.Error(err), mzap.StorableRef(account))
return response.Auto(a.logger, a.Name(), err)
}
// Check if user has permission to delete the organization
canDelete, err := a.enf.Enforce(ctx, orgPolicy.ID, account.ID, orgRef, primitive.NilObjectID, model.ActionDelete)
if err != nil {
a.logger.Error("Failed to check delete permission", zap.Error(err), mzap.StorableRef(account))
return response.Auto(a.logger, a.Name(), err)
}
if !canDelete {
a.logger.Warn("User does not have permission to delete organization", mzap.StorableRef(account), mzap.StorableRef(&org))
return response.AccessDenied(a.logger, a.Name(), "Insufficient permissions to delete organization")
}
// Delete everything (organization + account)
if err := a.accService.DeleteAll(ctx, &org, account.ID); err != nil {
a.logger.Error("Failed to delete all data", zap.Error(err), mzap.StorableRef(&org), mzap.StorableRef(account))
return response.Auto(a.logger, a.Name(), err)
}
a.logger.Info("All data deleted successfully", mzap.StorableRef(&org), mzap.StorableRef(account))
return response.Success(a.logger)
}
// Helper method to get current organization reference from request context
func (a *AccountAPI) getCurrentOrganizationRef(r *http.Request) (primitive.ObjectID, error) {
return a.oph.GetRef(r)
}