Passed
Pull Request — master (#2657)
by
unknown
03:06
created

internal/servers/permission_server.go   A

Size/Duplication

Total Lines 228
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 26
eloc 140
dl 0
loc 228
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A servers.*PermissionServer.Check 0 18 3
A servers.NewPermissionServer 0 3 1
A servers.*PermissionServer.Expand 0 18 3
A servers.*PermissionServer.LookupSubject 0 18 3
A servers.*PermissionServer.LookupEntityStream 0 18 3
B servers.*PermissionServer.BulkCheck 0 73 7
A servers.*PermissionServer.LookupEntity 0 18 3
A servers.*PermissionServer.SubjectPermission 0 18 3
1
package servers
2
3
import (
4
	"context"
5
	"log/slog"
6
7
	otelCodes "go.opentelemetry.io/otel/codes"
8
	"google.golang.org/grpc/status"
9
10
	"github.com/Permify/permify/internal"
11
	"github.com/Permify/permify/internal/invoke"
12
	v1 "github.com/Permify/permify/pkg/pb/base/v1"
13
)
14
15
// PermissionServer - Structure for Permission Server
16
type PermissionServer struct {
17
	v1.UnimplementedPermissionServer
18
19
	invoker invoke.Invoker
20
}
21
22
// NewPermissionServer - Creates new Permission Server
23
func NewPermissionServer(i invoke.Invoker) *PermissionServer {
24
	return &PermissionServer{
25
		invoker: i,
26
	}
27
}
28
29
// Check - Performs Authorization Check
30
func (r *PermissionServer) Check(ctx context.Context, request *v1.PermissionCheckRequest) (*v1.PermissionCheckResponse, error) {
31
	ctx, span := internal.Tracer.Start(ctx, "permissions.check")
32
	defer span.End()
33
34
	v := request.Validate()
35
	if v != nil {
36
		return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
37
	}
38
39
	response, err := r.invoker.Check(ctx, request)
40
	if err != nil {
41
		span.RecordError(err)
42
		span.SetStatus(otelCodes.Error, err.Error())
43
		slog.ErrorContext(ctx, err.Error())
44
		return nil, status.Error(GetStatus(err), err.Error())
45
	}
46
47
	return response, nil
48
}
49
50
// BulkCheck - Performs multiple authorization checks in a single request
51
func (r *PermissionServer) BulkCheck(ctx context.Context, request *v1.PermissionBulkCheckRequest) (*v1.PermissionBulkCheckResponse, error) {
52
	ctx, span := internal.Tracer.Start(ctx, "permissions.bulk-check")
53
	defer span.End()
54
55
	// Validate tenant_id
56
	if request.GetTenantId() == "" {
57
		err := status.Error(GetStatus(nil), "tenant_id is required")
58
		span.RecordError(err)
59
		span.SetStatus(otelCodes.Error, err.Error())
60
		return nil, err
61
	}
62
63
	// Validate number of requests
64
	if len(request.GetItems()) == 0 {
65
		err := status.Error(GetStatus(nil), "at least one item is required")
66
		span.RecordError(err)
67
		span.SetStatus(otelCodes.Error, err.Error())
68
		return nil, err
69
	}
70
71
	if len(request.GetItems()) > 100 {
72
		err := status.Error(GetStatus(nil), "maximum 100 items allowed")
73
		span.RecordError(err)
74
		span.SetStatus(otelCodes.Error, err.Error())
75
		return nil, err
76
	}
77
78
	// Process each check request
79
	results := make([]*v1.PermissionCheckResponse, len(request.GetItems()))
80
	for i, checkRequestItem := range request.GetItems() {
81
82
		// Validate individual request
83
		v := checkRequestItem.Validate()
84
		if v != nil {
85
			// Return error response for this check
86
			results[i] = &v1.PermissionCheckResponse{
87
				Can: v1.CheckResult_CHECK_RESULT_DENIED,
88
				Metadata: &v1.PermissionCheckResponseMetadata{
89
					CheckCount: 0,
90
				},
91
			}
92
			continue
93
		}
94
95
		// Perform the check using existing Check function
96
		checkRequest := &v1.PermissionCheckRequest{
97
			TenantId:      request.GetTenantId(),
98
			Subject:       checkRequestItem.GetSubject(),
99
			Entity:        checkRequestItem.GetEntity(),
100
			Permission:    checkRequestItem.GetPermission(),
101
			Metadata: 	   request.GetMetadata(),
102
			Context:       request.GetContext(),
103
			Arguments:     request.GetArguments(),
104
		}
105
		response, err := r.invoker.Check(ctx, checkRequest)
106
		if err != nil {
107
			// Log error but don't fail the entire bulk operation
108
			slog.ErrorContext(ctx, "check failed in bulk operation", "error", err.Error(), "index", i)
109
			results[i] = &v1.PermissionCheckResponse{
110
				Can: v1.CheckResult_CHECK_RESULT_DENIED,
111
				Metadata: &v1.PermissionCheckResponseMetadata{
112
					CheckCount: 0,
113
				},
114
			}
115
			continue
116
		}
117
118
		results[i] = response
119
	}
120
121
	return &v1.PermissionBulkCheckResponse{
122
		Results: results,
123
	}, nil
124
}
125
126
// Expand - Get schema actions in a tree structure
127
func (r *PermissionServer) Expand(ctx context.Context, request *v1.PermissionExpandRequest) (*v1.PermissionExpandResponse, error) {
128
	ctx, span := internal.Tracer.Start(ctx, "permissions.expand")
129
	defer span.End()
130
131
	v := request.Validate()
132
	if v != nil {
133
		return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
134
	}
135
136
	response, err := r.invoker.Expand(ctx, request)
137
	if err != nil {
138
		span.RecordError(err)
139
		span.SetStatus(otelCodes.Error, err.Error())
140
		slog.ErrorContext(ctx, err.Error())
141
		return nil, status.Error(GetStatus(err), err.Error())
142
	}
143
144
	return response, nil
145
}
146
147
// LookupEntity -
148
func (r *PermissionServer) LookupEntity(ctx context.Context, request *v1.PermissionLookupEntityRequest) (*v1.PermissionLookupEntityResponse, error) {
149
	ctx, span := internal.Tracer.Start(ctx, "permissions.lookup-entity")
150
	defer span.End()
151
152
	v := request.Validate()
153
	if v != nil {
154
		return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
155
	}
156
157
	response, err := r.invoker.LookupEntity(ctx, request)
158
	if err != nil {
159
		span.RecordError(err)
160
		span.SetStatus(otelCodes.Error, err.Error())
161
		slog.ErrorContext(ctx, err.Error())
162
		return nil, status.Error(GetStatus(err), err.Error())
163
	}
164
165
	return response, nil
166
}
167
168
// LookupEntityStream -
169
func (r *PermissionServer) LookupEntityStream(request *v1.PermissionLookupEntityRequest, server v1.Permission_LookupEntityStreamServer) error {
170
	ctx, span := internal.Tracer.Start(server.Context(), "permissions.lookup-entity-stream")
171
	defer span.End()
172
173
	v := request.Validate()
174
	if v != nil {
175
		return v
176
	}
177
178
	err := r.invoker.LookupEntityStream(ctx, request, server)
179
	if err != nil {
180
		span.RecordError(err)
181
		span.SetStatus(otelCodes.Error, err.Error())
182
		slog.ErrorContext(ctx, err.Error())
183
		return status.Error(GetStatus(err), err.Error())
184
	}
185
186
	return nil
187
}
188
189
// LookupSubject -
190
func (r *PermissionServer) LookupSubject(ctx context.Context, request *v1.PermissionLookupSubjectRequest) (*v1.PermissionLookupSubjectResponse, error) {
191
	ctx, span := internal.Tracer.Start(ctx, "permissions.lookup-subject")
192
	defer span.End()
193
194
	v := request.Validate()
195
	if v != nil {
196
		return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
197
	}
198
199
	response, err := r.invoker.LookupSubject(ctx, request)
200
	if err != nil {
201
		span.RecordError(err)
202
		span.SetStatus(otelCodes.Error, err.Error())
203
		slog.ErrorContext(ctx, err.Error())
204
		return nil, status.Error(GetStatus(err), err.Error())
205
	}
206
207
	return response, nil
208
}
209
210
// SubjectPermission -
211
func (r *PermissionServer) SubjectPermission(ctx context.Context, request *v1.PermissionSubjectPermissionRequest) (*v1.PermissionSubjectPermissionResponse, error) {
212
	ctx, span := internal.Tracer.Start(ctx, "permissions.subject-permission")
213
	defer span.End()
214
215
	v := request.Validate()
216
	if v != nil {
217
		return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
218
	}
219
220
	response, err := r.invoker.SubjectPermission(ctx, request)
221
	if err != nil {
222
		span.RecordError(err)
223
		span.SetStatus(otelCodes.Error, err.Error())
224
		slog.ErrorContext(ctx, err.Error())
225
		return nil, status.Error(GetStatus(err), err.Error())
226
	}
227
228
	return response, nil
229
}
230