Skip to content

Instantly share code, notes, and snippets.

@AmauryCarrade
Last active December 26, 2015 15:57
Show Gist options
  • Save AmauryCarrade/0f8ccfd5bed989f668cd to your computer and use it in GitHub Desktop.
Save AmauryCarrade/0f8ccfd5bed989f668cd to your computer and use it in GitHub Desktop.
Bukkit permissions generator (published under the CeCILL-B licence)
<?php
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Routing\Generator\UrlGenerator;
/* ** *** Plugin.yml generation *** ** */
function generatePermissionSection($name, $description = "", $default = "op", $children = array(), $children_default = "true")
{
$section = "\t" . $name . ":\n";
if ($description)
$section .= "\t\tdescription: \"" . addslashes($description) . "\"\n";
$section .= "\t\tdefault: " . $default . "\n";
if (sizeof($children) > 0)
{
$section .= "\t\tchildren:\n";
foreach ($children as $child)
$section .= "\t\t\t" . $child . ": " . $children_default . "\n";
}
return $section . "\n";
}
function generateInheritedPermissions($leaf, $subtree, $default = "op", $children_default = "true", $parents_description = "")
{
$generated = '';
// Only generated if the subtree is non empty, because else, we're at an
// explicitely entered permission and they are added separately after.
if (sizeof ($subtree) > 0)
{
if ($leaf != null)
{
$children = array();
foreach ($subtree as $subleaf => $subsubtree)
{
$children[] = $leaf . '.' . $subleaf;
}
$generated .= generatePermissionSection($leaf . ".*", $parents_description, $default, $children, $children_default);
}
foreach ($subtree as $subleaf => $subsubtree)
{
$generated .= generateInheritedPermissions(($leaf != null ? $leaf . '.' : '') . $subleaf, $subsubtree, $default, $children_default, $parents_description);
}
}
return $generated;
}
function safe_grant($raw_grant, $default = "op")
{
$raw_grant = strtolower($raw_grant);
return in_array($raw_grant, array("true", "false", "op", "non op")) ? $raw_grant : $default;
}
function generate_permissions_yaml($app, $permissions, $add_comments, $powered_comment, $default_grant, $parent_permissions_grant, $default_children_inheritance, $parents_description)
{
// Building a permissions tree
$permissions_tree = array();
foreach ($permissions as $permission)
{
$permission_path = explode('.', $permission['name']);
$leaf = &$permissions_tree;
foreach ($permission_path as $path_part)
{
if (!isset($leaf[$path_part]))
$leaf[$path_part] = array();
$leaf = &$leaf[$path_part];
}
}
// Powered-by
if ($powered_comment)
$generated .= "# Permissions section generated using " . $app['url_generator']->generate('tools.generators.permissions', array(), 1) . "\n";
// Base key
$generated .= "permissions:\n";
// The inherited permissions
if ($add_comments)
$generated .= "\n\t# Permissions inheritance\n\n";
$generated .= generateInheritedPermissions(null, $permissions_tree, $parent_permissions_grant, $default_children_inheritance, $parents_description);
$generated .= "\n";
// The entered permissions
if ($add_comments)
$generated .= "\n\t# Basic permissions\n\n";
foreach ($permissions as $permission)
{
$generated .= generatePermissionSection($permission['name'], $permission['description'], $permission['default']);
}
// We use tabulations while generating for commodity, but the YML format requires spaces.
return str_replace("\t", ' ', $generated);
}
/* ** *** Java enum generation *** ** */
function generate_permissions_enum($app, $permissions, $package = '', $enumVisibility = 'public', $enumName = 'Permissions', $methodGetPermissionName = 'getPermission', $methodIsGrantedName = 'isGrantedTo', $skip_first_permission_part = true, $add_javadoc = false)
{
$generated = '';
if ($package)
$generated .= 'package ' . $package . ';' . "\n\n";
$generated .= 'import org.bukkit.permissions.Permissible;' . "\n\n\n";
$generated .= $enumVisibility . ' enum ' . $enumName . "\n" . '{' . "\n";
// ------- Enum constants
foreach ($permissions as $permission)
{
// First, the JavaDoc
if ($add_javadoc)
{
$generated .= <<<JAVADOC_END
/**
* {$permission['description']}
*/
JAVADOC_END;
}
// We first generate a enum constant name based on the permission
$constantName = strtoupper(str_replace('.', '_', $permission['name']));
if ($skip_first_permission_part)
{
$first_separator_pos = strpos($constantName, '_');
if ($first_separator_pos !== false)
{
$constantName = substr($constantName, $first_separator_pos + 1);
}
}
$generated .= "\t" . $constantName . '("' . $permission['name'] . '"),' . "\n";
// With JavaDoc we add a blank line between the constants (lisibility).
if ($add_javadoc) $generated .= "\n";
}
if (!$add_javadoc) $generated .= "\n";
$generated .= "\t;\n";
// ------- Enum methods
$generated .= <<<ENUM_METHODS
private final String permission;
$enumName(String permission)
{
this.permission = permission;
}
/**
* @return the permission's name.
*/
public String $methodGetPermissionName()
{
return permission;
}
/**
* Checks if this permission is granted to the given permissible.
*
* @param permissible The permissible to check.
* @return {@code true} if this permission is granted to the permissible.
*/
public boolean $methodIsGrantedName(Permissible permissible)
{
return permissible.hasPermission(permission);
}
ENUM_METHODS;
$generated .= '}' . "\n";
return str_replace("\t", ' ', $generated);
}
$app->match("/tools/generators/bukkit/permissions.html", function(Request $request) use($app)
{
error_reporting(0);
$raw = trim($request->request->get('raw_permissions'));
$add_comments = $request->request->has('add_comments');
$powered_comment = $request->request->has('powered_comment');
$default_grant = safe_grant($request->request->get('default_grant'), 'op');
$parent_permissions_grant = safe_grant($request->request->get('parent_permissions_grant'), 'op');
$default_children_inheritance = safe_grant($request->request->get('default_children_inheritance'), 'true');
$parents_description = trim($request->request->get('parents_description'));
$generated_yaml = '';
$generated_java = '';
// Shared maybe?
if (!$raw)
{
$raw = ($request->query->get("data"));
if ($raw)
{
$compressed = base64_decode($raw);
if ($compressed !== false)
{
$raw = gzinflate($compressed);
if ($raw === false) $raw = '';
// Options extraction
if ($raw)
{
$options = $request->query->get('o');
if ($options)
{
$options = gzinflate(base64_decode($options));
if ($options)
{
$options = explode(',', $options);
$sizeofopt = sizeof($options);
if ($sizeofopt > 0)
{
$add_comments = $options[0] == '1';
if ($sizeofopt > 1)
{
$powered_comment = $options[1] == '1';
if ($sizeofopt > 2)
{
$default_grant = safe_grant($options[2]);
if ($sizeofopt > 3)
{
$parent_permissions_grant = safe_grant($options[3]);
if ($sizeofopt > 4)
{
$default_children_inheritance = safe_grant($options[4]);
if ($sizeofopt > 5)
{
$parents_description = base64_decode($options[5]);
}
}
}
}
}
}
}
}
}
}
else $raw = '';
}
}
if ($raw)
{
$raw_permissions = explode("\n", $raw);
$permissions = array();
// Permissions parsing
foreach ($raw_permissions as $raw_permission)
{
if (!trim($raw_permission))
continue;
$exploded_perm = explode(":", $raw_permission);
$size = sizeof($exploded_perm);
$name = "";
$default = $default_grant;
$description = "";
if ($size == 0)
continue;
else
{
$name = trim($exploded_perm[0]);
if ($size == 2)
{
$description = trim($exploded_perm[1]);
}
else if ($size >= 3)
{
$default = safe_grant(trim($exploded_perm[1]), $default_grant);
$description = trim($exploded_perm[2]);
}
}
if (!$name)
continue;
$permissions[] = array(
'name' => $name,
'description' => $description,
'default' => $default
);
}
$generated_yaml = generate_permissions_yaml($app, $permissions, $add_comments, $powered_comment, $default_grant, $parent_permissions_grant, $default_children_inheritance, $parents_description);
$generated_java = generate_permissions_enum($app, $permissions);
}
$options = ($add_comments ? '1' : '0')
. ',' . ($powered_comment ? '1' : '0')
. ',' . $default_grant
. ',' . $parent_permissions_grant
. ',' . $default_children_inheritance
. ',' . base64_encode($parents_description);
return $app['twig']->render('tools/generators/permissions.html.twig', array(
'section' => 'tools.generators.permissions',
'raw' => $raw,
'generated' => $generated_yaml != '',
'generated_yaml' => $generated_yaml,
'generated_java' => $generated_java,
'raw_base64' => urlencode(base64_encode(gzdeflate($raw))),
'options' => urlencode(base64_encode(gzdeflate($options))),
'add_comments' => $add_comments,
'powered_comment' => $powered_comment,
'default_grant' => $default_grant,
'parent_permissions_grant' => $parent_permissions_grant,
'default_children_inheritance' => $default_children_inheritance,
'parents_description' => $parents_description
));
})->bind('tools.generators.permissions');
{% extends 'base.html.twig' %}
{% block maintitle %}Générateur des permissions du plugin.yml ⋅ Minecraft{% endblock %}
{% block title %}
<h1>
Générateur de permissions
</h1>
<p>Permissions de Bukkit dans le fichier plugin.yml</p>
{% endblock %}
{% block stylesheets %}
<style type="text/css">
ol.linenums li {
text-shadow: none;
font-family: Consolas,"Liberation Mono",Menlo,Courier,monospace !important;
font-size: 12px !important;
}
.com { color: #969896; }
.lit { color: #195f91; }
.pun, .opn, .clo { color: #333333; }
.fun { color: #dc322f; }
.str, .atv { color: #183691; }
.kwd, .linenums .tag { color: #A71D5D; }
.typ, .atn, .dec, .var { color: #795DA3; }
.pln { color: #333333; }
</style>
{% endblock %}
{% block content %}
{% if generated %}
<div class="well well-large submit-form">
<h3>Code généré</h3>
<p>
Vous trouverez ci-dessous deux codes générés : la portion du <code>plugin.yml</code> décrivant les permissions, et une énumération Java proposée, permettant de simplifier l'usage des permissions durant le développement de votre plugin.
</p>
<ul class="nav nav-tabs">
<li class="active"><a href="#yaml" data-toggle="tab">Permissions dans le fichier plugin.yml</a></li>
<li><a href="#enum" data-toggle="tab">Énumération Java</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="yaml">
<pre class="prettyprint linenums">{{ generated_yaml }}</pre>
</div>
<div class="tab-pane" id="enum">
<pre class="prettyprint linenums">{{ generated_java }}</pre>
</div>
</div>
<div class="controls">
<label for="share_link">Partager cette génération</label>
<div class="input-prepend">
<span class="add-on"><span class="icon-share"></span></span>
<input type="text" value="{{ url('tools.generators.permissions') }}?data={{ raw_base64 }}&amp;o={{ options }}" onclick="this.select()" class="input-xxlarge" id="share_link" />
</div>
</div>
</div>
{% endif %}
<div class="well well-large submit-form">
<form class="pull-center form-horizontal" style="margin-bottom: 0;" method="post">
<fieldset>
<legend>Entrez les permissions à générer</legend>
<div class="controlss">
<label for="raw_permissions">
<p>Entrez une permission par ligne, sous la forme : </p>
<pre>permission.complete.jusquau.bout : attribution par défaut : Description de la permission</pre>
<p>...où l'attribution est <code>true</code>, <code>false</code>, <code>op</code> ou <code>non op</code>. Vous pouvez omettre l'attribution (et ne séparer que par <code>:</code>).</p>
<p>Ne rentrez pas les permissions intermédiaires (par exemple <code>permission.*</code>).</p>
</label>
<textarea name="raw_permissions" id="raw_permissions" class="span12" rows="15" style="font-family: monospace">{{ raw }}</textarea>
</div>
<div style="margin-top: 20px;">
<label class="checkbox">
<input type="checkbox" name="from_yml" value="" disabled>
Importer depuis un fichier <code>plugin.yml</code>
<span class="help-block">Si cette case est cochée, vous devez entrer un fichier <code>plugin.yml</code> contenant au moins la section <code>permissions</code> ; les permissions seront extraites et la section de permissions sera reconstruite, avec tous les héritages. Cette fonctionnalité n'est pas encore disponible.</span>
</label>
</div>
</fieldset>
<fieldset style="margin-top: 30px;">
<legend>Vous pouvez configurer un peu la génération</legend>
<fieldset>
<label class="checkbox">
<input type="checkbox" name="add_comments"{% if add_comments %} checked{%endif %}>
Ajouter des commentaires pour séparer les sections
</label>
<label class="checkbox">
<input type="checkbox" name="powered_comment"{% if not generated or powered_comment %} checked{% endif %}>
Ajouter un commentaire d'attribution liant vers ce service de génération
</label>
</fieldset>
<fieldset style="margin-top: 20px;">
<div class="control-group">
<label for="parents_description" class="control-label">
Description des parents
</label>
<div class="controls">
<input type="text" class="input-xxlarge" name="parents_description" value="{{ parents_description }}" />
<span class="help-block">
Permet de spécifier une description pour les permissions parentes (étoilées — par exemple <code>permission.*</code>) générées.<br />
La description sera toujours la même, libre à vous bien entendu de la modifier par la suite à la main.
</span>
</div>
</div>
</fieldset>
<fieldset style="margin-top: 20px;">
<div class="control-group">
<label for="default_grant" class="control-label">
Attribution par défaut
</label>
<div class="controls">
<select name="default_grant" id="default_grant">
<option value="true"{% if default_grant == 'true' %} selected{% endif %}>Tout le monde</option>
<option value="false"{% if default_grant == 'false' %} selected{% endif %}>Personne</option>
<option value="op"{% if not generated or default_grant == 'op' %} selected{% endif %}>Opérateurs</option>
<option value="non op"{% if default_grant == 'non op' %} selected{% endif %}>Non-opérateurs</option>
</select>
<span class="help-block">
Précise l'attribution par défaut des permissions pour lesquelles elle n'est pas précisée (format <code>permission.name:Description</code>).
</span>
</div>
</div>
<div class="control-group">
<label for="parent_permissions_grant" class="control-label">
Attribution des permissions parentes
</label>
<div class="controls">
<select name="parent_permissions_grant" id="parent_permissions_grant">
<option value="true"{% if parent_permissions_grant == 'true' %} selected{% endif %}>Tout le monde</option>
<option value="false"{% if parent_permissions_grant == 'false' %} selected{% endif %}>Personne</option>
<option value="op"{% if not generated or parent_permissions_grant == 'op' %} selected{% endif %}>Opérateurs</option>
<option value="non op"{% if parent_permissions_grant == 'non op' %} selected{% endif %}>Non-opérateurs</option>
</select>
<span class="help-block">
Précise l'attribution des permissions parentes générées.
</span>
</div>
</div>
<div class="control-group">
<label for="default_children_inheritance" class="control-label">
Attribution des enfants
</label>
<div class="controls">
<select name="default_children_inheritance" id="default_children_inheritance">
<option value="true"{% if not generated or default_children_inheritance == 'true' %} selected{% endif %}>Héritée</option>
<option value="false"{% if default_children_inheritance == 'false' %} selected{% endif %}>Exclue</option>
<option value="op"{% if default_children_inheritance == 'op' %} selected{% endif %}>Opérateurs</option>
<option value="non op"{% if default_children_inheritance == 'non op' %} selected{% endif %}>Non-opérateurs</option>
</select>
<span class="help-block">
Précise l'attribution par défaut des permissions enfant, si les permissions étoilées sont utilisées.<br />
Avec «&nbsp;Héritée&nbsp;», la permission sera accordée à toute personne ayant la permission étoilée.<br />
Avec «&nbsp;Exclue&nbsp;», la permission sera explicitement refusée même aux personnes ayant la permission étoilée. Elle devra être donnée directement.
</span>
</div>
</div>
</fieldset>
</fieldset>
<fieldset style="margin-top: 30px;">
<input type="submit" value="Générer la section «&nbsp;permissions&nbsp;» du plugin.yml" class="btn btn-primary btn-large span12" />
</fieldset>
</form>
</div>
<p style="text-align: center;" class="outside">
Des chatons vont mourir si vous abusez de ce service.<br />
<a href="https://gist.github.com/AmauryCarrade/0f8ccfd5bed989f668cd">Code source disponible.</a>
</p>
{% endblock %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment