diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
index 88b2a3b4..77136b69 100644
--- a/.gitlab/issue_templates/Bug.md
+++ b/.gitlab/issue_templates/Bug.md
@@ -3,16 +3,16 @@
- **Install Type:** Git Cloned(Manual) / Installer / WinPackage / Docker
## What Happened?
-*A brief description of what happened when you tried to perform an action*
+
## Expected result
-*What should have happened when you performed the actions*
+
## Steps to reproduce
-*List the steps required to produce the error. These should be as few as possible*
+
## Screenshots
-Any relevant screenshots which show the issue* !-->*
+
## Priority/Severity
- [ ] High (anything that impacts the normal user flow or blocks app usage)
diff --git a/.gitlab/issue_templates/Change Request.md b/.gitlab/issue_templates/Change Request.md
index 995e7ad1..f767ee15 100644
--- a/.gitlab/issue_templates/Change Request.md
+++ b/.gitlab/issue_templates/Change Request.md
@@ -1,13 +1,14 @@
## Summary
-*Outline the issue being faced, and why this needs to change*
+
## Area of the system
-*This might only be one part, but may involve multiple sections, Login/Dashboad/Terminal/Config*
+
## How does this currently work?
+
## What is the desired way of working?
-*After the change, what should the process/operation be?*
+
## Priority/Severity
- [ ] High (This will bring a huge increase in performance/productivity/usability)
diff --git a/.gitlab/issue_templates/Feature Request.md b/.gitlab/issue_templates/Feature Request.md
index 2450aa60..b26067d6 100644
--- a/.gitlab/issue_templates/Feature Request.md
+++ b/.gitlab/issue_templates/Feature Request.md
@@ -1,8 +1,8 @@
## Problem Statement
-*What is the issue being faced and needs addressing?*
+
## Who will benefit?
-*Will this fix a problem that only one user has, or will it benefit a lot of people*
+
## Benefits and risks
What benefits does this bring?
@@ -16,10 +16,10 @@
## Proposed solution
-*How would you like to see this issue resolved?*
+
## Examples
-*Are there any examples of this which exist in other software?*
+
## Priority/Severity
- [ ] High (This will bring a huge increase in performance/productivity/usability)
diff --git a/.gitlab/lint.yml b/.gitlab/lint.yml
index bc797808..37649e1a 100644
--- a/.gitlab/lint.yml
+++ b/.gitlab/lint.yml
@@ -5,7 +5,7 @@ yamllint:
stage: lint
image: registry.gitlab.com/pipeline-components/yamllint:latest
tags:
- - docker
+ - saas-linux-medium-amd64
rules:
- if: "$CODE_QUALITY_DISABLED"
when: never
@@ -18,7 +18,7 @@ jsonlint:
stage: lint
image: registry.gitlab.com/pipeline-components/jsonlint:latest
tags:
- - docker
+ - saas-linux-medium-amd64
rules:
- if: "$CODE_QUALITY_DISABLED"
when: never
@@ -33,7 +33,7 @@ black:
stage: lint
image: registry.gitlab.com/pipeline-components/black:latest
tags:
- - docker
+ - saas-linux-medium-amd64
rules:
- if: "$CODE_QUALITY_DISABLED"
when: never
@@ -46,7 +46,7 @@ pylint:
stage: lint
image: registry.gitlab.com/pipeline-components/pylint:latest
tags:
- - docker
+ - saas-linux-medium-amd64
rules:
- if: "$CODE_QUALITY_DISABLED"
when: never
@@ -69,7 +69,7 @@ sonarcloud-check:
name: sonarsource/sonar-scanner-cli:latest
entrypoint: [""]
tags:
- - docker
+ - saas-linux-medium-amd64
rules:
- if: "$SONAR_TOKEN == null"
when: never
@@ -91,7 +91,7 @@ lang-check:
stage: lint
image: alpine:latest
tags:
- - docker
+ - saas-linux-medium-amd64
rules:
- if: "$CODE_QUALITY_DISABLED"
when: never
diff --git a/.gitlab/merge_request_templates/Default.md b/.gitlab/merge_request_templates/Default.md
index a82cb3f8..70bcd7db 100644
--- a/.gitlab/merge_request_templates/Default.md
+++ b/.gitlab/merge_request_templates/Default.md
@@ -1,22 +1,22 @@
## What does this MR do and why?
-___Describe in detail what your merge request does and why.___
-> *Please keep this description updated with any discussion that takes place so*
-*that reviewers can understand your intent. Keeping the description updated is*
-*especially important if they didn't participate in the discussion.*
+
+
+
+
## Screenshots or screen recordings
-___These are strongly recommended to assist reviewers and reduce the time to merge your change.___
-> *Please include any relevant screenshots or screen recordings that will assist*
-*reviewers and future readers. If you need help visually verifying the change,*
-*please leave a comment and ping a GitLab reviewer, maintainer, or MR coach.*
+
+
+
+
## How to set up and validate locally
-___Numbered steps to set up and validate the change are strongly suggested.___
+
## MR acceptance checklist
diff --git a/.gitlab/scripts/linux_perms_fix.sh b/.gitlab/scripts/linux_perms_fix.sh
index 24b92176..d727b16b 100644
--- a/.gitlab/scripts/linux_perms_fix.sh
+++ b/.gitlab/scripts/linux_perms_fix.sh
@@ -3,13 +3,46 @@
# Prompt the user for the directory path
read -p "Enter the directory path to set permissions (/var/opt/minecraft/crafty): " directory_path
+# Count the total number of directories
+total_dirs=$(find "$directory_path" -type d 2>/dev/null | wc -l)
+
+# Count the total number of files
+total_files=$(find "$directory_path" -type f 2>/dev/null | wc -l)
+
+# Initialize a counter for directories and files
+dir_count=0
+file_count=0
+
+# Function to print progress
+print_progress() {
+ echo -ne "\rDirectories: $dir_count/$total_dirs Files: $file_count/$total_files"
+}
+
# Check if the script is running within a Docker container
if [ -f "/.dockerenv" ]; then
echo "Script is running within a Docker container. Exiting with error."
exit 1 # Exit with an error code if running in Docker
else
echo "Script is not running within a Docker container. Executing permissions changes..."
- # Run the commands to set permissions
- sudo chmod 700 $(find "$directory_path" -type d)
- sudo chmod 644 $(find "$directory_path" -type f)
-fi
\ No newline at end of file
+
+ # Run the commands to set permissions for directories
+ echo "Changing permissions for directories:"
+ for dir in $(find "$directory_path" -type d 2>/dev/null); do
+ if [ -e "$dir" ]; then
+ sudo chmod 700 "$dir" && ((dir_count++))
+ fi
+ print_progress
+ done
+
+ # Run the commands to set permissions for files
+ echo -e "\nChanging permissions for files:"
+ for file in $(find "$directory_path" -type f 2>/dev/null); do
+ if [ -e "$file" ]; then
+ sudo chmod 644 "$file" && ((file_count++))
+ fi
+ print_progress
+ done
+ echo "You will now need to execute a chmod +x on all bedrock executables"
+fi
+
+echo "" # Adding a new line after the loop for better readability
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 44750a39..cdc9d383 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,35 @@
# Changelog
-## --- [4.3.2] - 2024/TBD
+## --- [4.3.3] - 2024/TBD
+### Refactor
+- Refactor API keys "super user" to "full access" ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/731))
### New features
TBD
### Bug fixes
TBD
### Tweaks
-TBD
+- Add link to go back to dashboard on error page ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/743))
### Lang
TBD
+## --- [4.3.2] - 2024/04/07
+### Refactor
+- Refactor ServerJars caching and move to api.serverjars.com ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/744) | [Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/746))
+### Bug fixes
+- Fix migrator issue when jumping versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/734))
+- Fix backend issue causing error when restoring backups in 4.3.x ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/736))
+- Fix backend issue causing error when cloning servers in 4.3.x ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/741))
+- Bump orjson for CVE-2024-27454 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/747))
+- Fix calling of orjson JSONDecodeError class ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/747))
+- Fix stack on Crafty permissions route request in API ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/745))
+### Tweaks
+- Clean up remaining http handler references ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/733))
+- Remove version disclosure on login page ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/737))
+- Add openjdk-21 for recent versions of MC ([Commit](https://gitlab.com/crafty-controller/crafty-4/-/commit/77b0c2c9d2eac124a7504a3d3916fa22d29fa9d1))
+### Lang
+- Update `it_IT, cs_CS` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/739) | [Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/742))
+
+
## --- [4.3.1] - 2024/03/18
### Bug fixes
- Fix Server ID Rework for backups, schedules, and roles (INT ID to UUID migration) ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/729))
diff --git a/Dockerfile b/Dockerfile
index e8bdb102..d05cf3d0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -25,6 +25,7 @@ RUN apt-get update \
openjdk-8-jre-headless \
openjdk-11-jre-headless \
openjdk-17-jre-headless \
+ openjdk-21-jre-headless \
tzdata \
&& apt-get autoremove \
&& apt-get clean
diff --git a/README.md b/README.md
index ae70bd0e..64e26224 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
[![Crafty Logo](app/frontend/static/assets/images/logo_long.svg)](https://craftycontrol.com)
-# Crafty Controller 4.3.2
+# Crafty Controller 4.3.3
> Python based Control Panel for your Minecraft Server
## What is Crafty Controller?
diff --git a/app/classes/controllers/server_perms_controller.py b/app/classes/controllers/server_perms_controller.py
index f6632cd7..4586b4aa 100644
--- a/app/classes/controllers/server_perms_controller.py
+++ b/app/classes/controllers/server_perms_controller.py
@@ -17,6 +17,10 @@ class ServerPermsController:
def get_server_user_list(server_id):
return PermissionsServers.get_server_user_list(server_id)
+ @staticmethod
+ def get_permissions(permissions_mask):
+ return PermissionsServers.get_permissions(permissions_mask)
+
@staticmethod
def list_defined_permissions():
permissions_list = PermissionsServers.get_permissions_list()
@@ -47,7 +51,7 @@ class ServerPermsController:
new_server_id,
role.role_id,
PermissionsServers.get_permissions_mask(
- int(role.role_id), int(old_server_id)
+ int(role.role_id), old_server_id
),
)
# Permissions_Servers.add_role_server(
@@ -61,6 +65,22 @@ class ServerPermsController:
def get_permissions_mask(role_id, server_id):
return PermissionsServers.get_permissions_mask(role_id, server_id)
+ @staticmethod
+ def get_lowest_api_perm_mask(user_server_permissions_mask, api_key_permssions_mask):
+ mask = ""
+ # If this isn't an API key we'll know the request came from basic
+ # authentication and ignore the API key permissions mask.
+ if not api_key_permssions_mask:
+ return user_server_permissions_mask
+ for _index, (user_perm, api_perm) in enumerate(
+ zip(user_server_permissions_mask, api_key_permssions_mask)
+ ):
+ if user_perm == "1" and api_perm == "1":
+ mask += "1"
+ else:
+ mask += "0"
+ return mask
+
@staticmethod
def set_permission(
permission_mask, permission_tested: EnumPermissionsServer, value
@@ -82,6 +102,11 @@ class ServerPermsController:
def get_api_key_permissions_list(key: ApiKeys, server_id: str):
return PermissionsServers.get_api_key_permissions_list(key, server_id)
+ @staticmethod
+ def get_user_permissions_mask(user_id: str, server_id: str):
+ user = HelperUsers.get_user_model(user_id)
+ return PermissionsServers.get_user_permissions_mask(user, server_id)
+
@staticmethod
def get_authorized_servers_stats_from_roles(user_id):
user_roles = HelperUsers.get_user_roles_id(user_id)
diff --git a/app/classes/minecraft/serverjars.py b/app/classes/minecraft/serverjars.py
index 83731b52..944ec382 100644
--- a/app/classes/minecraft/serverjars.py
+++ b/app/classes/minecraft/serverjars.py
@@ -12,13 +12,15 @@ from app.classes.shared.file_helpers import FileHelpers
from app.classes.shared.websocket_manager import WebSocketManager
logger = logging.getLogger(__name__)
+# Temp type var until sjars restores generic fetchTypes0
+SERVERJARS_TYPES = ["modded", "proxies", "servers", "vanilla"]
PAPERJARS = ["paper", "folia"]
class ServerJars:
def __init__(self, helper):
self.helper = helper
- self.base_url = "https://serverjars.com"
+ self.base_url = "https://api.serverjars.com"
self.paper_base = "https://api.papermc.io"
@staticmethod
@@ -82,6 +84,183 @@ class ServerJars:
builds = api_data.get("builds", [])
return builds[-1] if builds else None
+ def _read_cache(self):
+ cache_file = self.helper.serverjar_cache
+ cache = {}
+ try:
+ with open(cache_file, "r", encoding="utf-8") as f:
+ cache = json.load(f)
+
+ except Exception as e:
+ logger.error(f"Unable to read serverjars.com cache file: {e}")
+
+ return cache
+
+ def get_serverjar_data(self):
+ data = self._read_cache()
+ return data.get("types")
+
+ def _check_sjars_api_alive(self):
+ logger.info("Checking serverjars.com API status")
+
+ check_url = f"{self.base_url}"
+ try:
+ response = requests.get(check_url, timeout=2)
+ response_json = response.json()
+
+ if (
+ response.status_code in [200, 201]
+ and response_json.get("status") == "success"
+ and response_json.get("response", {}).get("status") == "ok"
+ ):
+ logger.info("Serverjars.com API is alive and responding as expected")
+ return True
+ except Exception as e:
+ logger.error(f"Unable to connect to serverjar.com API due to error: {e}")
+ return False
+
+ logger.error(
+ "Serverjars.com API is not responding as expected or unable to contact"
+ )
+ return False
+
+ def _fetch_projects_for_type(self, server_type):
+ """
+ Fetches projects for a given server type from the ServerJars API.
+ """
+ try:
+ response = requests.get(
+ f"{self.base_url}/api/fetchTypes/{server_type}", timeout=5
+ )
+ response.raise_for_status() # Ensure HTTP errors are caught
+ data = response.json()
+ if data.get("status") == "success":
+ return data["response"].get("servers", [])
+ except requests.RequestException as e:
+ print(f"Error fetching projects for type {server_type}: {e}")
+ return []
+
+ def _get_server_type_list(self):
+ """
+ Builds the type structure with projects fetched for each type.
+ """
+ type_structure = {}
+ for server_type in SERVERJARS_TYPES:
+ projects = self._fetch_projects_for_type(server_type)
+ type_structure[server_type] = {project: [] for project in projects}
+ return type_structure
+
+ def _get_jar_versions(self, server_type, project_name, max_ver=50):
+ """
+ Grabs available versions for specified project
+
+ Args:
+ server_type (str): Server Type Category (modded, servers, etc)
+ project_name (str): Target project (paper, forge, magma, etc)
+ max (int, optional): Max versions returned. Defaults to 50.
+
+ Returns:
+ list: An array of versions
+ """
+ url = f"{self.base_url}/api/fetchAll/{server_type}/{project_name}?max={max_ver}"
+ try:
+ response = requests.get(url, timeout=5)
+ response.raise_for_status() # Ensure HTTP errors are caught
+ data = response.json()
+ logger.debug(f"Received data for {server_type}/{project_name}: {data}")
+
+ if data.get("status") == "success":
+ versions = [
+ item.get("version")
+ for item in data.get("response", [])
+ if "version" in item
+ ]
+ versions.reverse() # Reverse so versions are newest -> oldest
+ logger.debug(f"Versions extracted: {versions}")
+ return versions
+ except requests.RequestException as e:
+ logger.error(
+ f"Error fetching jar versions for {server_type}/{project_name}: {e}"
+ )
+
+ return []
+
+ def _refresh_cache(self):
+ """
+ Contains the shared logic for refreshing the cache.
+ This method is called by both manual_refresh_cache and refresh_cache methods.
+ """
+ now = datetime.now()
+ cache_data = {
+ "last_refreshed": now.strftime("%m/%d/%Y, %H:%M:%S"),
+ "types": self._get_server_type_list(),
+ }
+
+ for server_type, projects in cache_data["types"].items():
+ for project_name in projects:
+ versions = self._get_jar_versions(server_type, project_name)
+ cache_data["types"][server_type][project_name] = versions
+
+ for paper_project in PAPERJARS:
+ cache_data["types"]["servers"][paper_project] = self.get_paper_versions(
+ paper_project
+ )
+
+ return cache_data
+
+ def manual_refresh_cache(self):
+ """
+ Manually triggers the cache refresh process.
+ """
+ if not self._check_sjars_api_alive():
+ logger.error("ServerJars API is not available.")
+ return False
+
+ logger.info("Manual cache refresh requested.")
+ cache_data = self._refresh_cache()
+
+ # Save the updated cache data
+ try:
+ with open(self.helper.serverjar_cache, "w", encoding="utf-8") as cache_file:
+ json.dump(cache_data, cache_file, indent=4)
+ logger.info("Cache file successfully refreshed manually.")
+ except Exception as e:
+ logger.error(f"Failed to update cache file manually: {e}")
+
+ def refresh_cache(self):
+ """
+ Automatically trigger cache refresh process based age.
+
+ This method checks if the cache file is older than a specified number of days
+ before deciding to refresh.
+ """
+ cache_file_path = self.helper.serverjar_cache
+
+ # Determine if the cache is old and needs refreshing
+ cache_old = self.helper.is_file_older_than_x_days(cache_file_path)
+
+ # debug override
+ # cache_old = True
+
+ if not self._check_sjars_api_alive():
+ logger.error("ServerJars API is not available.")
+ return False
+
+ if not cache_old:
+ logger.info("Cache file is not old enough to require automatic refresh.")
+ return False
+
+ logger.info("Automatic cache refresh initiated due to old cache.")
+ cache_data = self._refresh_cache()
+
+ # Save the updated cache data
+ try:
+ with open(cache_file_path, "w", encoding="utf-8") as cache_file:
+ json.dump(cache_data, cache_file, indent=4)
+ logger.info("Cache file successfully refreshed automatically.")
+ except Exception as e:
+ logger.error(f"Failed to update cache file automatically: {e}")
+
def get_fetch_url(self, jar, server, version):
"""
Constructs the URL for downloading a server JAR file based on the server type.
@@ -132,151 +311,6 @@ class ServerJars:
logger.error(f"An error occurred while constructing fetch URL: {e}")
return None
- def _get_api_result(self, call_url: str):
- full_url = f"{self.base_url}{call_url}"
-
- try:
- response = requests.get(full_url, timeout=2)
- response.raise_for_status()
- api_data = json.loads(response.content)
- except Exception as e:
- logger.error(f"Unable to load {full_url} api due to error: {e}")
- return {}
-
- api_result = api_data.get("status")
- api_response = api_data.get("response", {})
-
- if api_result != "success":
- logger.error(f"Api returned a failed status: {api_result}")
- return {}
-
- return api_response
-
- def _read_cache(self):
- cache_file = self.helper.serverjar_cache
- cache = {}
- try:
- with open(cache_file, "r", encoding="utf-8") as f:
- cache = json.load(f)
-
- except Exception as e:
- logger.error(f"Unable to read serverjars.com cache file: {e}")
-
- return cache
-
- def get_serverjar_data(self):
- data = self._read_cache()
- return data.get("types")
-
- def _check_api_alive(self):
- logger.info("Checking serverjars.com API status")
-
- check_url = f"{self.base_url}/api/fetchTypes"
- try:
- response = requests.get(check_url, timeout=2)
-
- if response.status_code in [200, 201]:
- logger.info("Serverjars.com API is alive")
- return True
- except Exception as e:
- logger.error(f"Unable to connect to serverjar.com api due to error: {e}")
- return {}
-
- logger.error("unable to contact serverjars.com api")
- return False
-
- def manual_refresh_cache(self):
- cache_file = self.helper.serverjar_cache
-
- # debug override
- # cache_old = True
-
- # if the API is down... we bomb out
- if not self._check_api_alive():
- return False
-
- logger.info("Manual Refresh requested.")
- now = datetime.now()
- data = {
- "last_refreshed": now.strftime("%m/%d/%Y, %H:%M:%S"),
- "types": {},
- }
-
- jar_types = self._get_server_type_list()
- data["types"].update(jar_types)
- for s in data["types"]:
- data["types"].update({s: dict.fromkeys(data["types"].get(s), {})})
- for j in data["types"].get(s):
- versions = self._get_jar_details(j, s)
- data["types"][s].update({j: versions})
- for item in PAPERJARS:
- data["types"]["servers"][item] = self.get_paper_versions(item)
- # save our cache
- try:
- with open(cache_file, "w", encoding="utf-8") as f:
- f.write(json.dumps(data, indent=4))
- logger.info("Cache file refreshed")
-
- except Exception as e:
- logger.error(f"Unable to update serverjars.com cache file: {e}")
-
- def refresh_cache(self):
- cache_file = self.helper.serverjar_cache
- cache_old = self.helper.is_file_older_than_x_days(cache_file)
-
- # debug override
- # cache_old = True
-
- # if the API is down... we bomb out
- if not self._check_api_alive():
- return False
-
- logger.info("Checking Cache file age")
- # if file is older than 1 day
-
- if cache_old:
- logger.info("Cache file is over 1 day old, refreshing")
- now = datetime.now()
- data = {
- "last_refreshed": now.strftime("%m/%d/%Y, %H:%M:%S"),
- "types": {},
- }
-
- jar_types = self._get_server_type_list()
- data["types"].update(jar_types)
- for s in data["types"]:
- data["types"].update({s: dict.fromkeys(data["types"].get(s), {})})
- for j in data["types"].get(s):
- versions = self._get_jar_details(j, s)
- data["types"][s].update({j: versions})
- for item in PAPERJARS:
- data["types"]["servers"][item] = self.get_paper_versions(item)
- # save our cache
- try:
- with open(cache_file, "w", encoding="utf-8") as f:
- f.write(json.dumps(data, indent=4))
- logger.info("Cache file refreshed")
-
- except Exception as e:
- logger.error(f"Unable to update serverjars.com cache file: {e}")
-
- def _get_jar_details(self, server_type, jar_type="servers"):
- url = f"/api/fetchAll/{jar_type}/{server_type}"
- response = self._get_api_result(url)
- temp = []
- for v in response:
- temp.append(v.get("version"))
- time.sleep(0.5)
- return temp
-
- def _get_server_type_list(self):
- url = "/api/fetchTypes/"
- response = self._get_api_result(url)
- if "bedrock" in response.keys():
- # remove pocketmine from options
- del response["bedrock"]
- return response
-
def download_jar(self, jar, server, version, path, server_id):
update_thread = threading.Thread(
name=f"server_download-{server_id}-{server}-{version}",
diff --git a/app/classes/models/crafty_permissions.py b/app/classes/models/crafty_permissions.py
index 7430f332..e7a159d9 100644
--- a/app/classes/models/crafty_permissions.py
+++ b/app/classes/models/crafty_permissions.py
@@ -187,7 +187,7 @@ class PermissionsCrafty:
@staticmethod
def get_api_key_permissions_list(key: ApiKeys):
user = HelperUsers.get_user(key.user_id)
- if user["superuser"] and key.superuser:
+ if user["superuser"] and key.full_access:
return PermissionsCrafty.get_permissions_list()
if user["superuser"]:
# User is superuser but API key isn't
diff --git a/app/classes/models/server_permissions.py b/app/classes/models/server_permissions.py
index 56f9d8ac..12301e30 100644
--- a/app/classes/models/server_permissions.py
+++ b/app/classes/models/server_permissions.py
@@ -264,7 +264,7 @@ class PermissionsServers:
@staticmethod
def get_api_key_permissions_list(key: ApiKeys, server_id: str):
user = HelperUsers.get_user(key.user_id)
- if user["superuser"] and key.superuser:
+ if user["superuser"] and key.full_access:
return PermissionsServers.get_permissions_list()
roles_list = HelperUsers.get_user_roles_id(user["user_id"])
role_server = (
diff --git a/app/classes/models/users.py b/app/classes/models/users.py
index e44d06fb..3f96e651 100644
--- a/app/classes/models/users.py
+++ b/app/classes/models/users.py
@@ -71,7 +71,7 @@ class ApiKeys(BaseModel):
user_id = ForeignKeyField(Users, backref="api_token", index=True)
server_permissions = CharField(default="00000000")
crafty_permissions = CharField(default="000")
- superuser = BooleanField(default=False)
+ full_access = BooleanField(default=False)
class Meta:
table_name = "api_keys"
@@ -408,7 +408,7 @@ class HelperUsers:
def add_user_api_key(
name: str,
user_id: str,
- superuser: bool = False,
+ full_access: bool = False,
server_permissions_mask: t.Optional[str] = None,
crafty_permissions_mask: t.Optional[str] = None,
):
@@ -426,7 +426,7 @@ class HelperUsers:
if crafty_permissions_mask is not None
else {}
),
- ApiKeys.superuser: superuser,
+ ApiKeys.full_access: full_access,
}
).execute()
diff --git a/app/classes/shared/main_controller.py b/app/classes/shared/main_controller.py
index b6e824a5..9c3219ff 100644
--- a/app/classes/shared/main_controller.py
+++ b/app/classes/shared/main_controller.py
@@ -575,7 +575,7 @@ class Controller:
):
server_obj = self.servers.get_server_obj(new_server_id)
url = (
- "https://serverjars.com/api/fetchJar/"
+ "https://api.serverjars.com/api/fetchJar/"
f"{create_data['category']}"
f"/{create_data['type']}/{create_data['version']}"
)
@@ -1131,7 +1131,7 @@ class Controller:
server_obj.path = new_local_server_path
failed = False
for s in self.servers.failed_servers:
- if int(s["server_id"]) == int(server.get("server_id")):
+ if s["server_id"] == server.get("server_id"):
failed = True
if not failed:
self.servers.update_server(server_obj)
diff --git a/app/classes/shared/migration.py b/app/classes/shared/migration.py
index 6a93802b..287bb4f3 100644
--- a/app/classes/shared/migration.py
+++ b/app/classes/shared/migration.py
@@ -372,11 +372,11 @@ class MigrationManager(object):
Create migrator
"""
migrator = Migrator(self.database)
- # Removing the up_one to prevent running all
- # migrations each time we got a new one.
- # It's handled by migration.up() function.
- # for name in self.done:
- # self.up_one(name, migrator, True)
+ # Running false migrations to retrives the schemes of
+ # the precedents created tables in the table_dict element
+ # It's useful to run the new migrations
+ for name in self.done:
+ self.up_one(name, migrator, True)
return migrator
def compile(self, name, migrate="", rollback=""):
diff --git a/app/classes/web/base_handler.py b/app/classes/web/base_handler.py
index ced6cb97..7cca08e8 100644
--- a/app/classes/web/base_handler.py
+++ b/app/classes/web/base_handler.py
@@ -182,6 +182,7 @@ class BaseHandler(tornado.web.RequestHandler):
t.List[str],
bool,
t.Dict[str, t.Any],
+ str,
]
]:
try:
@@ -190,9 +191,10 @@ class BaseHandler(tornado.web.RequestHandler):
)
superuser = user["superuser"]
+ server_permissions_api_mask = ""
if api_key is not None:
- superuser = superuser and api_key.superuser
-
+ superuser = superuser and api_key.full_access
+ server_permissions_api_mask = api_key.server_permissions
exec_user_role = set()
if superuser:
authorized_servers = self.controller.servers.get_all_defined_servers()
@@ -214,6 +216,7 @@ class BaseHandler(tornado.web.RequestHandler):
user["user_id"]
)
)
+
logger.debug(user["roles"])
for r in user["roles"]:
role = self.controller.roles.get_role(r)
@@ -234,6 +237,7 @@ class BaseHandler(tornado.web.RequestHandler):
exec_user_role,
superuser,
user,
+ server_permissions_api_mask,
)
logging.debug("Auth unsuccessful")
auth_log.error(
diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py
index d61e3c0e..e1beb547 100644
--- a/app/classes/web/panel_handler.py
+++ b/app/classes/web/panel_handler.py
@@ -168,7 +168,7 @@ class PanelHandler(BaseHandler):
# Commented out because there is no server access control for API keys,
# they just inherit from the host user
# if api_key is not None:
- # superuser = superuser and api_key.superuser
+ # superuser = superuser and api_key.full_access
if server_id is None:
self.redirect("/panel/error?error=Invalid Server ID")
@@ -242,7 +242,7 @@ class PanelHandler(BaseHandler):
api_key, _token_data, exec_user = self.current_user
superuser = exec_user["superuser"]
if api_key is not None:
- superuser = superuser and api_key.superuser
+ superuser = superuser and api_key.full_access
if superuser: # TODO: Figure out a better solution
defined_servers = self.controller.servers.list_defined_servers()
@@ -351,7 +351,7 @@ class PanelHandler(BaseHandler):
"created": api_key.created,
"server_permissions": api_key.server_permissions,
"crafty_permissions": api_key.crafty_permissions,
- "superuser": api_key.superuser,
+ "full_access": api_key.full_access,
}
if api_key is not None
else None
@@ -1356,6 +1356,9 @@ class PanelHandler(BaseHandler):
page_data["crafty_permissions_all"] = (
self.controller.crafty_perms.list_defined_crafty_permissions()
)
+ page_data["user_crafty_permissions"] = (
+ self.controller.crafty_perms.get_crafty_permissions_list(user_id)
+ )
if user_id is None:
self.redirect("/panel/error?error=Invalid User ID")
@@ -1403,7 +1406,7 @@ class PanelHandler(BaseHandler):
self.controller.management.add_to_audit_log(
exec_user["user_id"],
f"Removed user {target_user['username']} (UID:{user_id})",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
self.redirect("/panel/panel_config")
diff --git a/app/classes/web/public_handler.py b/app/classes/web/public_handler.py
index 467765ea..21e2d495 100644
--- a/app/classes/web/public_handler.py
+++ b/app/classes/web/public_handler.py
@@ -228,7 +228,7 @@ class PublicHandler(BaseHandler):
)
# log this login
self.controller.management.add_to_audit_log(
- user_data.user_id, "Logged in", 0, self.get_remote_ip()
+ user_data.user_id, "Logged in", None, self.get_remote_ip()
)
return self.finish_json(
@@ -254,7 +254,7 @@ class PublicHandler(BaseHandler):
)
# log this failed login attempt
self.controller.management.add_to_audit_log(
- user_data.user_id, "Tried to log in", 0, self.get_remote_ip()
+ user_data.user_id, "Tried to log in", None, self.get_remote_ip()
)
return self.finish_json(
403,
diff --git a/app/classes/web/routes/api/auth/login.py b/app/classes/web/routes/api/auth/login.py
index 7a27c6f8..7e8131f3 100644
--- a/app/classes/web/routes/api/auth/login.py
+++ b/app/classes/web/routes/api/auth/login.py
@@ -101,7 +101,7 @@ class ApiAuthLoginHandler(BaseApiHandler):
# log this login
self.controller.management.add_to_audit_log(
- user_data.user_id, "logged in via the API", 0, self.get_remote_ip()
+ user_data.user_id, "logged in via the API", None, self.get_remote_ip()
)
self.finish_json(
@@ -119,7 +119,7 @@ class ApiAuthLoginHandler(BaseApiHandler):
else:
# log this failed login attempt
self.controller.management.add_to_audit_log(
- user_data.user_id, "Tried to log in", 0, self.get_remote_ip()
+ user_data.user_id, "Tried to log in", None, self.get_remote_ip()
)
self.finish_json(
401,
diff --git a/app/classes/web/routes/api/crafty/config/index.py b/app/classes/web/routes/api/crafty/config/index.py
index c901732c..40504d76 100644
--- a/app/classes/web/routes/api/crafty/config/index.py
+++ b/app/classes/web/routes/api/crafty/config/index.py
@@ -9,7 +9,6 @@ from app.classes.web.base_api_handler import BaseApiHandler
config_json_schema = {
"type": "object",
"properties": {
- "http_port": {"type": "integer"},
"https_port": {"type": "integer"},
"language": {
"type": "string",
@@ -107,7 +106,7 @@ class ApiCraftyConfigIndexHandler(BaseApiHandler):
try:
data = orjson.loads(self.request.body)
- except orjson.decoder.JSONDecodeError as e:
+ except orjson.JSONDecodeError as e:
return self.finish_json(
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
)
@@ -129,7 +128,7 @@ class ApiCraftyConfigIndexHandler(BaseApiHandler):
self.controller.management.add_to_audit_log(
user["user_id"],
"edited config.json",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
@@ -188,7 +187,7 @@ class ApiCraftyCustomizeIndexHandler(BaseApiHandler):
try:
data = orjson.loads(self.request.body)
- except orjson.decoder.JSONDecodeError as e:
+ except orjson.JSONDecodeError as e:
return self.finish_json(
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
)
@@ -226,7 +225,7 @@ class ApiCraftyCustomizeIndexHandler(BaseApiHandler):
self.controller.management.add_to_audit_log(
user["user_id"],
f"customized login photo: {data['photo']}/{data['opacity']}",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
self.controller.management.set_login_opacity(int(data["opacity"]))
diff --git a/app/classes/web/routes/api/crafty/config/server_dir.py b/app/classes/web/routes/api/crafty/config/server_dir.py
index 91c4cc89..07cf7c26 100644
--- a/app/classes/web/routes/api/crafty/config/server_dir.py
+++ b/app/classes/web/routes/api/crafty/config/server_dir.py
@@ -68,7 +68,7 @@ class ApiCraftyConfigServerDirHandler(BaseApiHandler):
try:
data = orjson.loads(self.request.body)
- except orjson.decoder.JSONDecodeError as e:
+ except orjson.JSONDecodeError as e:
return self.finish_json(
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
)
@@ -109,7 +109,7 @@ class ApiCraftyConfigServerDirHandler(BaseApiHandler):
self.controller.management.add_to_audit_log(
auth_data[4]["user_id"],
f"updated master servers dir to {new_dir}/servers",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
diff --git a/app/classes/web/routes/api/roles/index.py b/app/classes/web/routes/api/roles/index.py
index 266afb23..0f656dbb 100644
--- a/app/classes/web/routes/api/roles/index.py
+++ b/app/classes/web/routes/api/roles/index.py
@@ -161,7 +161,7 @@ class ApiRolesIndexHandler(BaseApiHandler):
self.controller.management.add_to_audit_log(
user["user_id"],
f"created role {role_name} (RID:{role_id})",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
diff --git a/app/classes/web/routes/api/roles/role/index.py b/app/classes/web/routes/api/roles/role/index.py
index 5ed12d69..97362f5b 100644
--- a/app/classes/web/routes/api/roles/role/index.py
+++ b/app/classes/web/routes/api/roles/role/index.py
@@ -112,7 +112,7 @@ class ApiRolesRoleIndexHandler(BaseApiHandler):
self.controller.management.add_to_audit_log(
user["user_id"],
f"deleted role with ID {role_id}",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
@@ -133,7 +133,7 @@ class ApiRolesRoleIndexHandler(BaseApiHandler):
try:
data = orjson.loads(self.request.body)
- except orjson.decoder.JSONDecodeError as e:
+ except orjson.JSONDecodeError as e:
return self.finish_json(
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
)
@@ -172,7 +172,7 @@ class ApiRolesRoleIndexHandler(BaseApiHandler):
self.controller.management.add_to_audit_log(
user["user_id"],
f"modified role with ID {role_id}",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
diff --git a/app/classes/web/routes/api/servers/server/action.py b/app/classes/web/routes/api/servers/server/action.py
index 01ce45c4..aba06da3 100644
--- a/app/classes/web/routes/api/servers/server/action.py
+++ b/app/classes/web/routes/api/servers/server/action.py
@@ -18,13 +18,14 @@ class ApiServersServerActionHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.COMMANDS
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.COMMANDS not in server_permissions:
# if the user doesn't have Commands permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
@@ -33,6 +34,17 @@ class ApiServersServerActionHandler(BaseApiHandler):
self.controller.crafty_perms.can_create_server(auth_data[4]["user_id"])
or auth_data[4]["superuser"]
):
+ srv_object = self.controller.servers.get_server_instance_by_id(
+ server_id
+ )
+ if srv_object.check_running():
+ return self.finish_json(
+ 409,
+ {
+ "status": "error",
+ "error": "Server Running!",
+ },
+ )
self._clone_server(server_id, auth_data[4]["user_id"])
return self.finish_json(200, {"status": "ok"})
return self.finish_json(
@@ -67,20 +79,29 @@ class ApiServersServerActionHandler(BaseApiHandler):
name_counter += 1
new_server_name = server_data.get("server_name") + f" (Copy {name_counter})"
- new_server_id = self.controller.servers.create_server(
- new_server_name,
- None,
- "",
- None,
- server_data.get("executable"),
- None,
- server_data.get("stop_command"),
- server_data.get("type"),
- user_id,
- server_data.get("server_port"),
+ new_server_id = self.helper.create_uuid()
+ new_server_path = os.path.join(self.helper.servers_dir, new_server_id)
+ new_backup_path = os.path.join(self.helper.backup_path, new_server_id)
+ new_server_command = str(server_data.get("execution_command")).replace(
+ server_id, new_server_id
+ )
+ new_server_log_path = server_data.get("log_path").replace(
+ server_id, new_server_id
)
- new_server_path = os.path.join(self.helper.servers_dir, new_server_id)
+ self.controller.register_server(
+ new_server_name,
+ new_server_id,
+ new_server_path,
+ new_backup_path,
+ new_server_command,
+ server_data.get("executable"),
+ new_server_log_path,
+ server_data.get("stop_command"),
+ server_data.get("server_port"),
+ user_id,
+ server_data.get("type"),
+ )
self.controller.management.add_to_audit_log(
user_id,
@@ -92,18 +113,6 @@ class ApiServersServerActionHandler(BaseApiHandler):
# copy the old server
FileHelpers.copy_dir(server_data.get("path"), new_server_path)
- # TODO get old server DB data to individual variables
- new_server_command = str(server_data.get("execution_command"))
- new_server_log_file = str(
- self.helper.get_os_understandable_path(server_data.get("log_path"))
- )
-
- server: Servers = self.controller.servers.get_server_obj(new_server_id)
- server.path = new_server_path
- server.log_path = new_server_log_file
- server.execution_command = new_server_command
- self.controller.servers.update_server(server)
-
for role in self.controller.server_perms.get_server_roles(server_id):
mask = self.controller.server_perms.get_permissions_mask(
role.role_id, server_id
diff --git a/app/classes/web/routes/api/servers/server/backups/backup/index.py b/app/classes/web/routes/api/servers/server/backups/backup/index.py
index 05edd3a9..1b9ff915 100644
--- a/app/classes/web/routes/api/servers/server/backups/backup/index.py
+++ b/app/classes/web/routes/api/servers/server/backups/backup/index.py
@@ -26,12 +26,14 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
auth_data = self.authenticate_user()
if not auth_data:
return
- if (
- EnumPermissionsServer.BACKUP
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.BACKUP not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
self.finish_json(200, self.controller.management.get_backup_config(server_id))
@@ -41,12 +43,14 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
backup_conf = self.controller.management.get_backup_config(server_id)
if not auth_data:
return
- if (
- EnumPermissionsServer.BACKUP
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.BACKUP not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
@@ -89,12 +93,14 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
auth_data = self.authenticate_user()
if not auth_data:
return
- if (
- EnumPermissionsServer.BACKUP
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.BACKUP not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
@@ -203,7 +209,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
except JobLookupError as e:
logger.info("No active tasks found for server: {e}")
self.controller.remove_server(server_id, True)
- except Exception as e:
+ except (FileNotFoundError, NotADirectoryError) as e:
return self.finish_json(
400, {"status": "error", "error": f"NO BACKUP FOUND {e}"}
)
diff --git a/app/classes/web/routes/api/servers/server/backups/index.py b/app/classes/web/routes/api/servers/server/backups/index.py
index 9e47bcfc..865fe25a 100644
--- a/app/classes/web/routes/api/servers/server/backups/index.py
+++ b/app/classes/web/routes/api/servers/server/backups/index.py
@@ -42,12 +42,14 @@ class ApiServersServerBackupsIndexHandler(BaseApiHandler):
auth_data = self.authenticate_user()
if not auth_data:
return
- if (
- EnumPermissionsServer.BACKUP
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.BACKUP not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
self.finish_json(200, self.controller.management.get_backup_config(server_id))
@@ -82,13 +84,14 @@ class ApiServersServerBackupsIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.BACKUP
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.BACKUP not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
diff --git a/app/classes/web/routes/api/servers/server/files.py b/app/classes/web/routes/api/servers/server/files.py
index 8e70d4fe..2951ff25 100644
--- a/app/classes/web/routes/api/servers/server/files.py
+++ b/app/classes/web/routes/api/servers/server/files.py
@@ -80,16 +80,16 @@ class ApiServersServerFilesIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
+ auth_data[4]["user_id"], server_id
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
if (
- EnumPermissionsServer.FILES
- not in self.controller.server_perms.get_user_id_permissions_list(
- auth_data[4]["user_id"], server_id
- )
- and EnumPermissionsServer.BACKUP
- not in self.controller.server_perms.get_user_id_permissions_list(
- auth_data[4]["user_id"], server_id
- )
+ EnumPermissionsServer.FILES not in server_permissions
+ and EnumPermissionsServer.BACKUP not in server_permissions
):
# if the user doesn't have Files or Backup permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
@@ -197,13 +197,14 @@ class ApiServersServerFilesIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.FILES
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.FILES not in server_permissions:
# if the user doesn't have Files permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
try:
@@ -254,13 +255,14 @@ class ApiServersServerFilesIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.FILES
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.FILES not in server_permissions:
# if the user doesn't have Files permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
try:
@@ -307,13 +309,14 @@ class ApiServersServerFilesIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.FILES
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.FILES not in server_permissions:
# if the user doesn't have Files permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
try:
@@ -373,13 +376,14 @@ class ApiServersServerFilesCreateHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.FILES
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.FILES not in server_permissions:
# if the user doesn't have Files permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
try:
@@ -438,13 +442,14 @@ class ApiServersServerFilesCreateHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.FILES
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.FILES not in server_permissions:
# if the user doesn't have Files permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
try:
@@ -504,13 +509,14 @@ class ApiServersServerFilesZipHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.FILES
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.FILES not in server_permissions:
# if the user doesn't have Files permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
try:
diff --git a/app/classes/web/routes/api/servers/server/index.py b/app/classes/web/routes/api/servers/server/index.py
index 81035bd0..9bfc3a9a 100644
--- a/app/classes/web/routes/api/servers/server/index.py
+++ b/app/classes/web/routes/api/servers/server/index.py
@@ -102,13 +102,14 @@ class ApiServersServerIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.CONFIG
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.CONFIG not in server_permissions:
# if the user doesn't have Config permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
@@ -154,13 +155,14 @@ class ApiServersServerIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.CONFIG
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.CONFIG not in server_permissions:
# if the user doesn't have Config permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
diff --git a/app/classes/web/routes/api/servers/server/logs.py b/app/classes/web/routes/api/servers/server/logs.py
index 94a8a71b..eb6ede00 100644
--- a/app/classes/web/routes/api/servers/server/logs.py
+++ b/app/classes/web/routes/api/servers/server/logs.py
@@ -30,13 +30,14 @@ class ApiServersServerLogsHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.LOGS
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.LOGS not in server_permissions:
# if the user doesn't have Logs permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
diff --git a/app/classes/web/routes/api/servers/server/stdin.py b/app/classes/web/routes/api/servers/server/stdin.py
index ba8400b7..ca2cd7d9 100644
--- a/app/classes/web/routes/api/servers/server/stdin.py
+++ b/app/classes/web/routes/api/servers/server/stdin.py
@@ -16,13 +16,14 @@ class ApiServersServerStdinHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.COMMANDS
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.COMMANDS not in server_permissions:
# if the user doesn't have Commands permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
diff --git a/app/classes/web/routes/api/servers/server/tasks/index.py b/app/classes/web/routes/api/servers/server/tasks/index.py
index 8e98bbbe..0c03319c 100644
--- a/app/classes/web/routes/api/servers/server/tasks/index.py
+++ b/app/classes/web/routes/api/servers/server/tasks/index.py
@@ -78,13 +78,14 @@ class ApiServersServerTasksIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.SCHEDULE
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.SCHEDULE not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
data["server_id"] = server_id
diff --git a/app/classes/web/routes/api/servers/server/tasks/task/index.py b/app/classes/web/routes/api/servers/server/tasks/task/index.py
index 742312a6..dac60762 100644
--- a/app/classes/web/routes/api/servers/server/tasks/task/index.py
+++ b/app/classes/web/routes/api/servers/server/tasks/task/index.py
@@ -54,12 +54,14 @@ class ApiServersServerTasksTaskIndexHandler(BaseApiHandler):
auth_data = self.authenticate_user()
if not auth_data:
return
- if (
- EnumPermissionsServer.SCHEDULE
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.SCHEDULE not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
self.finish_json(200, self.controller.management.get_scheduled_task(task_id))
@@ -68,12 +70,14 @@ class ApiServersServerTasksTaskIndexHandler(BaseApiHandler):
auth_data = self.authenticate_user()
if not auth_data:
return
- if (
- EnumPermissionsServer.SCHEDULE
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.SCHEDULE not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
@@ -120,13 +124,14 @@ class ApiServersServerTasksTaskIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.SCHEDULE
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.SCHEDULE not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
diff --git a/app/classes/web/routes/api/servers/server/webhooks/index.py b/app/classes/web/routes/api/servers/server/webhooks/index.py
index 223171c8..2557c309 100644
--- a/app/classes/web/routes/api/servers/server/webhooks/index.py
+++ b/app/classes/web/routes/api/servers/server/webhooks/index.py
@@ -38,12 +38,14 @@ class ApiServersServerWebhooksIndexHandler(BaseApiHandler):
auth_data = self.authenticate_user()
if not auth_data:
return
- if (
- EnumPermissionsServer.CONFIG
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.CONFIG not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
self.finish_json(
@@ -81,13 +83,14 @@ class ApiServersServerWebhooksIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.CONFIG
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.CONFIG not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
data["server_id"] = server_id
diff --git a/app/classes/web/routes/api/servers/server/webhooks/webhook/index.py b/app/classes/web/routes/api/servers/server/webhooks/webhook/index.py
index 4b58011e..c94aa975 100644
--- a/app/classes/web/routes/api/servers/server/webhooks/webhook/index.py
+++ b/app/classes/web/routes/api/servers/server/webhooks/webhook/index.py
@@ -39,12 +39,14 @@ class ApiServersServerWebhooksManagementIndexHandler(BaseApiHandler):
auth_data = self.authenticate_user()
if not auth_data:
return
- if (
- EnumPermissionsServer.CONFIG
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.CONFIG not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
if (
@@ -66,12 +68,14 @@ class ApiServersServerWebhooksManagementIndexHandler(BaseApiHandler):
auth_data = self.authenticate_user()
if not auth_data:
return
- if (
- EnumPermissionsServer.CONFIG
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.CONFIG not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
@@ -117,13 +121,14 @@ class ApiServersServerWebhooksManagementIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.CONFIG
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.CONFIG not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
@@ -159,13 +164,14 @@ class ApiServersServerWebhooksManagementIndexHandler(BaseApiHandler):
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
# if the user doesn't have access to the server, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
-
- if (
- EnumPermissionsServer.CONFIG
- not in self.controller.server_perms.get_user_id_permissions_list(
+ mask = self.controller.server_perms.get_lowest_api_perm_mask(
+ self.controller.server_perms.get_user_permissions_mask(
auth_data[4]["user_id"], server_id
- )
- ):
+ ),
+ auth_data[5],
+ )
+ server_permissions = self.controller.server_perms.get_permissions(mask)
+ if EnumPermissionsServer.CONFIG not in server_permissions:
# if the user doesn't have Schedule permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
webhook = self.controller.management.get_webhook_by_id(webhook_id)
diff --git a/app/classes/web/routes/api/users/index.py b/app/classes/web/routes/api/users/index.py
index f7341d38..fef154a0 100644
--- a/app/classes/web/routes/api/users/index.py
+++ b/app/classes/web/routes/api/users/index.py
@@ -177,7 +177,7 @@ class ApiUsersIndexHandler(BaseApiHandler):
self.controller.management.add_to_audit_log(
user["user_id"],
f"added user {username} (UID:{user_id}) with roles {roles}",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
diff --git a/app/classes/web/routes/api/users/user/api.py b/app/classes/web/routes/api/users/user/api.py
index 1c7635f2..2abb8463 100644
--- a/app/classes/web/routes/api/users/user/api.py
+++ b/app/classes/web/routes/api/users/user/api.py
@@ -43,7 +43,7 @@ class ApiUsersUserKeyHandler(BaseApiHandler):
auth_data[4]["user_id"],
f"Generated a new API token for the key {key.name} "
f"from user with UID: {key.user_id}",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
data_key = self.controller.authentication.generate(
@@ -75,7 +75,7 @@ class ApiUsersUserKeyHandler(BaseApiHandler):
"name": key.name,
"server_permissions": key.server_permissions,
"crafty_permissions": key.crafty_permissions,
- "superuser": key.superuser,
+ "full_access": key.full_access,
}
)
self.finish_json(
@@ -99,7 +99,7 @@ class ApiUsersUserKeyHandler(BaseApiHandler):
"type": "string",
"pattern": "^[01]{3}$", # 8 bits, see EnumPermissionsCrafty
},
- "superuser": {"type": "boolean"},
+ "full_access": {"type": "boolean"},
},
"additionalProperties": False,
"minProperties": 1,
@@ -163,7 +163,7 @@ class ApiUsersUserKeyHandler(BaseApiHandler):
key_id = self.controller.users.add_user_api_key(
data["name"],
user_id,
- data["superuser"],
+ data["full_access"],
data["server_permissions_mask"],
data["crafty_permissions_mask"],
)
@@ -173,7 +173,7 @@ class ApiUsersUserKeyHandler(BaseApiHandler):
f"Added API key {data['name']} with crafty permissions "
f"{data['crafty_permissions_mask']}"
f" and {data['server_permissions_mask']} for user with UID: {user_id}",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
self.finish_json(200, {"status": "ok", "data": {"id": key_id}})
@@ -233,7 +233,7 @@ class ApiUsersUserKeyHandler(BaseApiHandler):
auth_data[4]["user_id"],
f"Removed API key {target_key} "
f"(ID: {key_id}) from user {auth_data[4]['user_id']}",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
diff --git a/app/classes/web/routes/api/users/user/index.py b/app/classes/web/routes/api/users/user/index.py
index 1b7f6f91..6efee93e 100644
--- a/app/classes/web/routes/api/users/user/index.py
+++ b/app/classes/web/routes/api/users/user/index.py
@@ -94,7 +94,7 @@ class ApiUsersUserIndexHandler(BaseApiHandler):
self.controller.management.add_to_audit_log(
user["user_id"],
f"deleted the user {user_id}",
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
@@ -283,7 +283,7 @@ class ApiUsersUserIndexHandler(BaseApiHandler):
f"edited user {user_obj.username} (UID: {user_id})"
f"with roles {user_obj.roles}"
),
- server_id=0,
+ server_id=None,
source_ip=self.get_remote_ip(),
)
diff --git a/app/classes/web/routes/api/users/user/permissions.py b/app/classes/web/routes/api/users/user/permissions.py
index b6c8703a..5981eaf4 100644
--- a/app/classes/web/routes/api/users/user/permissions.py
+++ b/app/classes/web/routes/api/users/user/permissions.py
@@ -52,6 +52,8 @@ class ApiUsersUserPermissionsHandler(BaseApiHandler):
},
)
+ counter_data = PermissionsCrafty.get_created_quantity_list(user_id)
+
self.finish_json(
200,
{
@@ -59,9 +61,9 @@ class ApiUsersUserPermissionsHandler(BaseApiHandler):
"data": {
"permissions": res_data.permissions,
"counters": {
- SERVER_CREATION: res_data.created_server,
- USER_CONFIG: res_data.created_user,
- ROLES_CONFIG: res_data.created_role,
+ SERVER_CREATION: counter_data["SERVER_CREATION"],
+ USER_CONFIG: counter_data["USER_CONFIG"],
+ ROLES_CONFIG: counter_data["ROLES_CONFIG"],
},
"limits": {
SERVER_CREATION: res_data.limit_server_creation,
diff --git a/app/classes/web/server_handler.py b/app/classes/web/server_handler.py
index 545029aa..11853a47 100644
--- a/app/classes/web/server_handler.py
+++ b/app/classes/web/server_handler.py
@@ -30,7 +30,7 @@ class ServerHandler(BaseHandler):
) = self.current_user
superuser = exec_user["superuser"]
if api_key is not None:
- superuser = superuser and api_key.superuser
+ superuser = superuser and api_key.full_access
if superuser:
defined_servers = self.controller.servers.list_defined_servers()
@@ -124,7 +124,7 @@ class ServerHandler(BaseHandler):
"created": api_key.created,
"server_permissions": api_key.server_permissions,
"crafty_permissions": api_key.crafty_permissions,
- "superuser": api_key.superuser,
+ "full_access": api_key.full_access,
}
if api_key is not None
else None
@@ -147,7 +147,7 @@ class ServerHandler(BaseHandler):
page_data["server_api"] = False
if page_data["online"]:
page_data["server_api"] = self.helper.check_address_status(
- "https://serverjars.com/api/fetchTypes"
+ "https://api.serverjars.com"
)
page_data["server_types"] = self.controller.server_jars.get_serverjar_data()
page_data["js_server_types"] = json.dumps(
diff --git a/app/classes/web/tornado_handler.py b/app/classes/web/tornado_handler.py
index f65f4fca..6285edfc 100644
--- a/app/classes/web/tornado_handler.py
+++ b/app/classes/web/tornado_handler.py
@@ -98,7 +98,6 @@ class Webserver:
# let's verify we have an SSL cert
self.helper.create_self_signed_cert()
- http_port = self.helper.get_setting("http_port")
https_port = self.helper.get_setting("https_port")
debug_errors = self.helper.get_setting("show_errors")
@@ -110,9 +109,6 @@ class Webserver:
cookie_secret = self.helper.random_string_generator(32)
HelpersManagement.set_cookie_secret(cookie_secret)
- if not http_port and http_port != 0:
- http_port = 8000
-
if not https_port:
https_port = 8443
@@ -125,7 +121,7 @@ class Webserver:
),
}
- logger.info(f"Starting Web Server on ports http:{http_port} https:{https_port}")
+ logger.info(f"Starting Web Server on ports https:{https_port}")
asyncio.set_event_loop(asyncio.new_event_loop())
diff --git a/app/classes/web/upload_handler.py b/app/classes/web/upload_handler.py
index 0667dd12..747fa63b 100644
--- a/app/classes/web/upload_handler.py
+++ b/app/classes/web/upload_handler.py
@@ -42,7 +42,7 @@ class UploadHandler(BaseHandler):
if self.upload_type == "server_import":
superuser = exec_user["superuser"]
if api_key is not None:
- superuser = superuser and api_key.superuser
+ superuser = superuser and api_key.full_access
user_id = exec_user["user_id"]
stream_size_value = self.helper.get_setting("stream_size_GB")
@@ -133,7 +133,7 @@ class UploadHandler(BaseHandler):
elif self.upload_type == "background":
superuser = exec_user["superuser"]
if api_key is not None:
- superuser = superuser and api_key.superuser
+ superuser = superuser and api_key.full_access
user_id = exec_user["user_id"]
stream_size_value = self.helper.get_setting("stream_size_GB")
@@ -212,7 +212,7 @@ class UploadHandler(BaseHandler):
server_id = self.get_argument("server_id", None)
superuser = exec_user["superuser"]
if api_key is not None:
- superuser = superuser and api_key.superuser
+ superuser = superuser and api_key.full_access
user_id = exec_user["user_id"]
stream_size_value = self.helper.get_setting("stream_size_GB")
diff --git a/app/classes/web/websocket_handler.py b/app/classes/web/websocket_handler.py
index cde97584..3e426797 100644
--- a/app/classes/web/websocket_handler.py
+++ b/app/classes/web/websocket_handler.py
@@ -55,7 +55,7 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
self.controller.management.add_to_audit_log_raw(
"unknown",
0,
- 0,
+ None,
"Someone tried to connect via WebSocket without proper authentication",
self.get_remote_ip(),
)
diff --git a/app/config/version.json b/app/config/version.json
index 8dffa727..22de834f 100644
--- a/app/config/version.json
+++ b/app/config/version.json
@@ -1,5 +1,5 @@
{
"major": 4,
"minor": 3,
- "sub": 2
+ "sub": 3
}
diff --git a/app/frontend/templates/panel/panel_edit_user_apikeys.html b/app/frontend/templates/panel/panel_edit_user_apikeys.html
index 084db0c3..76fa780b 100644
--- a/app/frontend/templates/panel/panel_edit_user_apikeys.html
+++ b/app/frontend/templates/panel/panel_edit_user_apikeys.html
@@ -58,7 +58,7 @@