Adding Support for Crafty Permissions with limits

This commit is contained in:
Silversthorn 2021-08-24 23:07:00 +02:00
parent 25a0cf3d1e
commit bb1f43bc81
7 changed files with 258 additions and 45 deletions

View File

@ -12,7 +12,7 @@ from distutils import dir_util
from app.classes.shared.helpers import helper
from app.classes.shared.console import console
from app.classes.shared.models import db_helper, server_permissions
from app.classes.shared.models import db_helper, server_permissions, Enum_Permissions_Server, crafty_permissions, Enum_Permissions_Crafty
from app.classes.shared.server import Server
from app.classes.minecraft.server_props import ServerProps
@ -115,6 +115,11 @@ class Controller:
permissions_list = server_permissions.get_permissions_list()
return permissions_list
@staticmethod
def list_defined_crafty_permissions():
permissions_list = crafty_permissions.get_permissions_list()
return permissions_list
@staticmethod
def get_mask_permissions(role_id, server_id):
permissions_mask = db_helper.get_permissions_mask(role_id, server_id)
@ -128,18 +133,44 @@ class Controller:
@staticmethod
def get_server_permissions_foruser(user_id, server_id):
permissions_list = db_helper.get_user_permissions_list(user_id, server_id)
return permissions_list
@staticmethod
def get_mask_crafty_permissions(user_id):
permissions_mask = db_helper.get_crafty_permissions_mask(user_id)
return permissions_mask
@staticmethod
def get_crafty_permissions(user_id):
permissions_list = db_helper.get_crafty_permissions_list(user_id)
return permissions_list
@staticmethod
def can_create_server(user_id):
permissions_mask = db_helper.get_crafty_permissions_mask(user_id)
return crafty_permissions.has_permission(permissions_mask, Enum_Permissions_Crafty.Server_Creation)
@staticmethod
def list_all_crafty_permissions_quantity_limits():
return db_helper.get_all_permission_quantity_list()
@staticmethod
def list_crafty_permissions_quantity_limits(user_id):
return db_helper.get_permission_quantity_list(user_id)
@staticmethod
def get_crafty_permissions(user_id):
permissions_list = db_helper.get_crafty_permissions_list(user_id)
return permissions_list
@staticmethod
def get_crafty_permissions(user_id):
permissions_list = db_helper.get_crafty_permissions_list(user_id)
return permissions_list
@staticmethod
def list_authorized_servers(userId):
servers = db_helper.get_authorized_servers(userId)
server_list = []
for item in servers:
server_list.append(item)
role_servers = db_helper.get_authorized_servers(userId)
for item in role_servers:
server_list.append(item)
logger.debug("servers list = {}".format(servers))
server_list = db_helper.get_authorized_servers(userId)
return server_list
def get_server_data(self, server_id):

View File

@ -133,6 +133,8 @@ class User_Crafty(Model):
user_id = ForeignKeyField(Users, backref='users_crafty')
permissions = CharField(default="00000000")
limit_server_creation = IntegerField(default=-1)
limit_user_creation = IntegerField(default=0)
limit_role_creation = IntegerField(default=0)
class Meta:
table_name = 'user_crafty'
@ -432,6 +434,40 @@ class db_shortcuts:
if authorized.count() == 0:
return False
return True
@staticmethod
def get_crafty_permissions_mask(user_id):
permissions_mask = ''
user_crafty = User_Crafty.select().where(User_Crafty.user_id == user_id).get()
permissions_mask = user_crafty.permissions
return permissions_mask
@staticmethod
def get_crafty_permissions_list(user_id):
permissions_mask = ''
user_crafty = User_Crafty.select().where(User_Crafty.user_id == user_id).get()
permissions_mask = user_crafty.permissions
permissions_list = crafty_permissions.get_permissions(permissions_mask)
return permissions_list
@staticmethod
def get_all_permission_quantity_list():
quantity_list = {
Enum_Permissions_Crafty.Server_Creation.name: -1,
Enum_Permissions_Crafty.User_Config.name: -1,
Enum_Permissions_Crafty.Roles_Config.name: -1,
}
return quantity_list
@staticmethod
def get_permission_quantity_list(user_id):
user_crafty = User_Crafty.select().where(User_Crafty.user_id == user_id).get()
quantity_list = {
Enum_Permissions_Crafty.Server_Creation.name: user_crafty.limit_server_creation,
Enum_Permissions_Crafty.User_Config.name: user_crafty.limit_user_creation,
Enum_Permissions_Crafty.Roles_Config.name: user_crafty.limit_role_creation,
}
return quantity_list
@staticmethod
def get_latest_hosts_stats():
@ -555,7 +591,7 @@ class db_shortcuts:
return {}
@staticmethod
def update_user(user_id, user_data={}):
def update_user(user_id, user_data={}, user_crafty_data={}):
base_data = db_helper.get_user(user_id)
up_data = {}
added_roles = set()
@ -581,6 +617,31 @@ class db_shortcuts:
for role in added_roles:
User_Roles.get_or_create(user_id=user_id, role_id=role)
# TODO: This is horribly inefficient and we should be using bulk queries but im going for functionality at this point
for key in user_crafty_data:
if key == "permissions_mask":
permissions_mask = user_crafty_data['permissions_mask']
if key == "server_quantity":
limit_server_creation = user_crafty_data['server_quantity'][Enum_Permissions_Crafty.Server_Creation.name]
limit_user_creation = user_crafty_data['server_quantity'][Enum_Permissions_Crafty.User_Config.name]
limit_role_creation = user_crafty_data['server_quantity'][Enum_Permissions_Crafty.Roles_Config.name]
try:
user_crafty = User_Crafty.select().where(User_Crafty.user_id == user_id).get()
user_crafty.permissions = permissions_mask
user_crafty.limit_server_creation = limit_server_creation
user_crafty.limit_user_creation = limit_user_creation
user_crafty.limit_role_creation = limit_role_creation
User_Crafty.save(user_crafty)
except:
User_Crafty.insert({
User_Crafty.user_id: user_id,
User_Crafty.permissions: permissions_mask,
User_Crafty.limit_server_creation: limit_server_creation,
User_Crafty.limit_user_creation: limit_user_creation,
User_Crafty.limit_role_creation: limit_role_creation
}).execute()
User_Roles.delete().where(User_Roles.user_id == user_id).where(User_Roles.role_id.in_(removed_roles)).execute()
if up_data:

View File

@ -12,7 +12,7 @@ from tornado import iostream
from app.classes.shared.console import console
from app.classes.shared.models import Users, installer
from app.classes.web.base_handler import BaseHandler
from app.classes.shared.models import db_helper, server_permissions, Servers, Enum_Permissions_Server
from app.classes.shared.models import db_helper, server_permissions, Servers, Enum_Permissions_Server, crafty_permissions, Enum_Permissions_Crafty
from app.classes.shared.helpers import helper
logger = logging.getLogger(__name__)
@ -37,12 +37,14 @@ class PanelHandler(BaseHandler):
if exec_user['superuser'] == 1:
defined_servers = self.controller.list_defined_servers()
exec_user_role.add("Super User")
exec_user_crafty_permissions = self.controller.list_defined_crafty_permissions()
else:
exec_user_crafty_permissions = self.controller.get_crafty_permissions(exec_user_id)
logger.debug(exec_user['roles'])
for r in exec_user['roles']:
role = db_helper.get_role(r)
exec_user_role.add(role['role_name'])
defined_servers = db_helper.get_authorized_servers(exec_user_id)
defined_servers = self.controller.list_authorized_servers(exec_user_id)
page_data = {
# todo: make this actually pull and compare version data
@ -50,6 +52,12 @@ class PanelHandler(BaseHandler):
'version_data': helper.get_version_string(),
'user_data': exec_user_data,
'user_role' : exec_user_role,
'user_crafty_permissions' : exec_user_crafty_permissions,
'crafty_permissions': {
'Server_Creation': Enum_Permissions_Crafty.Server_Creation,
'User_Config': Enum_Permissions_Crafty.User_Config,
'Roles_Config': Enum_Permissions_Crafty.Roles_Config,
},
'server_stats': {
'total': len(defined_servers),
'running': len(self.controller.list_running_servers()),
@ -64,9 +72,13 @@ class PanelHandler(BaseHandler):
# if no servers defined, let's go to the build server area
if page_data['server_stats']['total'] == 0 and page != "error" and page != "credits" and page != "contribute":
self.set_status(301)
self.redirect("/server/step1")
return
if Enum_Permissions_Crafty.Server_Creation not in exec_user_crafty_permissions and len(defined_servers) == 0:
logger.warning("User '" + exec_user['username'] + "#" + str(exec_user_id) + "' has access to 0 servers and is not a server creator")
else:
self.set_status(301)
self.redirect("/server/step1")
return
if page == 'unauthorized':
template = "panel/denied.html"
@ -325,15 +337,18 @@ class PanelHandler(BaseHandler):
page_data['user']['last_update'] = "N/A"
page_data['user']['roles'] = set()
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access: not superuser")
if Enum_Permissions_Crafty.User_Config not in exec_user_crafty_permissions:
self.redirect("/panel/error?error=Unauthorized access: not a user editor")
return
page_data['roles_all'] = db_helper.get_all_roles()
page_data['servers'] = []
page_data['servers_all'] = self.controller.list_defined_servers()
page_data['permissions_all'] = self.controller.list_defined_permissions()
page_data['role-servers'] = []
page_data['permissions_all'] = self.controller.list_defined_crafty_permissions()
page_data['permissions_list'] = set()
page_data['quantity_server'] = self.controller.list_all_crafty_permissions_quantity_limits()
template = "panel/panel_edit_user.html"
elif page == "edit_user":
@ -349,12 +364,18 @@ class PanelHandler(BaseHandler):
page_data['role-servers'] = page_role_servers
page_data['roles_all'] = db_helper.get_all_roles()
page_data['servers_all'] = self.controller.list_defined_servers()
page_data['permissions_all'] = self.controller.list_defined_permissions()
page_data['permissions_all'] = self.controller.list_defined_crafty_permissions()
page_data['permissions_list'] = self.controller.get_crafty_permissions(user_id)
page_data['quantity_server'] = self.controller.list_crafty_permissions_quantity_limits(user_id)
if user_id is None:
self.redirect("/panel/error?error=Invalid User ID")
return
elif not exec_user['superuser']:
elif Enum_Permissions_Crafty.User_Config not in exec_user_crafty_permissions:
if user_id != exec_user_id:
self.redirect("/panel/error?error=Unauthorized access: not a user editor")
return
page_data['servers'] = []
page_data['role-servers'] = []
page_data['roles_all'] = []
@ -408,8 +429,8 @@ class PanelHandler(BaseHandler):
page_data['user-roles'] = user_roles
page_data['users'] = db_helper.get_all_users()
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access: not superuser")
if Enum_Permissions_Crafty.Roles_Config not in exec_user_crafty_permissions:
self.redirect("/panel/error?error=Unauthorized access: not a role editor")
return
page_data['servers_all'] = self.controller.list_defined_servers()
@ -435,8 +456,8 @@ class PanelHandler(BaseHandler):
page_data['user-roles'] = user_roles
page_data['users'] = db_helper.get_all_users()
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access: not superuser")
if Enum_Permissions_Crafty.Roles_Config not in exec_user_crafty_permissions:
self.redirect("/panel/error?error=Unauthorized access: not a role editor")
return
elif role_id is None:
self.redirect("/panel/error?error=Invalid Role ID")
@ -491,7 +512,9 @@ class PanelHandler(BaseHandler):
if exec_user['superuser'] == 1:
defined_servers = self.controller.list_defined_servers()
exec_user_role.add("Super User")
exec_user_crafty_permissions = self.controller.list_defined_crafty_permissions()
else:
exec_user_crafty_permissions = self.controller.get_crafty_permissions(exec_user_id)
defined_servers = self.controller.list_authorized_servers(exec_user_id)
for r in exec_user['roles']:
role = db_helper.get_role(r)
@ -592,7 +615,11 @@ class PanelHandler(BaseHandler):
enabled = int(float(self.get_argument('enabled', '0')))
regen_api = int(float(self.get_argument('regen_api', '0')))
if not exec_user['superuser']:
if Enum_Permissions_Crafty.User_Config not in exec_user_crafty_permissions:
if user_id != exec_user_id:
self.redirect("/panel/error?error=Unauthorized access: not a user editor")
return
user_data = {
"username": username,
"password": password0,
@ -632,15 +659,24 @@ class PanelHandler(BaseHandler):
if argument:
roles.add(role.role_id)
servers = set()
for server in self.controller.list_defined_servers():
permissions_mask = "00000000"
server_quantity = {}
for permission in self.controller.list_defined_crafty_permissions():
argument = int(float(
bleach.clean(
self.get_argument('server_{}_access'.format(server['server_id']), '0')
self.get_argument('permission_{}'.format(permission.name), '0')
)
))
if argument:
servers.add(server['server_id'])
permissions_mask = crafty_permissions.set_permission(permissions_mask, permission, argument)
q_argument = int(float(
bleach.clean(
self.get_argument('quantity_{}'.format(permission.name), '0')
)
))
if q_argument:
server_quantity[permission.name] = q_argument
user_data = {
"username": username,
@ -649,10 +685,14 @@ class PanelHandler(BaseHandler):
"regen_api": regen_api,
"roles": roles,
}
db_helper.update_user(user_id, user_data=user_data)
user_crafty_data = {
"permissions_mask": permissions_mask,
"server_quantity": server_quantity
}
db_helper.update_user(user_id, user_data=user_data, user_crafty_data=user_crafty_data)
db_helper.add_to_audit_log(exec_user['user_id'],
"Edited user {} (UID:{}) with roles {} and servers {}".format(username, user_id, roles, servers),
"Edited user {} (UID:{}) with roles {} and permissions {}".format(username, user_id, roles, permissions_mask),
server_id=0,
source_ip=self.get_remote_ip())
self.redirect("/panel/panel_config")
@ -664,8 +704,8 @@ class PanelHandler(BaseHandler):
password1 = bleach.clean(self.get_argument('password1', None))
enabled = int(float(self.get_argument('enabled', '0')))
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access: not superuser")
if Enum_Permissions_Crafty.User_Config not in exec_user_crafty_permissions:
self.redirect("/panel/error?error=Unauthorized access: not a user editor")
return
elif username is None or username == "":
self.redirect("/panel/error?error=Invalid username")
@ -689,22 +729,35 @@ class PanelHandler(BaseHandler):
))
if argument:
roles.add(role.role_id)
servers = set()
for server in self.controller.list_defined_servers():
permissions_mask = "00000000"
server_quantity = {}
for permission in self.controller.list_defined_crafty_permissions():
argument = int(float(
bleach.clean(
self.get_argument('server_{}_access'.format(server['server_id']), '0')
self.get_argument('permission_{}'.format(permission.name), '0')
)
))
if argument:
servers.add(server['server_id'])
permissions_mask = crafty_permissions.set_permission(permissions_mask, permission, argument)
q_argument = int(float(
bleach.clean(
self.get_argument('quantity_{}'.format(permission.name), '0')
)
))
if q_argument:
server_quantity[permission.name] = q_argument
user_id = db_helper.add_user(username, password=password0, enabled=enabled)
user_data = {
"roles": roles,
}
db_helper.update_user(user_id, user_data)
user_crafty_data = {
"permissions_mask": permissions_mask,
"server_quantity": server_quantity
}
db_helper.update_user(user_id, user_data=user_data, user_crafty_data=user_crafty_data)
db_helper.add_to_audit_log(exec_user['user_id'],
"Added user {} (UID:{})".format(username, user_id),
@ -720,8 +773,8 @@ class PanelHandler(BaseHandler):
role_id = bleach.clean(self.get_argument('id', None))
role_name = bleach.clean(self.get_argument('role_name', None))
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access: not superuser")
if Enum_Permissions_Crafty.Roles_Config not in exec_user_crafty_permissions:
self.redirect("/panel/error?error=Unauthorized access: not a role editor")
return
elif role_name is None or role_name == "":
self.redirect("/panel/error?error=Invalid username")
@ -771,8 +824,8 @@ class PanelHandler(BaseHandler):
elif page == "add_role":
role_name = bleach.clean(self.get_argument('role_name', None))
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access: not superuser")
if Enum_Permissions_Crafty.Roles_Config not in exec_user_crafty_permissions:
self.redirect("/panel/error?error=Unauthorized access: not a role editor")
return
elif role_name is None or role_name == "":
self.redirect("/panel/error?error=Invalid role name")

View File

@ -6,7 +6,7 @@ import shutil
from app.classes.shared.console import console
from app.classes.web.base_handler import BaseHandler
from app.classes.shared.models import db_helper
from app.classes.shared.models import db_helper, Enum_Permissions_Crafty
from app.classes.minecraft.serverjars import server_jar_obj
from app.classes.shared.helpers import helper
@ -37,7 +37,9 @@ class ServerHandler(BaseHandler):
if exec_user['superuser'] == 1:
defined_servers = self.controller.list_defined_servers()
exec_user_role.add("Super User")
exec_user_crafty_permissions = self.controller.list_defined_crafty_permissions()
else:
exec_user_crafty_permissions = self.controller.get_crafty_permissions(exec_user_id)
defined_servers = self.controller.list_authorized_servers(exec_user_id)
for r in exec_user['roles']:
role = db_helper.get_role(r)
@ -49,6 +51,12 @@ class ServerHandler(BaseHandler):
'version_data': helper.get_version_string(),
'user_data': exec_user_data,
'user_role' : exec_user_role,
'user_crafty_permissions' : exec_user_crafty_permissions,
'crafty_permissions': {
'Server_Creation': Enum_Permissions_Crafty.Server_Creation,
'User_Config': Enum_Permissions_Crafty.User_Config,
'Roles_Config': Enum_Permissions_Crafty.Roles_Config,
},
'server_stats': {
'total': len(self.controller.list_defined_servers()),
'running': len(self.controller.list_running_servers()),
@ -61,6 +69,10 @@ class ServerHandler(BaseHandler):
if page == "step1":
if not self.controller.can_create_server(exec_user_id):
self.redirect("/panel/error?error=Unauthorized access: not at server creator")
return
page_data['server_types'] = server_jar_obj.get_serverjar_data_sorted()
page_data['js_server_types'] = json.dumps(server_jar_obj.get_serverjar_data_sorted())
template = "server/wizard.html"

View File

@ -21,9 +21,11 @@
</a>
<div class="collapse" id="page-layouts">
<ul class="nav flex-column sub-menu">
<li class="nav-item">
{% if data['crafty_permissions']['Server_Creation'] in data['user_crafty_permissions'] %}
<li class="nav-item">
<a class="nav-link" href="/server/step1"><i class="fas fa-plus-circle"></i> &nbsp; {{ translate('sidebar', 'newServer') }}</a>
</li>
{% end %}
{% for s in data['menu_servers'] %}
<li class="nav-item">
<a class="nav-link" href="/panel/server_detail?id={{s['server_id']}}"><i class="fas fa-server"></i> &nbsp; {{s['server_name']}}</a>

View File

@ -121,6 +121,42 @@
</div>
<!-- Put Permissions Crafty part here -->
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-user-lock"></i> Crafty Permissions <small class="text-muted ml-1"> - permissions this user has on Crafty Controller </small></h4>
</div>
<div class="card-body">
<div class="form-group">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr class="rounded">
<th>Permission Name</th>
<th>Authorized ?</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
{% for permission in data['permissions_all'] %}
<tr>
<td>{{ permission.name }}</td>
<td>
{% if permission in data['permissions_list'] %}
<input type="checkbox" class="" id="permission_{{ permission.name }}" name="permission_{{ permission.name }}" checked="" value="1">
{% else %}
<input type="checkbox" class="" id="permission_{{ permission.name }}" name="permission_{{ permission.name }}" value="1">
{% end %}
</td>
<td><input type="text" class="form-control" name="quantity_{{ permission.name }}" id="quantity_{{ permission.name }}" value="{{ data['quantity_server'][permission.name] }}"></td>
</tr>
{% end %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="form-check-flat">
<label for="enabled" class="form-check-label ml-4 mb-4">

View File

@ -0,0 +1,18 @@
# Generated by database migrator
import peewee
def migrate(migrator, database, **kwargs):
migrator.add_columns('user_crafty', limit_user_creation=peewee.IntegerField(default=0))
migrator.add_columns('user_crafty', limit_role_creation=peewee.IntegerField(default=0))
"""
Write your migrations here.
"""
def rollback(migrator, database, **kwargs):
migrator.drop_columns('user_crafty', ['limit_user_creation'])
migrator.drop_columns('user_crafty', ['limit_role_creation'])
"""
Write your rollback migrations here.
"""