Merge branch 'dev' of gitlab.com:crafty-controller/crafty-commander into dev

This commit is contained in:
luukas 2021-11-02 17:00:58 +02:00
commit 2e1a5c8895
12 changed files with 165 additions and 155 deletions

View File

@ -27,20 +27,20 @@ class Crafty_Perms_Controller:
def list_defined_crafty_permissions():
permissions_list = crafty_permissions.get_permissions_list()
return permissions_list
@staticmethod
def get_mask_crafty_permissions(user_id):
permissions_mask = crafty_permissions.get_crafty_permissions_mask(user_id)
return permissions_mask
@staticmethod
def set_permission(permission_mask, permission_tested: Enum_Permissions_Crafty, value):
return crafty_permissions.set_permission(permission_mask, permission_tested, value)
@staticmethod
def can_create_server(user_id):
return crafty_permissions.can_add_in_crafty(user_id, Enum_Permissions_Crafty.Server_Creation)
@staticmethod
def can_add_user(user_id):
#TODO: Complete if we need a User Addition limit
@ -60,10 +60,13 @@ class Crafty_Perms_Controller:
@staticmethod
def list_crafty_permissions_quantity_limits(user_id):
return crafty_permissions.get_permission_quantity_list(user_id)
@staticmethod
def get_crafty_permissions_list(user_id):
permissions_mask = crafty_permissions.get_crafty_permissions_mask(user_id)
permissions_list = crafty_permissions.get_permissions(permissions_mask)
return permissions_list
@staticmethod
def add_server_creation(user_id):
return crafty_permissions.add_server_creation(user_id)

View File

@ -26,7 +26,7 @@ database = SqliteDatabase(helper.db_path, pragmas={
'journal_mode': 'wal',
'cache_size': -1024 * 10})
#************************************************************************************************
# User_Crafty Class
#************************************************************************************************
@ -89,7 +89,7 @@ class Permissions_Crafty:
@staticmethod
def get_permission(permission_mask, permission_tested: Enum_Permissions_Crafty):
return permission_mask[permission_tested.value]
@staticmethod
def get_crafty_permissions_mask(user_id):
permissions_mask = ''
@ -115,7 +115,7 @@ class Permissions_Crafty:
Enum_Permissions_Crafty.Roles_Config.name: user_crafty.limit_role_creation,
}
return quantity_list
#************************************************************************************************
# User_Crafty Methods
#************************************************************************************************
@ -141,7 +141,7 @@ class Permissions_Crafty:
def add_user_crafty(user_id, uc_permissions):
user_crafty = User_Crafty.insert({User_Crafty.user_id: user_id, User_Crafty.permissions: uc_permissions}).execute()
return user_crafty
@staticmethod
def add_or_update_user(user_id, permissions_mask, limit_server_creation, limit_user_creation, limit_role_creation):
try:
@ -159,7 +159,7 @@ class Permissions_Crafty:
User_Crafty.limit_user_creation: limit_user_creation,
User_Crafty.limit_role_creation: limit_role_creation
}).execute()
@staticmethod
def get_created_quantity_list(user_id):
user_crafty = crafty_permissions.get_User_Crafty(user_id)
@ -173,7 +173,7 @@ class Permissions_Crafty:
@staticmethod
def get_crafty_limit_value(user_id, permission):
user_crafty = crafty_permissions.get_User_Crafty(user_id)
quantity_list = get_permission_quantity_list(user_id)
quantity_list = crafty_permissions.get_permission_quantity_list(user_id)
return quantity_list[permission]
@staticmethod
@ -189,6 +189,6 @@ class Permissions_Crafty:
user_crafty = crafty_permissions.get_User_Crafty(user_id)
user_crafty.created_server += 1
User_Crafty.save(user_crafty)
return user_crafty.created_server
return user_crafty.created_server
crafty_permissions = Permissions_Crafty()

View File

@ -46,7 +46,7 @@ class Users(Model):
class Meta:
table_name = "users"
database = database
#************************************************************************************************
# User Roles Class
#************************************************************************************************
@ -63,7 +63,7 @@ class User_Roles(Model):
# Users Helpers
#************************************************************************************************
class helper_users:
@staticmethod
def get_by_id(user_id):
return Users.get_by_id(user_id)
@ -97,12 +97,12 @@ class helper_users:
return user
else:
return {}
@staticmethod
def user_query(user_id):
user_query = Users.select().where(Users.user_id == user_id)
return user_query
@staticmethod
def get_user(user_id):
if user_id == 0:
@ -168,7 +168,7 @@ class helper_users:
if not users_helper.get_user(user_id):
return False
return True
@staticmethod
def new_api_token():
while True:
@ -176,7 +176,7 @@ class helper_users:
test = list(Users.select(Users.user_id).where(Users.api_token == token))
if len(test) == 0:
return token
#************************************************************************************************
# User_Roles Methods
#************************************************************************************************
@ -216,7 +216,7 @@ class helper_users:
user_id = user.user_id
# I just copied this code from get_user, it had those TODOs & comments made by mac - Lukas
roles_query = User_Roles.select().join(Roles, JOIN.INNER).where(User_Roles.user_id == user_id)
# TODO: this query needs to be narrower
roles = set()
@ -226,13 +226,13 @@ class helper_users:
user['roles'] = roles
#logger.debug("user: ({}) {}".format(user_id, user))
return user
@staticmethod
def user_role_query(user_id):
user_query = User_Roles.select().where(User_Roles.user_id == user_id)
query = Roles.select().where(Roles.role_id == -1)
for u in user_query:
query = Roles.select().where(Roles.role_id == u.role_id)
query = query + Roles.select().where(Roles.role_id == u.role_id)
return query
@staticmethod

View File

@ -1,71 +1,71 @@
from app.classes.shared.helpers import helper
from app.classes.shared.console import console
import os
import json
import logging
logger = logging.getLogger(__name__)
class Translation():
def __init__(self):
self.translations_path = os.path.join(helper.root_dir, 'app', 'translations')
self.cached_translation = None
self.cached_translation_lang = None
self.lang_file_exists = []
def translate(self, page, word, lang):
translated_word = None
fallback_lang = 'en_EN'
if lang not in self.lang_file_exists and \
helper.check_file_exists(os.path.join(self.translations_path, lang + '.json')):
self.lang_file_exists.append(lang)
translated_word = self.translate_inner(page, word, lang) \
if lang in self.lang_file_exists else self.translate_inner(page, word, fallback_lang)
if translated_word:
if isinstance(translated_word, dict): return json.dumps(translated_word)
elif iter(translated_word) and not isinstance(translated_word, str): return '\n'.join(translated_word)
return translated_word
return 'Error while getting translation'
def translate_inner(self, page, word, lang):
lang_file = os.path.join(
self.translations_path,
lang + '.json'
)
try:
if not self.cached_translation:
with open(lang_file, 'r') as f:
data = json.load(f)
self.cached_translation = data
elif self.cached_translation_lang != lang:
with open(lang_file, 'r') as f:
data = json.load(f)
self.cached_translation = data
self.cached_translation_lang = lang
else:
data = self.cached_translation
try:
translated_page = data[page]
except KeyError:
logger.error('Translation File Error: page {} does not exist for lang {}'.format(page, lang))
console.error('Translation File Error: page {} does not exist for lang {}'.format(page, lang))
return None
try:
translated_word = translated_page[word]
return translated_word
except KeyError:
logger.error('Translation File Error: word {} does not exist on page {} for lang {}'.format(word, page, lang))
console.error('Translation File Error: word {} does not exist on page {} for lang {}'.format(word, page, lang))
return None
except Exception as e:
logger.critical('Translation File Error: Unable to read {} due to {}'.format(lang_file, e))
console.critical('Translation File Error: Unable to read {} due to {}'.format(lang_file, e))
return None
from app.classes.shared.helpers import helper
from app.classes.shared.console import console
import os
import json
import logging
logger = logging.getLogger(__name__)
class Translation():
def __init__(self):
self.translations_path = os.path.join(helper.root_dir, 'app', 'translations')
self.cached_translation = None
self.cached_translation_lang = None
self.lang_file_exists = []
def translate(self, page, word, lang):
translated_word = None
fallback_lang = 'en_EN'
if lang not in self.lang_file_exists and \
helper.check_file_exists(os.path.join(self.translations_path, str(lang) + '.json')):
self.lang_file_exists.append(lang)
translated_word = self.translate_inner(page, word, lang) \
if lang in self.lang_file_exists else self.translate_inner(page, word, fallback_lang)
if translated_word:
if isinstance(translated_word, dict): return json.dumps(translated_word)
elif iter(translated_word) and not isinstance(translated_word, str): return '\n'.join(translated_word)
return translated_word
return 'Error while getting translation'
def translate_inner(self, page, word, lang):
lang_file = os.path.join(
self.translations_path,
lang + '.json'
)
try:
if not self.cached_translation:
with open(lang_file, 'r', encoding='utf-8') as f:
data = json.load(f)
self.cached_translation = data
elif self.cached_translation_lang != lang:
with open(lang_file, 'r', encoding='utf-8') as f:
data = json.load(f)
self.cached_translation = data
self.cached_translation_lang = lang
else:
data = self.cached_translation
try:
translated_page = data[page]
except KeyError:
logger.error('Translation File Error: page {} does not exist for lang {}'.format(page, lang))
console.error('Translation File Error: page {} does not exist for lang {}'.format(page, lang))
return None
try:
translated_word = translated_page[word]
return translated_word
except KeyError:
logger.error('Translation File Error: word {} does not exist on page {} for lang {}'.format(word, page, lang))
console.error('Translation File Error: word {} does not exist on page {} for lang {}'.format(word, page, lang))
return None
except Exception as e:
logger.critical('Translation File Error: Unable to read {} due to {}'.format(lang_file, e))
console.critical('Translation File Error: Unable to read {} due to {}'.format(lang_file, e))
return None
translation = Translation()

View File

@ -129,15 +129,21 @@ class PanelHandler(BaseHandler):
user_auth = self.controller.servers.get_authorized_servers_stats(exec_user_id)
logger.debug("ASFR: {}".format(user_auth))
page_data['servers'] = user_auth
page_data['server_stats']['running'] = 0
page_data['server_stats']['stopped'] = 0
for data in page_data['servers']:
if data['stats']['running']:
page_data['server_stats']['running'] += 1
else:
page_data['server_stats']['stopped'] += 1
try:
data['stats']['waiting_start'] = self.controller.servers.get_waiting_start(int(data['stats']['server_id']['server_id']))
page_data['stats']['waiting_start'] = self.controller.servers.get_waiting_start(int(data['stats']['server_id']['server_id']))
except:
data['stats']['waiting_start'] = False
total_players = 0
for server in self.controller.servers.get_all_defined_servers():
total_players += len(self.controller.stats.get_server_players(server['server_id']))
for server in page_data['servers']:
total_players += len(self.controller.stats.get_server_players(server['server_data']['server_id']))
page_data['num_players'] = total_players
for s in page_data['servers']:
@ -303,7 +309,6 @@ class PanelHandler(BaseHandler):
users_list = []
role_users = {}
roles = self.controller.roles.get_all_roles()
role_servers = []
user_roles = {}
for user in self.controller.users.get_all_users():
user_roles_list = self.controller.users.get_user_roles_names(user.user_id)

View File

@ -45,7 +45,8 @@ class PublicHandler(BaseHandler):
'version': helper.get_version_string(),
'error': error
}
page_data['lang'] = helper.get_setting('language')
page_data['lang'] = tornado.locale.get("en_EN")
# sensible defaults
template = "public/404.html"

View File

@ -32,7 +32,7 @@ class ServerHandler(BaseHandler):
exec_user_data = json.loads(self.get_secure_cookie("user_data"))
exec_user_id = exec_user_data['user_id']
exec_user = self.controller.users.get_user_by_id(exec_user_id)
exec_user_role = set()
if exec_user['superuser'] == 1:
defined_servers = self.controller.list_defined_servers()
@ -64,17 +64,12 @@ class ServerHandler(BaseHandler):
},
'hosts_data': self.controller.management.get_latest_hosts_stats(),
'menu_servers': defined_servers,
'show_contribute': helper.get_setting("show_contribute_link", True)
'show_contribute': helper.get_setting("show_contribute_link", True),
'lang': self.controller.users.get_user_lang_by_id(exec_user_id)
}
page_data['lang'] = self.controller.users.get_user_lang_by_id(exec_user_id)
if page == "step1":
if len(self.controller.users.get_user_roles_id(exec_user_id)) <= 0:
self.redirect("/panel/error?error=Unauthorized access: you must have a role to create a server.")
return
elif not exec_user['superuser'] and not self.controller.crafty_perms.can_create_server(exec_user_id):
if not exec_user['superuser'] and not self.controller.crafty_perms.can_create_server(exec_user_id):
self.redirect("/panel/error?error=Unauthorized access: not a server creator or server limit reached")
return
@ -99,7 +94,8 @@ class ServerHandler(BaseHandler):
page_data = {
'version_data': "version_data_here",
'user_data': exec_user_data,
'show_contribute': helper.get_setting("show_contribute_link", True)
'show_contribute': helper.get_setting("show_contribute_link", True),
'lang': self.controller.users.get_user_lang_by_id(exec_user_id)
}
if page == "command":
@ -113,7 +109,7 @@ class ServerHandler(BaseHandler):
if server['server_name'] == name:
return True
return
server_data = self.controller.servers.get_server_data_by_id(server_id)
server_uuid = server_data.get('server_uuid')
new_server_name = server_data.get('server_name') + " (Copy)"
@ -146,7 +142,7 @@ class ServerHandler(BaseHandler):
self.controller.init_all_servers()
return
self.controller.management.send_command(exec_user_data['user_id'], server_id, self.get_remote_ip(), command)
if page == "step1":
@ -205,12 +201,13 @@ class ServerHandler(BaseHandler):
new_server_id,
self.get_remote_ip())
#These lines add the server to all the user's existing roles with full permissions
new_server_uuid = self.controller.servers.get_server_data_by_id(new_server_id).get("server_uuid")
for role_id in self.controller.users.get_user_roles_id(exec_user_id):
self.controller.server_perms.add_role_server(new_server_id, role_id, "11111111")
# These lines create a new Role for the Server with full permissions and add the user to it if he's not a superuser
if not exec_user['superuser']:
self.controller.server_perms.add_server_creation(exec_user_id)
new_server_uuid = self.controller.servers.get_server_data_by_id(new_server_id).get("server_uuid")
role_id = self.controller.roles.add_role("Creator of Server with uuid={}".format(new_server_uuid))
self.controller.server_perms.add_role_server(new_server_id, role_id, "11111111")
self.controller.users.add_role_to_user(exec_user_id, role_id)
self.controller.crafty_perms.add_server_creation(exec_user_id)
self.controller.stats.record_stats()
self.redirect("/panel/dashboard")

View File

@ -25,6 +25,7 @@ except ModuleNotFoundError as e:
class StatusHandler(BaseHandler):
def get(self):
page_data = {}
page_data['lang'] = tornado.locale.get("en_EN")
page_data['servers'] = self.controller.servers.get_all_servers_stats()
for srv in page_data['servers']:
server_data = srv.get('server_data', False)

View File

@ -135,7 +135,7 @@
<script src="/static/assets/js/shared/hoverable-collapse.js"></script>
<script src="/static/assets/js/shared/misc.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.22/fh-3.1.7/r-2.2.6/sc-2.0.3/sp-1.2.2/datatables.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootbox.js/5.4.0/bootbox.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/5.4.0/bootbox.min.js"></script>
<script>

View File

@ -32,7 +32,7 @@
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-users"></i> Users</h4>
<span class="too_small" title="{{ translate('dashboard', 'cannotSee', data['lang']) }}", data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}", data-placement="top"></span>
<div><a class="nav-link" href="/panel/add_user"><i class="fas fa-plus-circle"></i> &nbsp; Add New User</a></div>
</div>
<div class="card-body">
@ -52,7 +52,7 @@
{% for user in data['users'] %}
<tr>
<td><i class="fas fa-user"></i> {{ user.username }}</td>
<td style="max-width: 30px;">
<td>
{% if user.enabled %}
<span class="text-success">
<i class="fas fa-check-square"></i> Yes
@ -63,23 +63,27 @@
</span>
{% end %}
</td>
<td style="max-width: 30px;"><button data-toggle="tooltip" title="Show API Key" data-id="{{ user.api_token }}" type="button" class="btn btn-info show_button">Show</button></td>
<td class="server_list_{{user.user_id}}"><ul id="{{user.user_id}}">
{% for item in data['auth-servers'][user.user_id] %}
<li>{{item}}</li>
{% end %}
</ul></td>
<td class="role_list_{{user.user_id}}" style="max-width: 100px; overflow: scroll;"><ul>
<td>
<button data-toggle="tooltip" title="Show API Key" data-id="{{ user.api_token }}" type="button" class="btn btn-info show_button">Show</button>
</td>
<td id="server_list_{{user.user_id}}">
<ul id="{{user.user_id}}">
{% for item in data['auth-servers'][user.user_id] %}
<li>{{item}}</li>
{% end %}
</ul>
</td>
<td id="role_list_{{user.user_id}}">
<ul>
{% for item in data['user-roles'][user.user_id] %}
<li data-toggle="tooltip" title="{{ item }}">{{item}}</li>
<li data-toggle="tooltip" title="{{ item }}">{{item}}</li>
{% end %}
</ul>
</td>
<td><a href="/panel/edit_user?id={{user.user_id}}"><i class="fas fa-pencil-alt"></i></a></td>
</tr>
{% end %}
</tbody>
</table>
</div>
@ -110,11 +114,13 @@
{% for role in data['roles'] %}
<tr>
<td>{{ role.role_name }}</td>
<td class="role_list_{{role.role_id}}"><ul id="{{role.role_id}}">
{% for item in data['role-servers'][role.role_id] %}
<li>{{item}}</li>
{% end %}
</ul></td>
<td id="role_list_{{role.role_id}}">
<ul id="{{role.role_id}}">
{% for item in data['role-servers'][role.role_id] %}
<li>{{item}}</li>
{% end %}
</ul>
</td>
<td><ul>
{% for user in data['users'] %}
{% for ruser in data['user-roles'][user.user_id] %}
@ -155,13 +161,13 @@
{% block js %}
<script>
$(document).ready(function(){
$(document).ready(function(){
$('[data-toggle="popover"]').popover();
if($(window).width() < 1000){
$('.too_small').popover("show");
$('.too_small2').popover("show");
}
});
$(window).ready(function(){
$('body').click(function(){

View File

@ -62,27 +62,27 @@
<input type="hidden" name="id" value="{{ data['user']['user_id'] }}">
<input type="hidden" name="subpage" value="config">
<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"></i> User Settings</h4>
</div>
<div class="card-body">
<div class="card-body">
<div class="form-group">
<label for="username">User Name <small class="text-muted ml-1"> - What you wish to call this user</small> </label>
<label class="form-label" for="username">User Name <small class="text-muted ml-1"> - What you wish to call this user</small> </label>
<input type="text" class="form-control" name="username" id="username" value="{{ data['user']['username'] }}" placeholder="User Name" >
</div>
<div class="form-group">
<label for="password0">Password <small class="text-muted ml-1"> - leave blank to don't change</small> </label>
<label class="form-label" for="password0">Password <small class="text-muted ml-1"> - leave blank to don't change</small> </label>
<input type="password" class="form-control" name="password0" id="password0" value="" placeholder="Password" >
</div>
<div class="form-group">
<label for="password1">Repeat Password <small class="text-muted ml-1"> - leave blank to don't change</small> </label>
<label class="form-label" for="password1">Repeat Password <small class="text-muted ml-1"> - leave blank to don't change</small> </label>
<input type="password" class="form-control" name="password1" id="password1" value="" placeholder="Repeat Password" >
</div>
<div class="form-group">
<label for="language">User Language:</label>
<select id="language" name="language" form="user_form">
<label class="form-label" for="language">User Language:</label>
<select class="form-select" id="language" name="language" form="user_form">
{% for lang in data['languages'] %}
<option value="{{lang}}">{{lang}}</option>
{% end %}
@ -90,9 +90,7 @@
</div>
</div>
</div>
{% if len(data['servers_all']) > 0 %}
<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-tag"></i> Roles <small class="text-muted ml-1"> - the roles this user is a member of</small></h4>
@ -113,9 +111,9 @@
<td>{{ role.role_name }}</td>
<td>
{% if role.role_id in data['user']['roles'] %}
<input type="checkbox" class="" id="role_{{ role.role_id }}_membership" name="role_{{ role.role_id }}_membership" checked="" value="1">
<input type="checkbox" class="form-check-input" id="role_{{ role.role_id }}_membership" name="role_{{ role.role_id }}_membership" checked="" value="1">
{% else %}
<input type="checkbox" class="" id="role_{{ role.role_id }}_membership" name="role_{{ role.role_id }}_membership" value="1">
<input type="checkbox" class="form-check-input" id="role_{{ role.role_id }}_membership" name="role_{{ role.role_id }}_membership" value="1">
{% end %}
</td>
@ -128,13 +126,13 @@
</div>
</div>
<!-- Put Permissions Crafty part here -->
<!-- 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="card-body">
<div class="form-group">
<div class="table-responsive">
<table class="table table-hover">
@ -151,9 +149,9 @@
<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">
<input type="checkbox" class="form-check-input" 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">
<input type="checkbox" class="form-check-input" 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>
@ -165,7 +163,6 @@
</div>
</div>
</div>
{% end %}
<div class="form-check-flat">
<label for="enabled" class="form-check-label ml-4 mb-4">
@ -193,7 +190,7 @@
</label>
</div>
<button type="submit" class="btn btn-success mr-2"><i class="fas fa-save"></i> {{ translate('panelConfig', 'save', data['lang']) }}</button>
<button type="reset" onclick="location.href='/panel/panel_config'" class="btn btn-light"><i class="fas fa-undo-alt"></i> {{ translate('panelConfig', 'cancel', data['lang']) }}</button>
</form>

View File

@ -53,7 +53,7 @@
</td>
{% end %}
<td>
{% if server['stats']['int_ping_results'] %}
{% if server['stats']['running'] %}
<span class="text-success"><i class="fas fa-signal"></i> {{ translate('dashboard', 'online', data['lang']) }}</span>
{% else %}
<span class="text-danger"><i class="fas fa-ban"></i> {{ translate('dashboard', 'offline', data['lang']) }}</span>