diff --git a/CHANGELOG.md b/CHANGELOG.md
index 996acb40..44750a39 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,5 @@
# Changelog
-## --- [4.3.1] - 2023/TBD
+## --- [4.3.2] - 2024/TBD
### New features
TBD
### Bug fixes
@@ -10,7 +10,15 @@ TBD
TBD
-## --- [4.3.0] - 2023/03/09
+## --- [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))
+### Tweaks
+- Remove http re-direct handler. Users should implement nginx configurations for port 80 redirects ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/730))
+
+
+
+## --- [4.3.0] - 2024/03/09
### Breaking Changes
- This release includes database migrations that are not revertable. Once you update to this version you will not be able to rollback to a previous version.
- In this release, we've implemented a breaking change to enhance server identification within Crafty: instead of relying on numerical integers (1, 2, 3, etc.), Servers are now uniquely identified by their UUIDs. Please adapt your API clients accordingly.
@@ -34,7 +42,7 @@ TBD
- Update `de_DE, en_EN, es_ES, fr_FR, he_IL, lol_EN, lv_LV, nl_BE pl_PL, th_TH, tr_TR, uk_UA, zh_CN` translations for `4.3.0` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/715))
-## --- [4.2.3] - 2023/02/02
+## --- [4.2.3] - 2024/02/02
### New features
- Use Papermc Group's API for `paper` & `folia` builds in server builder ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/688))
- Allow omission of player count from Dashboard (e.g. for proxy servers) ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/692))
diff --git a/README.md b/README.md
index bc621c7d..ae70bd0e 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.1
+# Crafty Controller 4.3.2
> Python based Control Panel for your Minecraft Server
## What is Crafty Controller?
diff --git a/app/classes/shared/helpers.py b/app/classes/shared/helpers.py
index 6b821f9d..0427da11 100644
--- a/app/classes/shared/helpers.py
+++ b/app/classes/shared/helpers.py
@@ -496,7 +496,6 @@ class Helpers:
# Config.json was removed from the repo to make it easier for users
# To make non-breaking changes to the file.
return {
- "http_port": 8000,
"https_port": 8443,
"language": "en_EN",
"cookie_expire": 30,
diff --git a/app/classes/shared/migration.py b/app/classes/shared/migration.py
index 1adea4c6..6a93802b 100644
--- a/app/classes/shared/migration.py
+++ b/app/classes/shared/migration.py
@@ -369,11 +369,14 @@ class MigrationManager(object):
@cached_property
def migrator(self) -> Migrator:
"""
- Create migrator and setup it with fake migrations.
+ Create migrator
"""
migrator = Migrator(self.database)
- for name in self.done:
- self.up_one(name, migrator, True)
+ # 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)
return migrator
def compile(self, name, migrate="", rollback=""):
diff --git a/app/classes/web/http_handler.py b/app/classes/web/http_handler.py
deleted file mode 100644
index 32676d59..00000000
--- a/app/classes/web/http_handler.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import logging
-import requests
-
-from app.classes.web.base_handler import BaseHandler
-
-logger = logging.getLogger(__name__)
-
-
-class HTTPHandler(BaseHandler):
- def get(self):
- url = str(self.request.host)
- port = 443
- url_list = url.split(":")
- if url_list[0] != "":
- url = "https://" + url_list[0]
- else:
- url = "https://" + url
- db_port = self.helper.get_setting("https_port")
- try:
- resp = requests.head(url + ":" + str(port), timeout=(0.5, 5))
- resp.raise_for_status()
- except Exception:
- port = db_port
- self.redirect(url + ":" + str(port))
-
-
-class HTTPHandlerPage(BaseHandler):
- def get(self):
- url = str(self.request.host)
- port = 443
- url_list = url.split(":")
- if url_list[0] != "":
- url = "https://" + url_list[0]
- else:
- url = "https://" + url
- db_port = self.helper.get_setting("https_port")
- try:
- resp = requests.head(url + ":" + str(port), timeout=(0.5, 5))
- resp.raise_for_status()
- except Exception:
- port = db_port
- self.redirect(url + ":" + str(port))
diff --git a/app/classes/web/http_handler_page.py b/app/classes/web/http_handler_page.py
deleted file mode 100644
index 77161577..00000000
--- a/app/classes/web/http_handler_page.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import logging
-import requests
-from app.classes.web.base_handler import BaseHandler
-
-logger = logging.getLogger(__name__)
-
-
-class HTTPHandlerPage(BaseHandler):
- def get(self):
- url = self.request.full_url
- port = 443
- if url[len(url) - 1] == "/":
- url = url.strip(url[len(url) - 1])
- url_list = url.split("/")
- if url_list[0] != "":
- primary_url = url_list[0] + ":" + str(port) + "/"
- backup_url = (
- url_list[0] + ":" + str(self.helper.get_setting("https_port")) + "/"
- )
- for i in range(len(url_list) - 1):
- primary_url += url_list[i + 1]
- backup_url += url_list[i + 1]
- else:
- primary_url = url + str(port)
- backup_url = url + str(self.helper.get_setting("https_port"))
-
- try:
- resp = requests.head(primary_url, timeout=(0.5, 5))
- resp.raise_for_status()
- url = primary_url
- except Exception:
- url = backup_url
- self.redirect("https://" + url + ":" + str(port))
diff --git a/app/classes/web/routes/api/roles/index.py b/app/classes/web/routes/api/roles/index.py
index dce6f453..266afb23 100644
--- a/app/classes/web/routes/api/roles/index.py
+++ b/app/classes/web/routes/api/roles/index.py
@@ -17,7 +17,7 @@ create_role_schema = {
"type": "object",
"properties": {
"server_id": {
- "type": "integer",
+ "type": "string",
"minimum": 1,
},
"permissions": {
@@ -47,7 +47,7 @@ basic_create_role_schema = {
"type": "object",
"properties": {
"server_id": {
- "type": "integer",
+ "type": "string",
"minimum": 1,
},
"permissions": {
diff --git a/app/classes/web/routes/api/roles/role/index.py b/app/classes/web/routes/api/roles/role/index.py
index 0dd7d6c8..5ed12d69 100644
--- a/app/classes/web/routes/api/roles/role/index.py
+++ b/app/classes/web/routes/api/roles/role/index.py
@@ -16,7 +16,7 @@ modify_role_schema = {
"type": "object",
"properties": {
"server_id": {
- "type": "integer",
+ "type": "string",
"minimum": 1,
},
"permissions": {
@@ -46,7 +46,7 @@ basic_modify_role_schema = {
"type": "object",
"properties": {
"server_id": {
- "type": "integer",
+ "type": "string",
"minimum": 1,
},
"permissions": {
diff --git a/app/classes/web/tornado_handler.py b/app/classes/web/tornado_handler.py
index fbcf970f..f65f4fca 100644
--- a/app/classes/web/tornado_handler.py
+++ b/app/classes/web/tornado_handler.py
@@ -25,7 +25,6 @@ from app.classes.web.server_handler import ServerHandler
from app.classes.web.websocket_handler import WebSocketHandler
from app.classes.web.static_handler import CustomStaticHandler
from app.classes.web.upload_handler import UploadHandler
-from app.classes.web.http_handler import HTTPHandler, HTTPHandlerPage
from app.classes.web.status_handler import StatusHandler
@@ -44,7 +43,6 @@ class Webserver:
file_helper: FileHelpers,
):
self.ioloop = None
- self.http_server = None
self.https_server = None
self.helper = helper
self.controller = controller
@@ -173,30 +171,6 @@ class Webserver:
static_handler_class=CustomStaticHandler,
serve_traceback=debug_errors,
)
- http_handers = [
- (r"/", HTTPHandler, handler_args),
- (r"/(.+)", HTTPHandlerPage, handler_args),
- ]
- http_app = tornado.web.Application(
- http_handers,
- template_path=os.path.join(self.helper.webroot, "templates"),
- static_path=os.path.join(self.helper.webroot, "static"),
- debug=debug_errors,
- cookie_secret=cookie_secret,
- xsrf_cookies=True,
- autoreload=False,
- log_function=self.log_function,
- default_handler_class=HTTPHandler,
- login_url="/login",
- serve_traceback=debug_errors,
- )
-
- if http_port != 0:
- self.http_server = tornado.httpserver.HTTPServer(http_app)
- self.http_server.listen(http_port)
- else:
- logger.info("http port disabled by config")
-
self.https_server = tornado.httpserver.HTTPServer(app, ssl_options=cert_objects)
self.https_server.listen(https_port)
@@ -218,7 +192,6 @@ class Webserver:
logger.info("Shutting Down Web Server")
Console.info("Shutting Down Web Server")
self.ioloop.stop()
- self.http_server.stop()
self.https_server.stop()
logger.info("Web Server Stopped")
Console.info("Web Server Stopped")
diff --git a/app/config/version.json b/app/config/version.json
index 9a8d1a7f..8dffa727 100644
--- a/app/config/version.json
+++ b/app/config/version.json
@@ -1,5 +1,5 @@
{
"major": 4,
"minor": 3,
- "sub": 1
+ "sub": 2
}
diff --git a/app/migrations/20240310_fixing_rework_servers_uuid.py b/app/migrations/20240310_fixing_rework_servers_uuid.py
new file mode 100644
index 00000000..3c613e52
--- /dev/null
+++ b/app/migrations/20240310_fixing_rework_servers_uuid.py
@@ -0,0 +1,132 @@
+import datetime
+import uuid
+import peewee
+import logging
+
+from app.classes.shared.console import Console
+from app.classes.shared.migration import Migrator, MigrateHistory
+from app.classes.models.management import Schedules, Backups
+from app.classes.models.server_permissions import RoleServers
+
+logger = logging.getLogger(__name__)
+
+
+def migrate(migrator: Migrator, database, **kwargs):
+ """
+ Write your migrations here.
+ """
+ db = database
+
+ # **********************************************************************************
+ # Servers New Model from Old (easier to migrate without dunmping Database)
+ # **********************************************************************************
+ class Servers(peewee.Model):
+ server_id = peewee.CharField(primary_key=True, default=str(uuid.uuid4()))
+ created = peewee.DateTimeField(default=datetime.datetime.now)
+ server_name = peewee.CharField(default="Server", index=True)
+ path = peewee.CharField(default="")
+ backup_path = peewee.CharField(default="")
+ executable = peewee.CharField(default="")
+ log_path = peewee.CharField(default="")
+ execution_command = peewee.CharField(default="")
+ auto_start = peewee.BooleanField(default=0)
+ auto_start_delay = peewee.IntegerField(default=10)
+ crash_detection = peewee.BooleanField(default=0)
+ stop_command = peewee.CharField(default="stop")
+ executable_update_url = peewee.CharField(default="")
+ server_ip = peewee.CharField(default="127.0.0.1")
+ server_port = peewee.IntegerField(default=25565)
+ logs_delete_after = peewee.IntegerField(default=0)
+ type = peewee.CharField(default="minecraft-java")
+ show_status = peewee.BooleanField(default=1)
+ created_by = peewee.IntegerField(default=-100)
+ shutdown_timeout = peewee.IntegerField(default=60)
+ ignored_exits = peewee.CharField(default="0")
+
+ class Meta:
+ table_name = "servers"
+ database = db
+
+ try:
+ logger.info("Migrating Data from Int to UUID (Fixing Issue)")
+ Console.info("Migrating Data from Int to UUID (Fixing Issue)")
+
+ # Changes on Servers Roles Table
+ migrator.alter_column_type(
+ RoleServers,
+ "server_id",
+ peewee.ForeignKeyField(
+ Servers,
+ backref="role_server",
+ null=True,
+ field=peewee.CharField(primary_key=True, default=str(uuid.uuid4())),
+ ),
+ )
+
+ # Changes on Backups Table
+ migrator.alter_column_type(
+ Backups,
+ "server_id",
+ peewee.ForeignKeyField(
+ Servers,
+ backref="backup_server",
+ null=True,
+ field=peewee.CharField(primary_key=True, default=str(uuid.uuid4())),
+ ),
+ )
+
+ # Changes on SChedule Table
+ migrator.alter_column_type(
+ Schedules,
+ "server_id",
+ peewee.ForeignKeyField(
+ Servers,
+ backref="schedule_server",
+ null=True,
+ field=peewee.CharField(primary_key=True, default=str(uuid.uuid4())),
+ ),
+ )
+
+ migrator.run()
+
+ logger.info("Migrating Data from Int to UUID (Fixing Issue) : SUCCESS")
+ Console.info("Migrating Data from Int to UUID (Fixing Issue) : SUCCESS")
+
+ except Exception as ex:
+ logger.error("Error while migrating Data from Int to UUID (Fixing Issue)")
+ logger.error(ex)
+ Console.error("Error while migrating Data from Int to UUID (Fixing Issue)")
+ Console.error(ex)
+ last_migration = MigrateHistory.get_by_id(MigrateHistory.select().count())
+ last_migration.delete()
+ return
+
+ return
+
+
+def rollback(migrator: Migrator, database, **kwargs):
+ """
+ Write your rollback migrations here.
+ """
+ db = database
+
+ # Changes on Webhook Table
+ migrator.alter_column_type(
+ RoleServers,
+ "server_id",
+ peewee.IntegerField(null=True),
+ )
+
+ # Changes on Webhook Table
+ migrator.alter_column_type(
+ Backups,
+ "server_id",
+ peewee.IntegerField(null=True),
+ )
+
+ # Changes on Webhook Table
+ migrator.alter_column_type(
+ Schedules,
+ "server_id",
+ peewee.IntegerField(null=True),
+ )
diff --git a/sonar-project.properties b/sonar-project.properties
index b6fa060c..a5f5e258 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -3,7 +3,7 @@ sonar.organization=crafty-controller
# This is the name and version displayed in the SonarCloud UI.
sonar.projectName=Crafty 4
-sonar.projectVersion=4.3.1
+sonar.projectVersion=4.3.2
sonar.python.version=3.9, 3.10, 3.11
sonar.exclusions=app/migrations/**, app/frontend/static/assets/vendors/**