Sponge "Layered" Permissions API Proposal

I love that quote. Though we are basing this whole thing off forge which is basically the opposite of vanilla :stuck_out_tongue:

Indeed. They planned to attempt to keep it as vanilla as possible just like Bukkit. Tell the truth Permissions stuff is something that is really necessary. The storage end of it though might not be. It really depends.

This sounds good in theoryā€¦

However Iā€™m not sure itā€™s the greatest idea ever.

One thing Iā€™m certain wouldnā€™t work well is out-of-the-box chat formatting options that allow for group metadata like prefixes/titles.

This would mean people have no real options because the only option is what comes ported with sponge which would mean every sponge server would have very similar chat formatting. Sponge shouldnā€™t touch the chat formatting at all; just keep it completely vanilla. Plugins need to handle chat formatting.

As for permissions, having built-in groups and things doesnā€™t sound like my cup of tea, either.
Seeing as sponge is the hopeful successor to bukkit Iā€™d like to see it just be something similar to bukkitā€¦ A very basic way of defining which permissions non-OP players can use, and which OP-players can use. Nothing more, nothing lessā€¦ just a basic default setup that permissions plugins can build on top of.

Not to mention permission aliases like bukkitā€™s permissions.yml file, that could be very useful. (I know it was to me, I can easily define all of my donor perks in one simple and easy permission node that I can just apply to people on the go, instead of adding a whole sub-group to the user.)

I know that a lot of server owners would like to see built-in features to sponge as having things built-in to the server.jar could potentially speed up a lot of processes. However, having things built-in to the server .jar will eventually lead to the server .jar file being bloated, and suddenly the latest version of sponge is over 500 MB in size. Thatā€™s not what I want, and Iā€™m sure thatā€™s not what the devs want, either.

One solution I could offer to this would to be to provide some kind of API for inserting your plugins into the server.jar somehow? I donā€™t really know too much about coding so Iā€™m kind of talking out my ass here, but I think itā€™d be cool if there were some incentive to allow for plugin developers to insert their code into the server .jar so as to allow for more of these built-in features people keep begging for.

In fact, maybe sponge could have a main directory for downloads, where you can download the ā€œā€œvanillaā€ā€ version of sponge with no extraneous built-in stuff, and then offer other directories in which trusted plugin devs could submit packaged plugins or modified versions of the sponge.jar that make things easier on server admins.

Excuse me for rambling, I just really want to help brainstorm ideas : P

1 Like

Thatā€™s because one of the ā€œpopularā€ permissions based plugins was just a refactor of Permissions. A lot of the ones that came after included the same features simply because that is what users were use to and what they had come to expect.

Honestly, I donā€™t feel that any permission system beyond OP/Non-OP belong in Sponge. Sponge should try to stay as neutral as possible in regards to what the API exposes and provides. Something like a permission system not only isnā€™t default in Minecraft, it also isnā€™t needed by a lot of servers and just adds an extra layer of difficulty in setup.

The thing is that essentially every plugin wants some way to know ā€œis the user allowed to perform action X?ā€, for which ā€œis the user op?ā€ is a reasonable default (and what Bukkit did) for servers with no external permission handling, but without such a somehow-pluggable call in the core API, things are just a huge mess of plugins that are only usable by ops, arenā€™t compatible with your choice of permission system, conflicting standards, and the like.

2 Likes

I disagree with you @gratimax

Not all servers need the 6 points you listed.
The infrastructure looks similar, but the implementation of the permission plugin is different.
It is good if the user can choice from plugins. If one plugin is perfect then nobody would start a new plugin :wink:
In my opinon the Permission API need three things (similar to @SpaceManiac)

Specification of a Permission API

  1. Has user X permission Y
  2. Give user X permission Y
  3. Remove Permission Y from user X

Optional - Syntax Sugar

  1. List all permissons for each plugin
  2. Give a description for each perm

Not part of the API

  1. List users that have permission X
  2. Groups
3 Likes

Fantastic idea !

My thought is have services that are far more integrated that Bukkit.

Have these services follow a common API, like Vault. This API doesnā€™t have to cover everything, just enough to satisfy the most common needs of the server and developers. This API is integrated into the server, unlike Vault, making it easy to develop with.

Provide a default implementation, that does what it needs to and not much more. This could just be the user-level permissions, or maybe even groups. Let other plugins override this default, setting themselves as the permission manager for the server. The Permissions API could then be cast to that plugin, to access the individual features that any particular plugin gives. It would give a universal system thatā€™s more robust, but also allow advanced use cases.

Plugins that implement the API could do whatever they want: World permissions, chat formatting, whatever they want. Theyā€™d just be required to implement the core features in whatever way they wish, and provide access to the more advanced stuff for those who need it through the casting of this API.

2 Likes

The only useful (again syntax sugar, not needed) from my point of view is,
that ā€œdefault groupsā€ exists (guest, normal, trusted, mod, admin) and plugins sort their permission nodes
automatically into this groups.

Problems:

  1. What are useful default groups?
  2. Why did we need that in the API, it is server config stuff ā€¦

IRC discussion:

09:07] <IDragonfire> btw. what did you thing about that: http://forums.spongepowered.org/t/sponge-layered-permissions-api-proposal/2309?u=idragonfire
[09:07] <jacklin213> i just did @space and smacked tab
[09:07] *** Riking changed nick to Riking|away
[09:08] <jacklin213> tis a bit overkill
[09:09] <IDragonfire> i think the "sponge should have X" and "keep it simple" thread is atm not enough ^^
[09:11] <+zml> sponge is going to start with a simple permissions API that is just interfaces that can be implemented by permissions plugins, though it may be expanded if that is necessary to make stuff work well.
[09:13] *** Cervator quit (Quit: Cervator)
[09:14] <IDragonfire> zml, maybe we need some public specifications ... http://forums.spongepowered.org/t/sponge-layered-permissions-api-proposal/2309/12?u=idragonfire
[09:14] *** jimmikaelkael ([email protected]) joined
[09:15] <jimmikaelkael> hi everyone
[09:15] <jacklin213> hi
[09:15] *** CloakedAlien quit (Remote host closed the connection)
[09:15] <+zml> that line I said is the specification as it exists now :)
[09:16] <+zml> also probably going to have groups and getting all users/groups/whatever with a permission.
[09:17] <+zml> and plugins won't be expected to define permissions -- unless there's a way for default permissions to be specified
[09:18] <+SpaceManiac> not a fan of groups in the API, but a lot of other people seem to be, so ehh
[09:18] <+zml> groups are in the api because lots of people want groups
[09:18] <IDragonfire> why groups should be part of the api?
[09:19] <IDragonfire> lots of people want vault in the api  and X and Y
[09:19] <+zml> I'm at the moment thinking of some sort of abstract permission-subject interface that can be applied to group/player/irc-bot-user/whatever
[09:20] <+zml> IDragonfire: and the API could have something similar to Vault interfaces -- they're super lightweight
[09:20] <+zml> remember that the point of the API is to be useful to plugin developers
[09:20] * waterpicker lands ontop of IDragonfire as a dragon hatchling. He proceeds to rawr.
[09:21] <waterpicker> Hey zml
[09:21] <+zml> hey waterpicker
[09:21] <waterpicker> What you guys talking about?
[09:21] <IDragonfire> http://forums.spongepowered.org/t/sponge-layered-permissions-api-proposal/2309/12?u=idragonfire
[09:21] <+zml> permissions api
[09:22] <+zml> usual arguments pretty much
[09:22] <waterpicker> Ah how is the dicussion going?
[09:22] <IDragonfire> procs and cons, somebody must decide
[09:22] <+zml> I'll write out an initial set of interfaces this weekend in a branch, we can work from there.
[09:23] <IDragonfire> the question is .. if you give user groups ... what will the dev use it for?
[09:23] <Paril> built-in OP group I guess
[09:23] <Paril> a default group for everybody and OP group
[09:23] <+zml> rank ladder type things
[09:24] <Paril> oh, -other- devs? ranks and groups are widely used
[09:24] <Paril> thought he meant within the bounds of Sponge's default implementation
[09:24] <IDragonfire> yes
[09:24] <IDragonfire> that lead to a design problem
[09:24] <+zml> yeah, 2 groups --op and notop
[09:25] <+SpaceManiac> I don't really feel like those are groups wrt how the term is normally used
[09:25] <IDragonfire> if a plugin want a custom "op" group,
[09:25] <IDragonfire> then it should give the user myplugin.groups.myopgroup
[09:25] <+zml> IDragonfire: wait until some code exists then comment
[09:25] <IDragonfire> at runtime the plugin should give the "myopgroup perm" for each user
[09:26] <+zml> nononononono lets not have a ton of plugins storing permissions in 4999999 diferent places
[09:26] <Paril> there's another way that groups could be bypassed entirely, and that's if there could be "pseudo-permission nodes" which essentially act as groups
[09:26] <Paril> and these nodes can add more pseudo-perm nodes, which would effectively recreate inheritence
[09:26] *** Goldman60-Y510P ([email protected]) joined
[09:27] <IDragonfire> Paril, that was the thing i try to descirbe
[09:27] <+zml> yeah, that's a common thing. The issue is that's a bit more difficult to implement rank ladders with
[09:27] <Paril> not entirely, as long as you can give a numerical value to the pseudo-node
[09:27] <+zml> and the perm format for that would be group.<groupname>
[09:27] <+SpaceManiac> "rank ladders" aren't a core concept to permissions
[09:27] <+zml> so options too
[09:27] <Paril> yeah was gonna say
[09:27] <IDragonfire> zml, you try to add feature x to the apu
[09:27] <IDragonfire> *api
[09:27] <+zml> SpaceManiac: they're what people want groups for
[09:27] <Paril> groups having a "rank" isn't something that default would need
[09:27] <Paril> not really
[09:28] <Paril> certain types of servers do but I wouldn't say the majority use ranking
[09:28] <Paril> in a way that requires promote/demote sort of behavior
[09:28] <+SpaceManiac> zml: groups I can kind of concede on, but 0..N orderings of groups to create some linear path is def. not a core concept
[09:28] <IDragonfire> zml, groups must be handled be the creator, otherwise we need "default groups" in sponge
[09:28] <+SpaceManiac> neither are "options" - that's metadata, not permissions
[09:28] <Paril> there could be default groups in Sponge, IDragonfire
[09:28] <+zml> SpaceManiac: options are permissions with a non-boolean value -- they should have similar API
[09:28] <Paril> non-op and op are concepts that exist in Minecraft that can be faked through permissions
[09:29] <+SpaceManiac> somehow that argument has never convinced me
[09:29] *** Goldman60 quit (Ping timeout: 206 seconds)
[09:29] <Paril> I've always thought of permissions as being a yes or no situation
[09:29] <IDragonfire> from my view a normal plugin check against a permission x for function y ... the only "cool thing" is that a plugin can automatcilly sort the permissions into groups like normal, mod, op ...
[09:29] <+SpaceManiac> guess I'll wait and see, I'm out for the night
[09:30] <+zml> think of something like prefix -- it has inheritance, can be specified in a specific context, just like a permissions node except it has a string value
[09:30] <Paril> this is true, but like SpaceManiac said that's metadata, not a permission
[09:30] <Paril> unless you look at it as "I give this group permission to have a prefix of x"
[09:30] <Paril> but that just sounds weird
[09:30] <IDragonfire> keep it simple: http://forums.spongepowered.org/t/keep-it-simple-spongeapi-application-interface-utils/2307
[09:31] <+zml> think of permissions as a specialization of metadata and it's less weird rather than the other way around
[09:31] <Paril> permissions should be yes or no, that seems like it can be optimized a bit better
[09:31] <Paril> exactly how metadata like prefix would be applied to groups i dunno
[09:31] <Paril> guess it depends how it would be structured
[09:31] <+zml> like it works with something like PEX
[09:32] <Paril> in PEX it's separate to the "permissions" array
[09:32] <Paril> it's metadata, not a permission on its own
[09:32] <+zml> it's implemented the same... (saying this as the dev of PEX)
[09:33] <Paril> implementation isn't what I'm talking about, moreso the structure
[09:33] <+zml> api is also basically the same. nobody cares about file formats at this point
[09:33] <Paril> I don't remember using hasPermission for prefix
[09:34] <Paril> was there not a specific getPrefix function?
[09:34] <+zml> ...
[09:34] <+zml> there was, but that's been replaced in favor of getOption("prefix")
[09:34] <Paril> okay, so it's under options and not permission
[09:34] <Paril> so they are two separate concepts there
[09:35] <+zml> this is going in circles
[09:35] <Paril> I don't get what your argument is, you want metadata to be a permission but also like PEX where it is an option
[09:35] <+zml> you refuse to see how the two highest-level API methods are basically the same at lower levels.
[09:35] <+zml> metadata is options
[09:35] <Paril> right
[09:36] <Paril> and no, I don't see how they are the same at the lowest levels; of course it depends how it's implemented, that's a given, but if permissions array is kept strictly boolean it should be easier to optimize per user/group
[09:36] <Paril> I think they should be separate at both levels, but that's just me
[09:36] <Paril> I don't know. Interested to see what the core devs have in mind for it, if they have thought about it
[09:37] <+zml> how about no more permissions discussions until code exists? :)
[09:37] <IDragonfire> zml, only because the implementation can be the same (or perm can use the metasystem) the api must not be the same  !
[09:37] <+zml> how about no more permissions discussions until code exists? :)
[09:38] *** Sleaker quit (Ping timeout: 201 seconds)
[09:38] <IDragonfire> implementation code or interfaces?
[09:38] <+zml> interface
[09:38] <Paril> I guess my main point is that just because it may make sense to merge them because booleans can indeed be lumped into an object that they shouldn't be, because the array of allowed permissions can be optimized differently than a simple key/value pair can be
[09:38] <+zml> implementation is probably going to be a permissions plugin.
[09:38] <IDragonfire> post it in the forum ;)
[09:39] <+zml> uh fuck no, this is going into a branch on github

or:
no groups into api ā€¦ instead it exists a external site (+plugin, e.g. groupperm) where plugin authors can add/upload their plugins ā€¦ the side check the code for the permission nodes and the author can specify default groups ā€¦ the groupperm plugin fetch the data from the site ā€¦


Statement from @sk89q:

[10:10] <sk89q> for perms
[10:11] <sk89q> we can have very basic calls (hasPermission() ...)
[10:11] <sk89q> more advanced stuff can be service stuff
[10:11] <sk89q> once again, not top level api
[10:11] <sk89q> just crap we haev around for utility
[10:11] <sk89q> in some of other stuff I write, everything is a service lel
[10:11] <sk89q> even config
[10:11] <+zml> well the basic calls would go to the service eventually, since that can already handle plugins providing an implementation
[10:11] <luacs1998> "IMPLEMENTATION DETAILS" - lex
[10:11] <sk89q> no that's not implementation details
[10:11] <sk89q> that's api details
[10:12] <sk89q> yeah we can do service for perms too
[10:12] <sk89q> however
[10:12] <sk89q> the question is if we want hasPerm() on players, etc.
[10:12] <luacs1998> well
[10:12] <sk89q> on another note
[10:12] <+zml> I think it would be useful to have + make things simpler
[10:12] <sk89q> the nominal way in Java
[10:12] <sk89q> is not the way we are doing it
[10:12] <sk89q> with JAAS you
[10:12] <sk89q> get a Subject from a LoginModule
[10:12] <sk89q> and you check perm on Subject
[10:13] <sk89q> here we basically compile login + check into one call
[10:13] <sk89q> with the Subject you do have the advantage is that you decouple context from the point of permission check
[10:13] <sk89q> otherwise
[10:13] <sk89q> hasPerm(perm, context)
[10:13] <sk89q> though arguably you could pass around a context, but contexts won't be as rich as a custom Subject
[10:14] <sk89q> I used that https://github.com/sk89q/Eduardo/blob/master/src/main/java/com/sk89q/eduardo/auth/AuthService.java
[10:14] <sk89q> the plus is later
[10:14] <sk89q> I can maybe
[10:15] <sk89q> Subject login(totally something different)

Instead of trying to shove everything into the API just have ā€œofficialā€ plugins that the main devs develop, they should be open source.

If other developers want to improve the functionality, then they can fork it or extend it like an API.

It would at least reduce this issue: http://xkcd.com/927/

2 Likes

ā€œList all permissons for each pluginā€

This should be a MUST HAVE for any permission plugin/api/whatnot.

My opinion is that Sponge infrastructure should not permit an end-run around permissions. How that is accomplished I am not sure.

I though somebody would asks it earlier ā€¦

  1. There is no ā€œPermissionā€-Node register system, plugin ask for permission at runtime
  2. The permission Plugin has a list of all ā€œPermissionā€-Nodes where one users has the node
  3. Why a plugin want a list of all permissions?

The only thing that was always missing are offline user permissions. And there is some stuff that should be optional (but specified by the API, so that there is a standard plugin makers can implement).

Must-have: Permission Check

The essential method of a permission API is

permPlugin.hasPermission(UUID playerId, String permission)

I think it should work for online and offline players!

Must-have: permissions.yml##

And also important, groups can be handled with custom parent permissions (like the permissions.yml in Bukkit). I think many admins didnā€™t know how it worked.
Thatā€™s a must-have for sponge!

"permissions": {
    "myperms.basic": {
        "chatplugin.usecolors": true,
        "protectionplugin.build": true
    },
    "mygroups.user": {
        "myperms.basic": true,
        #give users User tag
        "chatplugin.tag.User": true
    },
    "mygroups.admin": {
        "myperms.basic": true,
        #give admins Boss tag
        "chatplugin.tag.Boss": true
        "worldedit.*": true,
        "mailplugin.sendtoall": true,
        "adminplugin.ban": true,
        "adminplugin.kick": true
    },
}

So when you give a player mygroups.admin, he gets all permissions listed under myperms.basic (just like users) and the additional onesā€¦

Optional: Permission Management##

There could be an optional interface for permission management:

permPlugin.setPermission(UUID playerId, String permission, boolean value, PermissionContext ... context)
...

Context could be a WorldContext object to restrict the permission to one world, or TimeContext to limit it to a certain in-game time, or a custom context object (plots, regions, whatever).

And a getter with context support

permPlugin.hasPermissionByContext(UUID playerId, String permission, PermissionContext ... context)
...

Optional: Permission/Player Lists##

There could also be an optional interface for player listing:

//gets all online and offline players who have or have not the permission in the context they are in right now
List playerList = permPlugin.getPlayersByPermission(String permission, boolean value)
...
//gets all online and offline players who have or have not the permission in the specified context
List playerList = permPlugin.getPlayersByPermissionAndContext(String permission, boolean value, PermissionContext ... context)
...

That means to get a list of online and offline players who can build in a world, you can just specify a WorldContext.
And permission lists:

//gets all online and offline players who have or have not the permission in the specified context
List permissionList = permPlugin.getPermissionsByContext(UUID playerId, PermissionContext ... context)
...

The permission plugin##

The plugin decides how it handles (or ignores) the context, how it saves permission andcontext data (extra table in database etc.) and anything else.
The only thing the server does is find all parent permissions (specified by plugins, or in the permissions.yml) that include the permission that is asked for:

plugin checks if player.hasPermission("protectionplugin.build")
>
server finds all parent perms that include it:
- protectionplugin.build
- myperms.basic
- mygroups.user
- mygroups.admin
>
server asks permPlugin if player has any of these
permPlugin.hasPermission(player.getUniqueId(), "protectionplugin.build") --> false
permPlugin.hasPermission(player.getUniqueId(), "myperms.basic") --> false
permPlugin.hasPermission(player.getUniqueId(), "mygroups.user") --> true
>
Yay, found one! return true;
1 Like

Letā€™s say you have a plugin for giving build permissions for a certain world

/world trust IDragonfire

The plugin doesnā€™t have itā€™s own datastore but uses the permission system (makes sense, or not?)
Now someone wants to see who can build in this world:

/world members

So you need a list of all players who have the permission in this world

I realize that for some of you this goes against what the Sponge API should do.
But thereā€™s a reason that Vault became the most downloaded plugin ā€“ people thought that this API was useful. Sure itā€™s not vanilla, but it is extremely useful for at least 80% of server admins.

And thereā€™s a reason itā€™s layered. That means that plugins can switch out certain layers instead of rewriting the whole infrastructure. To prevent the permissions mess that happened to Bukkit, let permissions plugins only have to worry about individual layers. The point is to give a predictable, standard API between those layers, so the stack can function however server owners want it to function without much pain.

And Iā€™m not even saying that Sponge has to implement the whole stack. Most of us know that once Bukkit had object-level permissions and permissions config storage, the permissions situation was at least somewhat sane. But the point is to have some useful API defaults so that at least the whole thing wonā€™t be implemented over and over. Meaning: have an API skeleton with pluggable layers to adhere to.

I would have suggested to put that in a standard package outside like ā€˜sponge-permsā€™ that would be depended on by every permissions plugin, but seeing as thereā€™s been no progress on the package repository I decided to try to get this into core. If there will be a package manager like soak, this package would be a perfect fit. In order to prevent permissions fragmentation once more, this needs to be out at the same time Sponge is, or people will start writing their own implementations.

2 Likes

This is an empty statement. Of course implementation is different, theyā€™re different plugins.

Yes, exactly. Let them choose from SQL vs YML storage, then let them choose between a provider of group-level metadata. This doesnā€™t mean that the user doesnā€™t get to customize at all. If anything, it gives the user more combinations that individual permissions plugins didnā€™t offer before.

1 Like

@Falkreon and @Minecrell talked about it some hours ago ā€¦ SpongeCommons
In my opinion we need a new layer, e.g. modules, that build on top of the sponge api that are useful for plugin devs, but not required.
We can use plugins for that, but then we have thousand pieces.
I am not sure, but @sk89q talked about a seperate util package for syntaxsugar.

1 Like

I think I see where a lot of people are coming from in saying that a permissions API doesnā€™t belong in Sponge, but I think itā€™d be more helpful than detrimental. Saying that itā€™d complicate setup, Iā€™d think not. Bukkit aimed for maintaining a vanilla experience if no plugins/modifications were added, so I think itā€™d be just as well if the permission API didnā€™t do anything until told to do so. Personal opinion (and from what I understood from the OP), is that itā€™d be great if Sponge had a nice cascading permissions API, but didnā€™t implement it in itā€™s own server. So it wouldnā€™t have a permissions file, and it wouldnā€™t determine who could do what at all, only provide the tools to allow developers to do this early on, rather than writing a nice plugin, then wanting to re-write parts later to fit a user-made permissions API.

I can see how keeping the API vanilla is somewhat of a valid argument, wanting to follow Bukkitā€™s train of thought (for example, if you want a very vanilla server with only minimal modifications, you donā€™t want extra functions interfering), but thatā€™s not generally what APIs are for. As the server owner, using Sponge or Bukkit wouldnā€™t noticeably modify the server unless you wanted it to, unless Iā€™ve misunderstood what Sponge is aiming for.

Not all plugin creators (at least in the Bukkit world) listed all of the permissions used by their plugin. Since I donā€™t want to OP anyone on my server, I need a complete list of permissions so I can properly enter them into whatever permission plugin I use.

1 Like