LuckPerms | An advanced permissions plugin

For most plugins, the root permission (eg luckperms) will suffice. But there are a few plugins that are a bit more complicated, such as Griefprevention and Nucleus, both of which recommend a different setup, and make it relatively easy to do it automatically (creating admin and player permission sets). Giving yourself all permissions with * will inadvertently give you permissions that can produce unintended behaviour with those plugins.

1 Like

Hello. I have LuckPerms and Nucleus. And I try to set prefix or colour of nickname for user, but nothing woks out :frowning_face:
For example, I use: /lp user O9YBAH4UK meta addprefix 100 “&1[Test]”
And display in “/lp user O9YBAH4UK meta info”, that I have this prefix, but it doesn’t display in chat.
*I didn’t change something in “Chat” in Nucleus’s config.
What to do?
Thank you for advance!

If you’re problem hasn’t been fixed yet, make sure that

Allows for the formatting of chat to potentially include player prefixes, nicknames and other information
chat=ENABLED

this line is set to ENABLED in your config. Also make sure that you are in the right group and that you aren’t inheriting the prefix from any other group you may have.

You might also get faster help in the LuckPerms discord.

I can’t find this line in LuckPerms’s config. But I found something similar to this in Nucleus’s config and set to ENABLED in chat:

> # Available modules to enable or disable. Set each to ENABLED to enable the module, DISABLED to prevent the module from loading or FORCELOAD to load the module even if something else tries to disable it.

modules {
admin=ENABLED
afk=ENABLED
back=ENABLED
ban=ENABLED
blacklist=ENABLED
chat=ENABLED
…
}
But after that prefixes don’t work :worried:
Moreover, O9YBAH4UK - default group, so this user don’t have any prefixes exempt, for example, “&1[Test]”.
Maybe, I’m looking not there?

Yes, that’s the same config, mines just annotated is all.

Make sure you are using the latest versions of both Nucleus and LuckPerms, as well as the latest sponge version. Also make sure that nucleus has loaded properly do commands like /spawn and /home work? Also make sure that the data for luck perms is being stored properly, if you have a database make sure that the connecting information is correct, any errors could throw your permissions off.

I’m also not certain what you are running on your server but test it out with nothing except for nucleus and luckperms and see if it is working correctly there, it could be a compatibility issue with another plugin.

Can you add a config option when using mongodb backing to use the UUID_STANDARD representation instead of UUID_LEGACY and to choose the dot replacement (currently hardcoded: [**DOT**]) ?

Why is it creating own directory on the server root folder? There’s dedicated folder for those sort of things in Sponge.

Hi thanks for that favolous mod however i have 2 questions:
About the rename of default goup i switched to player however when i run commands it still named default (for example when i tab to autocomplate) any way to also ranem it for comands? or the best option is create a new group and make it a parent for default and edit there all?.
Secondly: where is the herarchy stored and the permissions that each group has (the file where it is saved)

EDIT: I looked this over again recently and found a much simpler way to do it (still using MySQL directly, but without any perl/scripting involved)

The video is here:

The rest of the post below is still true and the information still relevant

The LuckPerms plugin offers the admin a choice to store permissions data in MySQL. It’s a good choice to use MySQL as the data store for permission node data because it’s portable across any servers you are running and want to share the permission data without repetitively entering the same node configuration on each server.

In addition to that benefit, there’s also a use-case where one can go into the database and make bulk changes if the admin knows a little SQL and scripting language.

Let me explain:

When a new server is established, it’s often necessary to program hundreds of new permission nodes for the various role/groups that are designed. For example, your server may have roles as member, moderator, builder, staff, and admin, etc…

Just for example, the Nucleus plugin has roughly 500+ permission nodes that can be set. GriefPrevention has a few dozen more, and with each new administrative plugin the number of nodes can pile up. It’s a chore and not effective to type these in via the game. In fact, I simply refuse to. I’d rather write some SQL to pre-program the database with the node parameters.

This post will walk you through how that can be done.

The prerequisite is that you have shell access to the system that hosts the MySQL database used by your server (probably the same server hardware, but it doesn’t have to be).

Also, you need to have some familiarity with a scripting language (perl, python, or something else that can establish database connectivity to a MySQL database).

I know perl far better than python so I use perl.

FInally, you need to have a bare minimum of experience with SQL. It’s not difficult to learn SQL if you remember some golden rules about how SQL works and the intent of SQL:

SQL never (usually never) describes HOW a database perform a query. It defines instead WHAT the query is. The database engine designers implement the execution of SQL and the server knows better than you on how to actually carry out the query. By query I mean either a SELECT type statement (one that fetches data), and a UPDATE type statement which modifies data. In either case, write the SQL to describe WHAT not HOW.

The second golden rule is to remember that SQL is a language to interact with a Relational Database. A relational database means that intrinsically, records in table A relate to records in table B by referential integrity established by the schema of the database. There is a science behind this. (Extra review: [Tuple relational calculus - Wikipedia] of relational calculus) Database schema’s are designed with a certain Normal Form. Take a CS class in database theory and you’ll go over this in detail. (Review Normal Forms here: [Database normalization - Wikipedia]). Most schemas used by most plugins do not exhibit normal forms of any definite pattern – they are close, but not exact. That won’t impact your use of the database, but it can come to bear when you try to make modifications to a relational database when the relational integrity is not clear (or defined).

Disclaimer: In college I rebelled against the professor ([https://cse.wwu.edu/computer-science/johnsoj5]) on wanting to take Database Theory. The outcome was I re-took the class (CS 320) about 4 times. (We used his textbook in draft that became a publication, highly recommended: [http://bit.ly/2iBhrt8]) I finally gave in and passed the course, but in the process became convinced that understanding Database Theory was very important for CS knowledge. Maybe it was several years of hanging out on campus and realizing I wasn’t going to graduate until I finished the course.

Upshot:
Plugin developers who use external data stores (like MySQL) should take this subject seriously
.

OK, so let’s start.

First step when using MySQL database with a plugin like LuckPerms is to create the database itself. This is simple, but my advice is to make a temporary database and let LuckPerms be configured to use it before putting the results into production. After experimenting (as shown below) and you’re confident you can alter the database in a bulk mode, then re-build a new database (as shown below) and apply the same bulk operation to that database. In otherwords, don’t do this on your production database.

(In the following instructions, when you see a $ prompt, that implies the shell prompt of the system on which the MySQL database is running). A mysql> prompt is the prompt of the MySQL session.

  1. Create the database:

$ mysql -u root -D mysql -p

Enter the password for user root on the MySQL server. If you don’t have it, google how to reset it. This is not the password for the user root of the System but the password of the MySQL database user root

At the MySQL prompt enter this:

mysql> create database fooDatabase;

SQL statements end with ; SQL is not case sensitive (with regard to commands and the SQL language. The data you insert into a SQL database is case sensitive because it’s data, not part of the SQL language.

Now the database is created.

  1. Create a user for accessing this new database.

mysql> create user 'joe'@'localhost' identified by "PASSWORD";

(Note; use literally 'localhost', don’t enter the host name of your server. )

The key is that 'joe' is in single quotes. @ is not in single quotes. 'localhost' is in single quotes. The PASSWORD is in double quotes and this is the PLAIN text password.

  1. Grant rights for 'joe'@'localhost' to access only the new database (and no other)

mysql> grant all on fooDatabase.* to 'joe'@'localhost';

Now joe can do anything on the database fooDatabase and only fooDatabase.

  1. Now when you configure your LuckPerms plugin, you can set the database name, user, password to these details:

This is a snippit from the LuckPerms config file. Note the match-up of the database, username, and password
field entries. They should match what you did when you created the database. leave address as is ("localhost").

data {
  # Uses standard DB engine port by default
  # MySQL: 3306, PostgreSQL: 5432, MongoDB: 27017
  # Specify as "host:port" if differs
  address="localhost"

  database="fooDatabase"
  username="joe"
  password="PASSWORD"

There’s no need to set username="joe@localhost". Just use joe

When your server starts up with the LuckPerms plugin, then the plugin will do the work to create the tables IN the database fooDatabase;

Exit from MySQL and re-login as joe

mysql> mysql -u joe -D fooDatabase -p

Press ENTER, Enter the password

You should be logged into MySQL as joe on fooDatabase.

Back to the MySQL shell. You can list those tables as follows:

mysql> show databases;

You’ll see your new database in the list.

Now you can describe the database. That means to list the tables IN that database.

mysql> show tables;

All the tables in that database are now listed.

Pick a table, you can describe the table. This means to list the fields and types of each field of that table:

mysql> desc luckperms_user_permissions;

mysql> desc luckperms_user_permissions;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| uuid       | varchar(36)  | NO   | MUL | NULL    |                |
| permission | varchar(200) | NO   | MUL | NULL    |                |
| value      | tinyint(1)   | NO   |     | NULL    |                |
| server     | varchar(36)  | NO   |     | NULL    |                |
| world      | varchar(36)  | NO   |     | NULL    |                |
| expiry     | int(11)      | NO   |     | NULL    |                |
| contexts   | varchar(200) | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

Without knowledge of how the code in the plugin actually populates the records of various tables, it can be more informative to use the /luckperm command to just add a permission to a user or a group using the Getting Started wiki page. Do that now, create the initial permissions for LuckPerms as described in the Getting Started wiki page.

Once you have that you can come back to the MySQL shell (no reason to log out of MySQL while you do that… that’s the whole point-- multiple agents can access the database asynchronously.

mysql> desc luckperms_groups;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(36) | NO   | PRI | NULL    |       |
+-------+-------------+------+-----+---------+-------+
1 row in set (0.00 sec)

Let’s see what groups you have so far:

mysql> select name from luckperms_groups;

On my server I have this output:

mysql> select name from luckperms_groups;
+---------+
| name    |
+---------+
| admin   |
| default |
| member  |
| mod     |
| staff   |
+---------+
5 rows in set (0.00 sec)

To find all the groups that are associated with (read: related to) a record in luckperms_group_permissions:

mysql> select distinct name from luckperms_group_permissions;

To count the number of permission records in luckperms_group_permissions that are involved with relation to some group (eg, admin):

mysql> select count(*) from luckperms_group_permissions where name = "admin";

By the way, operations like count(*) in SQL are called aggregates. It’s a function built into a RDBMS like MySQL. What it means here is every row that matches the WHERE clause is counted. The result is one row, the count of rows that match the WHERE clause of the SELECT statement.

On my server:

mysql> select count(*) from luckperms_group_permissions where name ="admin";
+----------+
| count(*) |
+----------+
|      548 |
+----------+
1 row in set (0.00 sec)

You can do the same sort of thing with the by-user permission table.

To remind yourself what the fields are in the table:


mysql> desc   luckperms_user_permissions;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| uuid       | varchar(36)  | NO   | MUL | NULL    |                |
| permission | varchar(200) | NO   | MUL | NULL    |                |
| value      | tinyint(1)   | NO   |     | NULL    |                |
| server     | varchar(36)  | NO   |     | NULL    |                |
| world      | varchar(36)  | NO   |     | NULL    |                |
| expiry     | int(11)      | NO   |     | NULL    |                |
| contexts   | varchar(200) | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)

And to look at the records:

mysql> select uuid, permission from luckperms_user_permissions;
+--------------------------------------+---------------+
| uuid                                 | permission    |
+--------------------------------------+---------------+
| 4aaabd99-af6c-4d18-a5ab-0ef317691da9 | group.default |
| 4aaabd99-af6c-4d18-a5ab-0ef317691da9 | luckperms.*   |
| 4aaabd99-af6c-4d18-a5ab-0ef317691da9 | group.admin   |
| 5f78336f-c890-4bba-8f43-a3a2351e46e1 | group.default |
| 5f78336f-c890-4bba-8f43-a3a2351e46e1 | luckperms.*   |
| 5f78336f-c890-4bba-8f43-a3a2351e46e1 | group.admin   |
| 4aaabd99-af6c-4d18-a5ab-0ef317691da9 | enjin.*       |
| 5f78336f-c890-4bba-8f43-a3a2351e46e1 | enjin.*       |
+--------------------------------------+---------------+
8 rows in set (0.00 sec)

Now you can get the idea of how the data is stored in the MySQL tables associated with the plugin. Each table has an id record in each field (each tuple we’d say). The id field in the tuple is like saying the “column id in the row of data from a table”. Instead of saying “row of data” we just say “tuple” /too-pəl/

The id field is a key and it’s auto-incremented by the database. No need to insert id field when making additions to the tables.

Let’s make two queries. One is to look at per-user tuples where the permission is defined by the LuckPerm plugin (“group.admin”) and another query to look at tuples where the permission node is an actual node defined by the third party plugin/mod:


mysql> select * from  luckperms_user_permissions where permission = "group.admin";
+----+--------------------------------------+-------------+-------+--------+--------+--------+----------+
| id | uuid                                 | permission  | value | server | world  | expiry | contexts |
+----+--------------------------------------+-------------+-------+--------+--------+--------+----------+
|  3 | 4aaabd99-af6c-4d18-a5ab-0ef317691da9 | group.admin |     1 | global | global |      0 | {}       |
|  6 | 5f78336f-c890-4bba-8f43-a3a2351e46e1 | group.admin |     1 | global | global |      0 | {}       |
+----+--------------------------------------+-------------+-------+--------+--------+--------+----------+
2 rows in set (0.00 sec)

mysql> select * from  luckperms_user_permissions where permission = "enjin.*";
+----+--------------------------------------+------------+-------+--------+--------+--------+----------+
| id | uuid                                 | permission | value | server | world  | expiry | contexts |
+----+--------------------------------------+------------+-------+--------+--------+--------+----------+
|  7 | 4aaabd99-af6c-4d18-a5ab-0ef317691da9 | enjin.*    |     1 | global | global |      0 | {}       |
|  8 | 5f78336f-c890-4bba-8f43-a3a2351e46e1 | enjin.*    |     1 | global | global |      0 | {}       |
+----+--------------------------------------+------------+-------+--------+--------+--------+----------+
2 rows in set (0.00 sec)

At this point, even for those with a modest amount of SQL experience can begin to see the connection.

To automate the population of permission nodes for a GROUP would be fairly trivial.

Here’s how I’d do it in perl:

First an example of how to fetch data.

#!/usr/bin/perl

use DBI;

# set parameters used to connect to your database

my $database = 'fooDatabase';
my $host = 'localhost';
my $user = 'joe';
my $password = 'PASSWORD';
my $port = 3306;


my $dsn = "DBI:mysql:user=$user;password=$password;database=$database;host=$hostname;port=$port";

# this is the handle to the database session
my $dbh = DBI->connect($dsn, $user, $password);

# with the session, create a statement to execute
my $sth = $dbh->prepare('select * from luckperms_group_permissions')
    or die "prepare statement failed: $dbh->errstr()";

# execute the statement
$sth->execute() or die "execution failed: $dbh->errstr()";

# analyze the results:

print $sth->rows . " rows found.\n";

# with the scripting language writing the emebdded SQL
# we can iterate the results as they are obtained from the server

while (my $ref = $sth->fetchrow_hashref()) {

     # the code below is written such that we expect
     # the fields by the listed names.

     print "Found a row: ",
        join("|",
          $ref->{'id'},
          $ref->{'name'},
          $ref->{'permission'},
          $ref->{'value'},
          $ref->{'server'},
          $ref->{'world'},
          $ref->{'expiry'},
          $ref->{'contexts'}), "\n";
}
# close the handle to the database (equivalent to exiting mysql command)

$sth->finish;

That code is virtually the same as running this SQL statement:

mysql> select * from luckperms_group_permissions;

The difference is that with the script we can do actions against the database while we query.

Now, with a little more perl you could make a script read from a text file of permission nodes (a dump of some node list from Nucleus, for example) and then change the SQL statement to an UPDATE to insert new tuples into the database.

Suppose we learn the permission nodes for the Nucleus plugin. From a simple extraction of the web site, we can produce a text file of role and permission.

The file may look like:
[https://gist.github.com/sibomots/30dec8d104284f4d9dd2a4ee9dabd35c] (sampleDataFile.txt)

That will be our input file. Our goal is to establish the permission nodes in LuckPerms for those entries.

Here’s a sample script that will insert records into the table for group-wise permissions:

[http://gist.github.com/081889184462c80266cff7867da7a4bd] (loadLuckPerms.pl)

Questions – drop me a line (or post here)

4 Likes

is there a way to give 2 groups the same permission by just parenting them? like we have 2 groups 1 for players who are not registered on the website and one for players who registered on the website so

my question is

default group has a permission named warp.warp.test which makes the user be able to do /warp test

so to make it easier for server owners is there a way to just parent the group default to the group for website registered players?

@GetShrekt
I do the same, have a default rank, and then a member rank for website registered players. Parenting them works great.

/lp group member parent add default

I believe that’s the correct command, if i recall correctly. So that will give your members all the permissions that default has.

Hope this helps :slight_smile:

  • Alice

no.Only LuckPerms plugin

I am lazy. I want to make the permissions just be there. So I worked out the SQL to do it.

This script (link below) will just setup your Luckperms permission nodes, group ranking, and add a “track” for promotions.

It does the work to handle Nucleus and GriefPrevention plugins. It also handles the basic Minecraft, Forge, and Sponge coremod permission nodes too.

The documentation shows the steps to take.

WARNING: It’s designed to create the initial database configuration. DO NOT run this on an existing database.

YOU HAVE BEEN WARNED.

https://github.com/sibomots/YouTube/tree/master/LuckPerms/scripts

1 Like

You can be either lazy OR spend time and effort to make a script for yourself and others to use, you can’t be both :slight_smile:

Is there a way to tell what Sponge API version the LuckPerms releases are for? I can’t seem to find any information on the files until I run them in the server.

Groups can inherit an number of groups.

It’s an exercize in normalizing the permissions into groups and inheriting those groups into groups.

It’s counter-intuitive, but collect a topic into a group. Say, “Nucleus perms for users” and “Nucleus perms for moderators” and “Nucleus perms for admins”.

Call them nuc-users, nuc-moderators, nuc-admin

Same exercize for anohter plugin, and so on.

You’ll wind up with X-users, X-moderators, X-admin and so on depending on your overall hierarchy of users.
(Think of users, moderators and admin as just the list of “track-able” ranks, add more sub-divisions as necessary)

So for the situation where X-users and X-users-prime differ by a set of perms S, then that would be codified by the new hierarchy:

general-user inherits X-users and Y-users and Z-users
general-user-prime inherits X-users-prime, Y-users and Z-users

The key is to inject new perms into a top-level track-able group (rank) by inheritance of groups. The result is that a player in the game is simply a member of a certain single group.

The schema of Luckperms allows this. As far as it’s efficiency by the way that Luckperms implements it, is another story.

All releases support API 5-7. Not sure how long that will last for, I’m resisting having to maintain separate branches. :smiley:

3 Likes

Hello, im trying to find luck pems for sponge 5.2 but your download is only for sponge 6 and 7 but on jenkis you have this Sponge API 5/6 –> LuckPerms-Sponge. When i run it server pops up in log this:

The mod luckperms was designed for spongeapi 6.0.0 but version 5.2.0-SNAPSHOT-c675e80 is in use. It may not work properly.

Where i can find luckperms for sponge5+ pls ?

@Wyrmilius_Korses

As far as I know, Luckperms works on API’s 5, 6 and 7.

does someone know why i cant use command blocks any more after i start using luckperms ???