@quenty/permissionprovider 14.43.0 → 14.44.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/package.json +13 -12
- package/src/Client/PermissionServiceClient.lua +5 -1
- package/src/Client/PermissionServiceClient.spec.lua +176 -0
- package/src/Client/Providers/PermissionProviderClient.lua +8 -2
- package/src/Client/Providers/PermissionProviderClient.spec.lua +186 -0
- package/src/Server/PermissionProviderUtils.spec.lua +118 -0
- package/src/Server/PermissionService.lua +6 -5
- package/src/Server/PermissionService.spec.lua +203 -0
- package/src/Server/Providers/BasePermissionProvider.lua +7 -6
- package/src/Server/Providers/BasePermissionProvider.spec.lua +136 -0
- package/src/Server/Providers/CreatorPermissionProvider.lua +6 -2
- package/src/Server/Providers/CreatorPermissionProvider.spec.lua +130 -0
- package/src/Server/Providers/GroupPermissionProvider.lua +17 -12
- package/src/Server/Providers/GroupPermissionProvider.spec.lua +180 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--[[
|
|
3
|
+
Coverage for GroupPermissionProvider using PlayerMock players. Group membership is injected
|
|
4
|
+
via GroupTestUtils.assignGroupInfo (defaulting to non-member, rank 0 — a mock is in no real
|
|
5
|
+
group), intercepted at the GroupService engine calls, so permission outcomes flow through
|
|
6
|
+
GroupUtils' real parsing and the provider's real threshold logic deterministically — no group
|
|
7
|
+
API call and no Studio dependence.
|
|
8
|
+
|
|
9
|
+
@class GroupPermissionProvider.spec.lua
|
|
10
|
+
]]
|
|
11
|
+
|
|
12
|
+
local require = require(script.Parent.loader).load(script)
|
|
13
|
+
|
|
14
|
+
local Workspace = game:GetService("Workspace")
|
|
15
|
+
|
|
16
|
+
local GroupPermissionProvider = require("GroupPermissionProvider")
|
|
17
|
+
local GroupTestUtils = require("GroupTestUtils")
|
|
18
|
+
local Jest = require("Jest")
|
|
19
|
+
local Maid = require("Maid")
|
|
20
|
+
local PermissionLevel = require("PermissionLevel")
|
|
21
|
+
local PermissionProviderUtils = require("PermissionProviderUtils")
|
|
22
|
+
local PlayerMock = require("PlayerMock")
|
|
23
|
+
local PromiseTestUtils = require("PromiseTestUtils")
|
|
24
|
+
|
|
25
|
+
local describe = Jest.Globals.describe
|
|
26
|
+
local expect = Jest.Globals.expect
|
|
27
|
+
local it = Jest.Globals.it
|
|
28
|
+
|
|
29
|
+
local remoteNameCounter = 0
|
|
30
|
+
|
|
31
|
+
local function setup(options: { minAdminRequiredRank: number, minCreatorRequiredRank: number })
|
|
32
|
+
local maid = Maid.new()
|
|
33
|
+
|
|
34
|
+
-- Unique remote function name so providers from separate tests never share the global remote.
|
|
35
|
+
remoteNameCounter += 1
|
|
36
|
+
local provider = maid:Add(GroupPermissionProvider.new(PermissionProviderUtils.createGroupRankConfig({
|
|
37
|
+
groupId = 12345,
|
|
38
|
+
minAdminRequiredRank = options.minAdminRequiredRank,
|
|
39
|
+
minCreatorRequiredRank = options.minCreatorRequiredRank,
|
|
40
|
+
remoteFunctionName = string.format("GroupPermissionProviderSpecRemote%d", remoteNameCounter),
|
|
41
|
+
})))
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
provider = provider,
|
|
45
|
+
fakePlayer = function(userId: number): Player
|
|
46
|
+
local player = maid:Add(PlayerMock.new({ UserId = userId }))
|
|
47
|
+
player.Parent = Workspace
|
|
48
|
+
return player
|
|
49
|
+
end,
|
|
50
|
+
awaitBool = function(promise: any): boolean
|
|
51
|
+
expect(PromiseTestUtils.awaitSettled(promise, 5)).toEqual(true)
|
|
52
|
+
local ok, value = promise:Yield()
|
|
53
|
+
expect(ok).toEqual(true)
|
|
54
|
+
return value
|
|
55
|
+
end,
|
|
56
|
+
destroy = function(_self)
|
|
57
|
+
maid:DoCleaning()
|
|
58
|
+
end,
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe("GroupPermissionProvider.new", function()
|
|
63
|
+
it("should reject a single user config", function()
|
|
64
|
+
expect(function()
|
|
65
|
+
GroupPermissionProvider.new(PermissionProviderUtils.createSingleUserConfig({
|
|
66
|
+
userId = 12345,
|
|
67
|
+
}) :: any)
|
|
68
|
+
end).toThrow("Bad configType")
|
|
69
|
+
end)
|
|
70
|
+
end)
|
|
71
|
+
|
|
72
|
+
describe("GroupPermissionProvider.PromiseIsPermissionLevel", function()
|
|
73
|
+
it("should grant both levels when the rank thresholds are met", function()
|
|
74
|
+
local controller = setup({ minAdminRequiredRank = 0, minCreatorRequiredRank = 0 })
|
|
75
|
+
local player = controller.fakePlayer(111)
|
|
76
|
+
|
|
77
|
+
expect(controller.awaitBool(controller.provider:PromiseIsAdmin(player))).toEqual(true)
|
|
78
|
+
expect(controller.awaitBool(controller.provider:PromiseIsCreator(player))).toEqual(true)
|
|
79
|
+
|
|
80
|
+
controller:destroy()
|
|
81
|
+
end)
|
|
82
|
+
|
|
83
|
+
it("should deny both levels when the rank thresholds are not met", function()
|
|
84
|
+
local controller = setup({ minAdminRequiredRank = 100, minCreatorRequiredRank = 200 })
|
|
85
|
+
local player = controller.fakePlayer(111)
|
|
86
|
+
|
|
87
|
+
expect(controller.awaitBool(controller.provider:PromiseIsAdmin(player))).toEqual(false)
|
|
88
|
+
expect(controller.awaitBool(controller.provider:PromiseIsCreator(player))).toEqual(false)
|
|
89
|
+
|
|
90
|
+
controller:destroy()
|
|
91
|
+
end)
|
|
92
|
+
|
|
93
|
+
it("should grant admin but deny creator for a tiered config", function()
|
|
94
|
+
local controller = setup({ minAdminRequiredRank = 0, minCreatorRequiredRank = 1 })
|
|
95
|
+
local player = controller.fakePlayer(111)
|
|
96
|
+
|
|
97
|
+
expect(controller.awaitBool(controller.provider:PromiseIsAdmin(player))).toEqual(true)
|
|
98
|
+
expect(controller.awaitBool(controller.provider:PromiseIsCreator(player))).toEqual(false)
|
|
99
|
+
|
|
100
|
+
controller:destroy()
|
|
101
|
+
end)
|
|
102
|
+
|
|
103
|
+
it("should grant admin but deny creator from an injected group rank", function()
|
|
104
|
+
local controller = setup({ minAdminRequiredRank = 100, minCreatorRequiredRank = 200 })
|
|
105
|
+
local player = controller.fakePlayer(111)
|
|
106
|
+
GroupTestUtils.assignGroupInfo(player, 12345, { rank = 150, role = "Admin" })
|
|
107
|
+
|
|
108
|
+
expect(controller.awaitBool(controller.provider:PromiseIsAdmin(player))).toEqual(true)
|
|
109
|
+
expect(controller.awaitBool(controller.provider:PromiseIsCreator(player))).toEqual(false)
|
|
110
|
+
|
|
111
|
+
controller:destroy()
|
|
112
|
+
end)
|
|
113
|
+
|
|
114
|
+
it("should grant both levels from an injected group rank meeting both thresholds", function()
|
|
115
|
+
local controller = setup({ minAdminRequiredRank = 100, minCreatorRequiredRank = 200 })
|
|
116
|
+
local player = controller.fakePlayer(111)
|
|
117
|
+
GroupTestUtils.assignGroupInfo(player, 12345, { rank = 255, role = "Owner" })
|
|
118
|
+
|
|
119
|
+
expect(controller.awaitBool(controller.provider:PromiseIsAdmin(player))).toEqual(true)
|
|
120
|
+
expect(controller.awaitBool(controller.provider:PromiseIsCreator(player))).toEqual(true)
|
|
121
|
+
|
|
122
|
+
controller:destroy()
|
|
123
|
+
end)
|
|
124
|
+
|
|
125
|
+
it("should ignore a rank injected for a different group", function()
|
|
126
|
+
local controller = setup({ minAdminRequiredRank = 100, minCreatorRequiredRank = 200 })
|
|
127
|
+
local player = controller.fakePlayer(111)
|
|
128
|
+
GroupTestUtils.assignGroupInfo(player, 99999, { rank = 255, role = "Owner" })
|
|
129
|
+
|
|
130
|
+
expect(controller.awaitBool(controller.provider:PromiseIsAdmin(player))).toEqual(false)
|
|
131
|
+
|
|
132
|
+
controller:destroy()
|
|
133
|
+
end)
|
|
134
|
+
|
|
135
|
+
it("should reject a player outside the game hierarchy", function()
|
|
136
|
+
local controller = setup({ minAdminRequiredRank = 0, minCreatorRequiredRank = 0 })
|
|
137
|
+
local maid = Maid.new()
|
|
138
|
+
local unparented = maid:Add(PlayerMock.new({ UserId = 111 }))
|
|
139
|
+
|
|
140
|
+
expect(function()
|
|
141
|
+
controller.provider:PromiseIsPermissionLevel(unparented, PermissionLevel.CREATOR)
|
|
142
|
+
end).toThrow("Bad player")
|
|
143
|
+
|
|
144
|
+
maid:DoCleaning()
|
|
145
|
+
controller:destroy()
|
|
146
|
+
end)
|
|
147
|
+
|
|
148
|
+
it("should reject a non-player value", function()
|
|
149
|
+
local controller = setup({ minAdminRequiredRank = 0, minCreatorRequiredRank = 0 })
|
|
150
|
+
|
|
151
|
+
expect(function()
|
|
152
|
+
controller.provider:PromiseIsPermissionLevel(nil :: any, PermissionLevel.ADMIN)
|
|
153
|
+
end).toThrow("Bad player")
|
|
154
|
+
|
|
155
|
+
controller:destroy()
|
|
156
|
+
end)
|
|
157
|
+
|
|
158
|
+
it("should reject an invalid permission level", function()
|
|
159
|
+
local controller = setup({ minAdminRequiredRank = 0, minCreatorRequiredRank = 0 })
|
|
160
|
+
local player = controller.fakePlayer(111)
|
|
161
|
+
|
|
162
|
+
expect(function()
|
|
163
|
+
controller.provider:PromiseIsPermissionLevel(player, "not-a-level" :: any)
|
|
164
|
+
end).toThrow()
|
|
165
|
+
|
|
166
|
+
controller:destroy()
|
|
167
|
+
end)
|
|
168
|
+
end)
|
|
169
|
+
|
|
170
|
+
describe("GroupPermissionProvider.Start", function()
|
|
171
|
+
it("should start and clean up without error", function()
|
|
172
|
+
local controller = setup({ minAdminRequiredRank = 100, minCreatorRequiredRank = 200 })
|
|
173
|
+
|
|
174
|
+
expect(function()
|
|
175
|
+
controller.provider:Start()
|
|
176
|
+
end).never.toThrow()
|
|
177
|
+
|
|
178
|
+
controller:destroy()
|
|
179
|
+
end)
|
|
180
|
+
end)
|