Skip to content

Commit e4e40c4

Browse files
committed
Reload permissions from group on setrobloxgroup.
1 parent a2a1b40 commit e4e40c4

File tree

3 files changed

+128
-92
lines changed

3 files changed

+128
-92
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,14 @@ Managing roles/permission levels is done via the `/setadmin`, `/setscribe`, `/se
4343

4444
* If the experience is owned by a Roblox group, you cannot manually set the `robloxGroupId` as it is set automatically to the owning group.
4545
* You can use `/setrobloxgroup N` to set your Roblox group (as usual, find the ID by navigating to your group on the Roblox homepage and extracting it from the URL).
46+
47+
## Generating a Release
48+
49+
The `metaadmin.rbxmx` file is generated like this
50+
```bash
51+
rojo build --output "build.rbxlx"
52+
remodel run admin_packager.lua
53+
```
54+
55+
The first command builds a place file according to `default.project.json`.
56+
The second command uses [remodel](https://github.com/rojo-rbx/remodel) to extract the `ChatModules` folder as an `rbxmx` file.

admin_packager.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
local args = {...}
2+
local input = args[1] or "build.rbxlx"
3+
local output = args[2] or "metaadmin.rbxmx"
4+
5+
local game = remodel.readPlaceFile(input)
6+
remodel.writeModelFile(game.Chat.ChatModules, output)

src/AdminCommands.lua

Lines changed: 111 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,6 @@
66
local Settings = {
77
Prefix = "/", -- Symbol that lets the script know the message is a command
88
DebugMode = false, -- Set to true when making new commands so it's easier to identify errors
9-
Admins = {
10-
-- Dictionary of user ids and the rank the player with that user id will be receiving (rank must be a number)
11-
-- These entries overwrite whatever is saved in the permissions DataStore everytime the server is started (see game:BindToClose)
12-
[tostring(game.CreatorId)] = 255;
13-
-- Hard code more roles here, which will overwrite any changes when the server restarts
14-
-- e.g. To make player with user ID 1234 a permanent admin, add this (make sure the ID is a string)
15-
-- ["1234"] = 254;
16-
},
179
DefaultPerm = 0,
1810
ScribePerm = 50, -- Can be overwritten by Roblox group settings
1911
AdminPerm = 254, -- Can be overwritten by Roblox group settings
@@ -156,6 +148,72 @@ function SetDefault(userId)
156148
SetPermLevel(userId, Settings.DefaultPerm)
157149
end
158150

151+
local function LoadPlayerPermissionsFromGroup(player, groupId)
152+
if not groupId or not player or groupId == 0 then return end
153+
154+
local success, groups = pcall(function()
155+
return GroupService:GetGroupsAsync(player.UserId)
156+
end)
157+
if success then
158+
for _, group in ipairs(groups) do
159+
if group["Id"] == groupId then
160+
-- The player is a member of the group that owns this experience
161+
-- and so we just use their group rank here
162+
local playerRank = group["Rank"]
163+
SetPermLevel(player.UserId, playerRank)
164+
print("[Admin] Found player ".. player.Name.." in group, assigning rank "..tostring(playerRank))
165+
end
166+
end
167+
else
168+
print("[Admin] Failed to query player's groups")
169+
end
170+
end
171+
172+
local function LoadPermissionsFromGroup(groupId)
173+
if not robloxGroupId or robloxGroupId == 0 then return end
174+
175+
for _, player in pairs(PlayersService:GetPlayers()) do
176+
LoadPlayerPermissionsFromGroup(player, robloxGroupId)
177+
end
178+
end
179+
180+
local function LoadSettingsFromGroup(groupId)
181+
if groupId == 0 then
182+
Settings.ScribePerm = 50
183+
Settings.AdminPerm = 254
184+
return
185+
end
186+
187+
local success, response = pcall(function()
188+
return GroupService:GetGroupInfoAsync(groupId)
189+
end)
190+
if success then
191+
if response and response.Roles then
192+
for _, role in ipairs(response.Roles) do
193+
if role.Name == "Scribe" then
194+
-- Overwrite settings for scribes
195+
Settings.ScribePerm = role.Rank
196+
end
197+
198+
if role.Name == "Admin" then
199+
-- Overwrite settings for admins
200+
Settings.AdminPerm = role.Rank
201+
end
202+
end
203+
end
204+
else
205+
print("[Admin] Failed to get group info")
206+
end
207+
end
208+
209+
local function isPrivateServer()
210+
if game.PrivateServerId ~= "" and game.PrivateServerOwnerId ~= 0 then
211+
return true
212+
else
213+
return false
214+
end
215+
end
216+
159217
game:BindToClose(function()
160218
local countAdmin = 0
161219
local countGuest = 0
@@ -207,24 +265,9 @@ PlayersService.PlayerAdded:Connect(function(player)
207265
return
208266
end
209267

210-
-- On a per-user basis we look for settings based on the Roblox group
211-
if robloxGroupId ~= 0 then
212-
local success, groups = pcall(function()
213-
return GroupService:GetGroupsAsync(player.UserId)
214-
end)
215-
if success then
216-
for _, group in ipairs(groups) do
217-
if group["Id"] == robloxGroupId then
218-
-- The player is a member of the group that owns this experience
219-
-- and so we just use their group rank here
220-
local playerRank = group["Rank"]
221-
SetPermLevel(player.UserId, playerRank)
222-
print("[Admin] Found player ".. player.Name.." in group, assigning rank "..tostring(playerRank))
223-
end
224-
end
225-
else
226-
print("[Admin] Failed to query player's groups")
227-
end
268+
-- If a group is set, load permissions for this user
269+
if robloxGroupId ~=0 then
270+
LoadPlayerPermissionsFromGroup(player, robloxGroupId)
228271
end
229272

230273
if Settings.DebugMode then
@@ -463,14 +506,6 @@ function BindCommands()
463506
return false
464507
end
465508

466-
if game.CreatorType == Enum.CreatorType.Group then
467-
SendMessageToClient({
468-
Text = "Cannot manually set Roblox group for an experience owned by a group.";
469-
ChatColor = Color3.new(1,0,0)
470-
}, speaker.Name)
471-
return false
472-
end
473-
474509
local groupId = tonumber(args[1])
475510

476511
if groupId == nil then
@@ -484,6 +519,12 @@ function BindCommands()
484519
-- groupId checks out, set the Roblox group and update settings
485520
robloxGroupId = groupId
486521
LoadSettingsFromGroup(groupId)
522+
LoadPermissionsFromGroup(groupId)
523+
524+
SendMessageToClient({
525+
Text = "Roblox group set to "..groupId..".";
526+
ChatColor = Color3.new(0, 1, 0)
527+
}, speaker.Name)
487528
end
488529
})
489530

@@ -582,7 +623,7 @@ function BindCommands()
582623

583624
BindCommand({
584625
name = "boards",
585-
perm = Settings.ScribePerm,
626+
perm = Settings.AdminPerm,
586627
usage = Settings.Prefix.."boards {on|off}",
587628
brief = "Turn the whiteboards on/off for guests (anyone below scribe level)",
588629
help = "'"..Settings.Prefix.."boards off' deactivates drawing on whiteboards for guests, and anyone with permission level below 'scribe'.\n'"..Settings.Prefix.."boards on' allows anyone to draw on whiteboards",
@@ -632,13 +673,6 @@ function BindCommands()
632673
local userId = GetUserId(name)
633674

634675
if userId then
635-
if Settings.Admins[userId] then
636-
SendMessageToClient({
637-
Text = "This player's permission level is hardcoded to the value "..tostring(Settings.Admins[userId])..". This change will be overwritten when the server restarts.";
638-
ChatColor = Color3.new(1, 0, 0)
639-
}, speaker.Name)
640-
end
641-
642676
SetPermLevel(userId, level)
643677
UpdatePerms(userId)
644678

@@ -710,13 +744,6 @@ function BindCommands()
710744
end
711745

712746
if userId then
713-
if Settings.Admins[userId] then
714-
SendMessageToClient({
715-
Text = "This player's permission level is hardcoded to the value "..Settings.Admins[userId]..". This change will be overwritten when the server restarts.";
716-
ChatColor = Color3.new(1, 0, 0)
717-
}, speaker.Name)
718-
end
719-
720747
SetPermLevel(userId, level)
721748
UpdatePerms(userId)
722749

@@ -836,58 +863,50 @@ local function CreateRemotes()
836863
end
837864
end
838865

839-
local function LoadSettingsFromGroup(groupId)
840-
if groupId == 0 then
841-
Settings.ScribePerm = 50
842-
Settings.AdminPerm = 254
843-
return
844-
end
845-
846-
local success, response = pcall(function()
847-
return GroupService:GetGroupInfoAsync(groupId)
848-
end)
849-
if success then
850-
if response and response.Roles then
851-
for _, role in ipairs(response.Roles) do
852-
if role.Name == "Scribe" then
853-
-- Overwrite settings for scribes
854-
Settings.ScribePerm = role.Rank
855-
end
856-
857-
if role.Name == "Admin" then
858-
-- Overwrite settings for admins
859-
Settings.AdminPerm = role.Rank
860-
end
861-
end
862-
end
863-
else
864-
print("[Admin] Failed to get group info")
865-
end
866-
end
867-
868866
-- Binds all commands at once
869867
function Run(ChatService)
870-
-- If the game is created by a group, set this as the robloxGroupId
871-
if game.CreatorType == Enum.CreatorType.Group then
872-
robloxGroupId = game.CreatorId
868+
-- The CREATOR of an experience is one who published it to Roblox. This can be an individual
869+
-- user or a group. The OWNER of an experience is the creator in the case of public servers,
870+
-- but for private servers it is the person who made the private server.
871+
--
872+
-- In the case of private servers we do not give the creator (or those in the group, if the
873+
-- creator is a group) special permissions in the server, as the owner of the private server
874+
-- does not expect this and may not be able to know what permissions have been set in that group.
875+
876+
-- For a private server, the robloxGroupId is 0 by default (ununsed) and may be
877+
-- set by the owner to whatever they like
878+
879+
-- For a public server, the robloxGroupId is 0 by default (unused), is automatically
880+
-- set to the group if the server is created by a group, and may be set by admins
881+
-- to whatever they like
882+
883+
-- Note that by the time this runs, permissions, scribeOnlyMode and robloxGroupId
884+
-- have been read from the DataStore, so anything we do not now is overwriting
885+
-- those stored settings (and will be written on server shutdown to the DataStore)
886+
887+
-- Give admin rights to owners of private servers and the creator of
888+
-- public servers if they are a user
889+
if isPrivateServer() then
890+
print("[Admin] Giving private server owner "..tostring(game.PrivateServerOwnerId).." admin")
891+
SetPermLevel(game.PrivateServerOwnerId, 255)
892+
elseif game.CreatorType == Enum.CreatorType.User then
893+
print("[Admin] Giving game creator "..tostring(game.CreatorId).." admin")
894+
SetPermLevel(game.CreatorId, 255)
895+
end
896+
897+
if not isPrivateServer() and robloxGroupId == 0 then
898+
-- If the game is created by a group, set this as the robloxGroupId
899+
if game.CreatorType == Enum.CreatorType.Group then
900+
robloxGroupId = game.CreatorId
901+
end
873902
end
874903

875904
-- Look for Roblox group settings on Scribe and Admin rank cutoffs
876905
if robloxGroupId ~= 0 then
906+
print("[Admin] Loading settings from group "..tostring(robloxGroupId))
877907
LoadSettingsFromGroup(robloxGroupId)
878908
end
879909

880-
-- Give admin rights to owners of private servers
881-
if game.PrivateServerId ~= "" and game.PrivateServerOwnerId ~= 0 then
882-
Settings.Admins[tostring(game.PrivateServerOwnerId)] = Settings.AdminPerm
883-
end
884-
885-
-- (Potentially) overwrite the permissions loaded from the DataStore
886-
-- with the settings in Settings.Admins
887-
for userIdStr, level in pairs(Settings.Admins) do
888-
SetPermLevel(userIdStr, level)
889-
end
890-
891910
-- Other code interacts with the permission system via remote functions and events
892911
CreateRemotes()
893912

0 commit comments

Comments
 (0)