Skip to content

Conversation

@S-S-X
Copy link
Member

@S-S-X S-S-X commented Feb 18, 2023

Simple access control lists for channels.

Possible roles are:

  • deny Access to channel is denied.
  • read Can read messages sent to channel.
  • write Can send messages to channel.
  • manager Can manage deny, read and write ACLs for channel.
  • owner Can manage all ACLs, including channel owners.

Primary channel owner (player who created channel) cannot be removed or changed, this is not the same as ACL owner role.
ACLs will not affect primary owner in any way, this primary owner information is checked but not managed by ACL plugin.
Default access role, when ACLs are not used for channel, is write.

Identities and identity providers

Possible built in identities for ACL matching are:

  • Player name. Matches individual players.
  • Privilege prefixed with $, for example $interact. Matches players who has that privilege.
  • Special identity *. Default privilege for channel, used when no better match found.
  • More special identities can be added, for example faction membership or such.

Primary function of identity provider is to translate player name into valid secondary identities.
For example, take in player name and return list of available privileges.
Adding different identities can be done by registering new identity provider, for example see plugin/acl/privileges.lua.

Channel invites

Basic channel invite command /ic has been removed.
Command didn't actually do anything besides playing a sound and sending a message with /jc instructions.

Adding player specific ACL will also send invite message.
Adding privilege based (players with privilege) or default role (everyone) wont send invite messages.

Channel passwords

Password handling have been mostly moved from core to ACL plugin.
Beerchat now asks for password when attempting to join password protected channel, /jc wont accept password at all (however it could still do that but access checks still requires ACL plugin).

Chat commands

/ca <Channel Name> [[-d] <Identity> [Access Role]]
/channel_acl Same as above / alias.
/ic Same as above / alias. Should this be removed while at it❓
/invite_channel Same as above / alias. Should this be removed while at it❓

I had plans to reorder chat command arguments but not going to do it for this PR. Updating chat command can be easily done later if needed.

Examples

Ban single player from channel:
/ca #main Sam deny

Allow players with staff privilege to send messages while everyone else can just read:
/ca #main * read
/ca #main $staff write

It's anarchy server (though even this wont allow overriding primary owner):
/ca #main * owner

Known shortcomings

Ordering of multiple roles isn't currently guaranteed in any way across identity providers other than player name is always first and fallback role is always last.
First explicitly defined role is returned instead of returning highest or lowest permission.
Though currently ordering is known as there's only player name, privilege and fallback.
Left this undefined and undecided for now, behavior could be changed later.

Stats for change set

What Lines added Lines removed
Mod code, including plugins +602 -145
Mod code +66 -141
Plugin code +536 -4
Tests +1011 -24
Total +1613 -169

@S-S-X S-S-X added the enhancement New feature or request label Feb 18, 2023
@S-S-X
Copy link
Member Author

S-S-X commented Feb 21, 2023

ACL Password Outcome
allow allow ✔️
undef allow ✔️
deny allow
allow undef ✔️
undef undef ✔️
deny undef
allow deny
undef deny
deny deny

That is how event handlers work by default. By default access is always granted and must be explicitly denied: if any handler denies access then access is denied completely. If nothing denies access then access is granted.

Explicit grants however are possible, if event handler returns true instead of nil then propagation is stopped and access granted immediately without checking any other rules. This however also requires extra care with event handler registration order and is way harder to manage.

@S-S-X
Copy link
Member Author

S-S-X commented Feb 25, 2023

For privilege and player factions / groups support, one way to implement backend db would be this:

{
	owner = {
		["president"] = true, -- Allow player named `president` to do everything like chat, manage managers, delete channel and so on.
	},
	manager = {
		["$privs"] = true, -- Allow players with `privs` privilege to chat and manage users.
		["sam"] = true -- Allow player named `sam` to chat and manage users.
	},
	user = {
		["@Tree House Clan"] = true, -- Allow `Tree House Clan` faction members to chat.
		["gandalf"] = true -- Allow player named `gandalf` to chat.
	},
	read = {
		["!@Mosters"] = true, -- Allow everyone but `Monsters` faction members to read channel.
	}
}

Empty table would enforce auto propagated checks. Missing table would skip checks for that role and follow normal access resolution through other registered restrictions.

Adding metatables when loading db allows easily checking for higher privs, lookup should already be fast enough for that.

This would be simply exploiting the fact that characters in player names are restricted, easy to check matches without much special handling for different mods implementing player groups.

Could even allow areas mod support to check if player is in named area when receiving messages or trying to chat on channel, see also pandorabox-io/in-game#171

Update 2025:

Identities are handled through separately registered identity providers.
Each identity provider uses unique id (special character) for storage and to determine when to use provider.
This provider id is still mixed with player names but, if needed, it can be detached without rewriting everything.

Identity providers are fairly simple:

  • Main function is to translate player name into available identities like privileges, faction names or anything player can have.
  • Basically with just few lines of code you can for example make channel readable only to players who has certain item in their inventory.
  • Secondary function is to provide better more informative feedback and invite messages, this could be later extended to cover ACL error messages too.

@S-S-X S-S-X force-pushed the channel-acls branch 2 times, most recently from 59e4555 to f0cd733 Compare May 12, 2023 13:40
@S-S-X S-S-X force-pushed the channel-acls branch 3 times, most recently from b7cccde to 53dd3ff Compare May 20, 2023 17:27
@S-S-X S-S-X changed the title ACL starting point Channel ACLs May 21, 2023
S-S-X added a commit that referenced this pull request May 21, 2023
beerchat.join_channel rework backwards compatible way

Update chatcommands

Update ACLs / actual permission checks

Add beerchat.capture_message

Password query / single shot override everything

Privilege based ACL roles + other updates

Remove password from /jc command

Cleanup /cc

Remove ACLs with -d switch

Rename channel_name
@S-S-X S-S-X marked this pull request as ready for review May 21, 2023 20:00
@S-S-X
Copy link
Member Author

S-S-X commented May 21, 2023

This is going to need some play testing on actual server.

Things to test:

  • Basic chatting / channel switching / joining / creating channels.
  • Channels with password, is there any issues with existing protected channels or password functionality.
  • Do player based ACLs work?
  • Do privilege based ACLs work?
  • Do owner and manager roles work correctly?
  • ACLs should not affect channels where there's no ACLs.

It does also change basic message formatting parameters channel_name -> channel and channel_password -> password so custom format strings might break.
Currently however only main channel format string is actually configurable and even if formatting breaks it'll be easy to fix (in configuration) and chat should work just fine.

Stats:
spec/** 5 files changed, 249 insertions(+), 16 deletions(-)
!spec/** 12 files changed, 342 insertions(+), 145 deletions(-)
plugin/acl** 2 files changed, 270 insertions(+)

@S-S-X S-S-X marked this pull request as draft January 2, 2024 15:44
S-S-X added a commit that referenced this pull request Jan 3, 2024
beerchat.join_channel rework backwards compatible way

Update chatcommands

Update ACLs / actual permission checks

Add beerchat.capture_message

Password query / single shot override everything

Privilege based ACL roles + other updates

Remove password from /jc command

Cleanup /cc

Remove ACLs with -d switch

Rename channel_name
S-S-X added a commit that referenced this pull request Jan 7, 2024
beerchat.join_channel rework backwards compatible way

Update chatcommands

Update ACLs / actual permission checks

Add beerchat.capture_message

Password query / single shot override everything

Privilege based ACL roles + other updates

Remove password from /jc command

Cleanup /cc

Remove ACLs with -d switch

Rename channel_name
@S-S-X
Copy link
Member Author

S-S-X commented Jan 17, 2024

* [ ] Reorder chat command args #107 (comment)

Edit: not going to do this. Chat command can be updated later if needed.

@S-S-X
Copy link
Member Author

S-S-X commented Jun 14, 2025

Took only bit over two years to check few boxes 🐌
But I think I'll finish this one soon, also coverage for automated ACL tests is pretty good already.

S-S-X added a commit that referenced this pull request Jun 15, 2025
beerchat.join_channel rework backwards compatible way

Update chatcommands

Update ACLs / actual permission checks

Add beerchat.capture_message / password query / single shot override everything

Privilege based ACL roles + other updates

Remove password from /jc command

Cleanup /cc command

Remove ACLs with -d switch

Rename channel_name

Rework password protected join

Refactor privilege roles -> generic identity providers

Fix some bugs and corner cases
@S-S-X
Copy link
Member Author

S-S-X commented Jun 15, 2025

Rebased to master. Kind of finished I think but one thing is missing: actually saving changes to persistent storage.

Storage is available, just acls:write_storage() isn't called anywhere.
Could be called every time something gets changed, could call every nth minutes or could call on shutdown.

S-S-X added a commit that referenced this pull request Jun 16, 2025
beerchat.join_channel rework backwards compatible way

Update chatcommands

Update ACLs / actual permission checks

Add beerchat.capture_message / password query / single shot override everything

Privilege based ACL roles + other updates

Remove password from /jc command

Cleanup /cc command

Remove ACLs with -d switch

Rename channel_name

Rework password protected join

Refactor privilege roles -> generic identity providers

Fix some bugs and corner cases

Better UX for chat commands
@S-S-X
Copy link
Member Author

S-S-X commented Jun 16, 2025

Fixed UX issues and reduced risks of mental health issues after using chat commands.
Also added even more tests for mentioned UX issues, cache behavior and few corner cases.

Also added calls to acls:write_storage() which now:

  1. Triggers pending write / restarts 60 second timer.
    a. Returns to 1. if acls:write_storage() is called during these 60 seconds.
    b. Serializes/writes data to mod storage if not interrupted by another acls:write_storage() call.

@S-S-X S-S-X marked this pull request as ready for review June 16, 2025 19:04
Test password query

ACL/acls basic tests

Tests for /mc

Test ACL removal

Remove print from channel ban test

Test common ACL combinations and chat commands

Test chat feedback for player deny
beerchat.join_channel rework backwards compatible way

Update chatcommands

Update ACLs / actual permission checks

Add beerchat.capture_message / password query / single shot override everything

Privilege based ACL roles + other updates

Remove password from /jc command

Cleanup /cc command

Remove ACLs with -d switch

Rename channel_name

Rework password protected join

Refactor privilege roles -> generic identity providers

Fix some bugs and corner cases

Better UX for chat commands
@S-S-X
Copy link
Member Author

S-S-X commented Jun 22, 2025

Cleaned up commits, singleplayer setting for tests also isn't really needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request needs testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants