Passed
Pull Request — master (#1517)
by
unknown
02:36
created

postgres.*TenantWriter.DeleteTenant   B

Complexity

Conditions 6

Size

Total Lines 44
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 31
nop 2
dl 0
loc 44
rs 8.2026
c 0
b 0
f 0
1
package postgres
2
3
import (
4
	"context"
5
	"errors"
6
	"fmt"
7
	"log/slog"
8
	"strings"
9
	"time"
10
11
	"github.com/jackc/pgx/v5"
12
13
	"go.opentelemetry.io/otel/codes"
14
15
	"google.golang.org/protobuf/types/known/timestamppb"
16
17
	"github.com/Permify/permify/internal/storage/postgres/utils"
18
	db "github.com/Permify/permify/pkg/database/postgres"
19
	base "github.com/Permify/permify/pkg/pb/base/v1"
20
)
21
22
// TenantWriter - Structure for Tenant Writer
23
type TenantWriter struct {
24
	database *db.Postgres
25
	// options
26
	txOptions pgx.TxOptions
27
}
28
29
// NewTenantWriter - Creates a new TenantWriter
30
func NewTenantWriter(database *db.Postgres) *TenantWriter {
31
	return &TenantWriter{
32
		database:  database,
33
		txOptions: pgx.TxOptions{IsoLevel: pgx.ReadCommitted, AccessMode: pgx.ReadWrite},
34
	}
35
}
36
37
// CreateTenant - Creates a new Tenant
38
func (w *TenantWriter) CreateTenant(ctx context.Context, id, name string) (result *base.Tenant, err error) {
39
	ctx, span := tracer.Start(ctx, "tenant-writer.create-tenant")
40
	defer span.End()
41
42
	slog.DebugContext(ctx, "creating new tenant", slog.Any("id", id), slog.Any("name", name))
43
44
	var createdAt time.Time
45
	err = w.database.WritePool.QueryRow(ctx, utils.InsertTenantTemplate, id, name).Scan(&createdAt)
46
	if err != nil {
47
		if strings.Contains(err.Error(), "duplicate key value") {
48
			span.RecordError(err)
49
			span.SetStatus(codes.Error, err.Error())
50
			slog.ErrorContext(ctx, "error encountered", slog.Any("error", err))
51
			return nil, errors.New(base.ErrorCode_ERROR_CODE_UNIQUE_CONSTRAINT.String())
52
		}
53
		return nil, utils.HandleError(ctx, span, err, base.ErrorCode_ERROR_CODE_EXECUTION)
54
	}
55
56
	slog.DebugContext(ctx, "successfully created Tenant", slog.Any("id", id), slog.Any("name", name), slog.Any("created_at", createdAt))
57
58
	return &base.Tenant{
59
		Id:        id,
60
		Name:      name,
61
		CreatedAt: timestamppb.New(createdAt),
62
	}, nil
63
}
64
65
// DeleteTenant - Deletes a Tenant
66
func (w *TenantWriter) DeleteTenant(ctx context.Context, tenantID string) (result *base.Tenant, err error) {
67
	ctx, span := tracer.Start(ctx, "tenant-writer.delete-tenant")
68
	defer span.End()
69
70
	slog.DebugContext(ctx, "deleting tenant", slog.Any("tenant_id", tenantID))
71
72
	tx, err := w.database.WritePool.Begin(ctx)
73
	if err != nil {
74
		return nil, utils.HandleError(ctx, span, err, base.ErrorCode_ERROR_CODE_EXECUTION)
75
	}
76
	defer tx.Rollback(ctx)
77
78
	tables := []string{"bundles", "relation_tuples", "attributes", "schema_definitions", "transactions"}
79
	var totalDeleted int
80
81
	for _, table := range tables {
82
		query := fmt.Sprintf(utils.DeleteAllByTenantTemplate, table)
0 ignored issues
show
introduced by
can't check non-constant format in call to Sprintf
Loading history...
83
		result, err := tx.Exec(ctx, query, tenantID)
84
		if err != nil {
85
			return nil, utils.HandleError(ctx, span, err, base.ErrorCode_ERROR_CODE_EXECUTION)
86
		}
87
		totalDeleted += int(result.RowsAffected())
88
	}
89
90
	err = tx.Commit(ctx)
91
	if err != nil {
92
		return nil, utils.HandleError(ctx, span, err, base.ErrorCode_ERROR_CODE_EXECUTION)
93
	}
94
95
	var name string
96
	var createdAt time.Time
97
98
	tenant := tx.QueryRow(ctx, utils.DeleteTenantTemplate, tenantID)
99
	if err != nil {
100
		return nil, utils.HandleError(ctx, span, err, base.ErrorCode_ERROR_CODE_EXECUTION)
101
	} else {
102
		tenant.Scan(&name, &createdAt)
103
	}
104
105
	return &base.Tenant{
106
		Id:        tenantID,
107
		Name:      name,
108
		CreatedAt: timestamppb.New(createdAt),
109
	}, nil
110
}
111