-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright 2026 Shota FUJI
//
// This program is free software: you can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
const std = @import("std");
const flatbuffers = @import("flatbuffers");
const v1 = @import("v1");
const schema = v1.Yamori.Auth.V1;
/// * 管理者以外は自分のリソースのみ作成・変更可能
/// * どのユーザでも全てのリソースを閲覧可能
export fn v1_allow_resource_access(buffer_ptr: [*]const u8, buffer_len: u32) bool {
const buffer = buffer_ptr[0..buffer_len];
return v1AllowResourceAccess(buffer) catch return false;
}
fn v1AllowResourceAccess(buffer: []const u8) !bool {
const root = flatbuffers.decodeRoot(schema.AccessRequest, @alignCast(buffer)) catch return false;
if (root.user().is_super_user()) {
return true;
}
const access_type = root.access_type();
if (access_type == .Read) {
return true;
}
return switch (root.resource_type()) {
.User => |u| switch (access_type) {
.Modify => std.mem.eql(u8, u.id(), root.user().id()),
.Read => unreachable,
else => false,
},
.UserAttribute => false,
.UserAttributeDefinition => false,
else => false,
};
}
test "フィールドが欠けている場合はアクセスを拒否する" {
var builder = try flatbuffers.Builder.init(std.testing.allocator);
defer builder.deinit();
try builder.writeRoot(schema.AccessRequest, try builder.writeTable(schema.AccessRequest, .{
.user = try builder.writeTable(schema.User, .{
.id = "foo-bar",
}),
}));
const buffer = try builder.writeAlloc(std.testing.allocator);
defer std.testing.allocator.free(buffer);
try std.testing.expectEqual(false, try v1AllowResourceAccess(buffer));
}
test "管理者はユーザを追加できる" {
var builder = try flatbuffers.Builder.init(std.testing.allocator);
defer builder.deinit();
try builder.writeRoot(schema.AccessRequest, try builder.writeTable(schema.AccessRequest, .{
.user = try builder.writeTable(schema.User, .{
.id = "foo-bar",
.is_super_user = true,
}),
.access_type = .Create,
.resource_type = .{
.User = try builder.writeTable(schema.User, .{
.id = "baz-qux",
.is_super_user = true,
}),
},
}));
const buffer = try builder.writeAlloc(std.testing.allocator);
defer std.testing.allocator.free(buffer);
try std.testing.expectEqual(true, try v1AllowResourceAccess(buffer));
}
test "非管理者は自身の基本情報を変更できる" {
var builder = try flatbuffers.Builder.init(std.testing.allocator);
defer builder.deinit();
try builder.writeRoot(schema.AccessRequest, try builder.writeTable(schema.AccessRequest, .{
.user = try builder.writeTable(schema.User, .{
.id = "foo-bar",
}),
.access_type = .Modify,
.resource_type = .{
.User = try builder.writeTable(schema.User, .{
.id = "foo-bar",
}),
},
}));
const buffer = try builder.writeAlloc(std.testing.allocator);
defer std.testing.allocator.free(buffer);
try std.testing.expectEqual(true, try v1AllowResourceAccess(buffer));
}
test "非管理者は他人の基本情報を変更できない" {
var builder = try flatbuffers.Builder.init(std.testing.allocator);
defer builder.deinit();
try builder.writeRoot(schema.AccessRequest, try builder.writeTable(schema.AccessRequest, .{
.user = try builder.writeTable(schema.User, .{
.id = "foo-bar",
}),
.access_type = .Modify,
.resource_type = .{
.User = try builder.writeTable(schema.User, .{
.id = "baz-qux",
}),
},
}));
const buffer = try builder.writeAlloc(std.testing.allocator);
defer std.testing.allocator.free(buffer);
try std.testing.expectEqual(false, try v1AllowResourceAccess(buffer));
}