From c7ef9cc4504783cfa95926a34698b7a9cb2fb251 Mon Sep 17 00:00:00 2001 From: Barunes Padhy Date: Wed, 19 Jun 2024 11:24:28 +0300 Subject: [PATCH] code restructuring --- backend/apimanager/dialogue_box.py | 70 ++++++ backend/apimanager/publish_methods.py | 219 +++++-------------- backend/apimanager/publish_methods_github.py | 157 +++++++++++++ backend/apimanager/publish_views.py | 35 ++- backend/apimanager/utilities.py | 20 ++ backend/backend/settings.py | 4 +- 6 files changed, 320 insertions(+), 185 deletions(-) create mode 100644 backend/apimanager/dialogue_box.py create mode 100644 backend/apimanager/publish_methods_github.py create mode 100644 backend/apimanager/utilities.py diff --git a/backend/apimanager/dialogue_box.py b/backend/apimanager/dialogue_box.py new file mode 100644 index 0000000..12534d3 --- /dev/null +++ b/backend/apimanager/dialogue_box.py @@ -0,0 +1,70 @@ +import sys +from PyQt6.QtWidgets import QApplication, QInputDialog, QWidget, QLineEdit, QMessageBox + + +def get_text_input(title, message, widget): + text, ok = QInputDialog.getText( + widget, + title, + message + ) + + if ok: + return text + else: + return None + + +def get_password(title, message, widget): + password, ok = QInputDialog.getText( + widget, + title, + message, + QLineEdit.EchoMode.Password + ) + + if ok: + return password + else: + return None + + +def show_confirmation(title, message, widget): + reply = QMessageBox.question( + widget, + title, + message, + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.No + ) + + if reply == QMessageBox.StandardButton.Yes: + return True + else: + return False + + +def show_message_box(title, message, widget): + QMessageBox.information( + widget, + title, + message + ) + return None + + +def draw_dialogue_box(title, message, dialogue_box_type): + app = QApplication(sys.argv) + widget = QWidget() + widget.setWindowTitle('Password Dialog') + + if dialogue_box_type == 'textbox': + return get_text_input(title, message, widget) + if dialogue_box_type == 'password': + return get_password(title, message, widget) + if dialogue_box_type == 'confirmation': + return show_confirmation(title, message, widget) + if dialogue_box_type == 'message': + return show_message_box(title, message, widget) + + app.exit() diff --git a/backend/apimanager/publish_methods.py b/backend/apimanager/publish_methods.py index 36bf484..0a05ac8 100644 --- a/backend/apimanager/publish_methods.py +++ b/backend/apimanager/publish_methods.py @@ -1,12 +1,22 @@ from django.conf import settings import os -import shutil -import subprocess -import tkinter as tk from rest_framework import status -from tkinter import simpledialog -from tkinter import messagebox -import urllib.parse + +from .utilities import ( + copy_content +) + +from .dialogue_box import ( + draw_dialogue_box +) + +from .publish_methods_github import ( + create_404_page, + git_existing_repo_setup, + github_init, + github_pages_deploy + +) deployment_methods = { "server_deploy": { @@ -17,191 +27,70 @@ deployment_methods = { } } -def invokeDialogueBox(title, message, type): - root = tk.Tk() - root.withdraw() - input_data = None - if type == 'text': - input_data = simpledialog.askstring(title, message) - if type == 'password': - input_data = simpledialog.askstring(title, message, show='*') - if type == 'yesno': - input_data = messagebox.askyesno(title, message) - if type == 'message': - messagebox.showinfo(title, message) - - root.destroy() - return input_data - -def copyData(data_location, deploy_location): - if not os.path.exists(data_location): - print("The source directory does not exist.") - else: - try: - if os.path.exists(f'{deploy_location}/data'): - shutil.rmtree(f'{deploy_location}/data') - else: - pass - shutil.copytree(data_location, deploy_location, dirs_exist_ok=True) - print(f"Data successfully deployed") - except Exception as e: - print(f"Error occurred: {e}") def server_deploy(): try: - data_location = f'{settings.BASE_DIR}/deploy/' - deploy_location = settings.DEPLOY_CONFIG["DEPLOY_LOCATION"]+'/server' - copyData(data_location, deploy_location) + copy_content( + settings.DEPLOY_CONFIG["EDITOR_DATA_LOCATION"], + f'{settings.DEPLOY_CONFIG["DEPLOY_LOCATION"]}/server/data', + 'folder', + 'remove_and_copy' + ) return {'message': 'Server deployment successful', 'status': status.HTTP_200_OK} except Exception as e: - print (f"An error occurred: {str(e)}") + print(f"An error occurred: {str(e)}") return {'message': str(e), 'status': status.HTTP_500_INTERNAL_SERVER_ERROR} + def github_deploy(): print("Deploying via github") - git_commands = {} - git_commands["git_init"] = ['git', 'init'] - git_commands["git_add"] = ['git', 'add', '.'] - git_commands["git_pull"] = ['git', 'pull'] - git_commands["git_config_email"] = ['git', 'config', '--local', 'user.email'] - git_commands["git_config_name"] = ['git', 'config', '--local', 'user.name'] - git_commands["git_commit"] = ['git', 'commit', '-m', 'Update website'] - git_commands["git_branch"] = ['git', 'branch', '-m', 'main'] - git_commands["git_get_origin_url"] = ['git', 'remote', 'get-url', 'origin'] - git_commands["git_set_origin_url"] = ['git', 'remote', 'set-url', 'origin'] - git_commands["git_add_url"] = ['git', 'remote', 'add', 'origin'] - git_commands["git_push"] = ['git', 'push', '-u', 'origin', 'main'] - git_commands["git_clone"] = ['git', 'clone'] + git_commands = { + "git_init": ['git', 'init'], + "git_add": ['git', 'add', '.'], + "git_pull": ['git', 'pull'], + "git_config_email": ['git', 'config', '--local', 'user.email'], + "git_config_name": ['git', 'config', '--local', 'user.name'], + "git_commit": ['git', 'commit', '-m', 'Update website'], + "git_branch": ['git', 'branch', '-m', 'main'], + "git_get_origin_url": ['git', 'remote', 'get-url', 'origin'], + "git_set_origin_url": ['git', 'remote', 'set-url', 'origin'], + "git_add_url": ['git', 'remote', 'add', 'origin'], + "git_push": ['git', 'push', '-u', 'origin', 'main'], + "git_clone": ['git', 'clone'] + } - data_location = f'{settings.BASE_DIR}/deploy/' deploy_location = settings.DEPLOY_CONFIG["DEPLOY_LOCATION"]+'/ghpages' create_404_page(deploy_location) - copyData(data_location, deploy_location) + copy_content( + settings.DEPLOY_CONFIG["EDITOR_DATA_LOCATION"], + f'{settings.DEPLOY_CONFIG["DEPLOY_LOCATION"]}/ghpages/data', + 'folder', + 'remove_and_copy' + ) if not os.path.exists(f'{deploy_location}/.git'): try: - existingRepo = invokeDialogueBox('Github Deploy', 'Do you have an existing repository with Rangolio on github?', 'yesno') - if (existingRepo): + existing_repo = draw_dialogue_box( + 'Github Deploy', + 'Do you have an existing repository with Rangolio on github?', + 'confirmation' + ) + if existing_repo: git_existing_repo_setup(deploy_location, git_commands) else: github_init(deploy_location, git_commands) - gh_pages_deploy(deploy_location, git_commands) + github_pages_deploy(deploy_location, git_commands) return {'message': 'Github deployment successful', 'status': status.HTTP_200_OK} except Exception as e: - print (f"An error occurred: {str(e)}") + print(f"An error occurred: {str(e)}") return {'message': str(e), 'status': status.HTTP_500_INTERNAL_SERVER_ERROR} else: try: - gh_pages_deploy(deploy_location, git_commands) + github_pages_deploy(deploy_location, git_commands) return {'message': 'Github deployment successful', 'status': status.HTTP_200_OK} except Exception as e: - print (f"An error occurred: {str(e)}") + print(f"An error occurred: {str(e)}") return {'message': str(e), 'status': status.HTTP_500_INTERNAL_SERVER_ERROR} - - -def github_init(deploy_location, git_commands): - user_details_defined = git_check_user_details(deploy_location, git_commands) - if not user_details_defined: - git_set_user_details(deploy_location, git_commands) - username = invokeDialogueBox('Github Deploy', 'Enter your username', 'text') - password = invokeDialogueBox('Github Deploy', 'Enter your github token', 'password') - remote_url = f'https://{username}:{password}@github.com/{username}/{username}.github.io.git' - - subprocess.run(git_commands["git_init"], cwd=deploy_location, check=True, text=True, capture_output=True) - subprocess.run(git_commands["git_add"], cwd=deploy_location, check=True, text=True, capture_output=True) - subprocess.run(git_commands["git_commit"], cwd=deploy_location, check=True, text=True, capture_output=True) - subprocess.run(git_commands["git_branch"], cwd=deploy_location, check=True, text=True, capture_output=True) - subprocess.run((git_commands["git_add_url"]).append(remote_url), cwd=deploy_location, check=True, text=True, capture_output=True) - subprocess.run(git_commands["git_push"], cwd=deploy_location, check=True, text=True, capture_output=True) - -def git_set_user_details(deploy_location, git_commands): - email = invokeDialogueBox('Github Deploy', 'Enter your github email', 'text') - name = invokeDialogueBox('Github Deploy', 'Enter your name', 'text') - subprocess.run(git_commands["git_config_email"] + [email], cwd=deploy_location, check=True, text=True, capture_output=True) - subprocess.run(git_commands["git_config_name"]+ [name], cwd=deploy_location, check=True, text=True, capture_output=True) - -def git_existing_repo_setup(deploy_location, git_commands): - - repo_url = invokeDialogueBox('Github Deploy', 'Enter Repository URL', 'text') - if not repo_url.endswith('.git'): - repo_url = repo_url + '.git' - - dist_folder_name = ((repo_url.split('/')).pop()).removesuffix('.git') - subprocess.run(git_commands["git_clone"] + [repo_url], cwd=settings.DEPLOY_CONFIG["DEPLOY_LOCATION"], check=True, text=True, capture_output=True) - git_update_viewable_ui(deploy_location, dist_folder_name) - -def git_check_user_details( deploy_location, git_commands): - try: - subprocess.run(git_commands["git_config_name"], cwd=deploy_location, check=True, text=True, capture_output=True) - subprocess.run(git_commands["git_config_email"], cwd=deploy_location, check=True, text=True, capture_output=True) - return True - except Exception as e: - return False - - -def git_update_viewable_ui(deploy_location, dist_folder_name, build_frontend=False): - shutil.move(deploy_location, f'{deploy_location}.temp') - if build_frontend: - subprocess.run(["npm", 'run', 'build:ghpages'], cwd=settings.DEPLOY_CONFIG["VIEWABLE_UI_LOCATION"], check=True, text=True, capture_output=True) - shutil.move(f'{settings.DEPLOY_CONFIG["DEPLOY_LOCATION"]}/{dist_folder_name}', f'{deploy_location}') - shutil.copy(f'{deploy_location}.temp/index.html', deploy_location) - shutil.copy(f'{deploy_location}.temp/404.html', deploy_location) - shutil.copytree(f'{deploy_location}.temp/assets', f'{deploy_location}/assets', dirs_exist_ok=True) - if os.path.exists(f'{deploy_location}.temp/data'): - shutil.copytree(f'{deploy_location}.temp/data', f'{deploy_location}/data', dirs_exist_ok=True) - shutil.rmtree(f'{deploy_location}.temp') - -def gh_pages_deploy(deploy_location, git_commands): - user_details_defined = git_check_user_details(deploy_location, git_commands) - if not user_details_defined: - git_set_user_details(deploy_location, git_commands) - subprocess.run(git_commands["git_pull"], cwd=deploy_location, check=True, text=True, capture_output=True) - print("completed git pull") - origin_url_subprocess = subprocess.run(git_commands["git_get_origin_url"], cwd=deploy_location, check=True, text=True, capture_output=True) - origin_url = origin_url_subprocess.stdout.strip() - print("Got origin as "+str(origin_url)) - parsed_url = urllib.parse.urlparse(origin_url) - print(parsed_url) - if not '@' in parsed_url.netloc: - username = invokeDialogueBox('Github Deploy', 'Enter your username', 'text') - password = invokeDialogueBox('Github Deploy', 'Enter your github token', 'password') - netloc = f"{username}:{password}@{parsed_url.hostname}" - new_url = urllib.parse.urlunparse(parsed_url._replace(netloc=netloc)) - subprocess.run(git_commands["git_set_origin_url"] + [new_url], cwd=deploy_location, check=True, text=True, capture_output=True) - print("Origin URL changed") - subprocess.run(git_commands["git_add"], cwd=deploy_location, check=True, text=True, capture_output=True) - subprocess.run(git_commands["git_commit"], cwd=deploy_location, check=True, text=True, capture_output=True) - subprocess.run(git_commands["git_push"], cwd=deploy_location, check=True, text=True, capture_output=True) - - -def create_404_page(deploy_location): - html_content = """ - - - - - Rangoio - - - - - - """ - - with open(f'{deploy_location}/404.html', 'w') as file: - file.write(html_content) - - print("404 page created successfully.") \ No newline at end of file diff --git a/backend/apimanager/publish_methods_github.py b/backend/apimanager/publish_methods_github.py new file mode 100644 index 0000000..f9abf84 --- /dev/null +++ b/backend/apimanager/publish_methods_github.py @@ -0,0 +1,157 @@ +from django.conf import settings +import os +import shutil +import subprocess +import urllib.parse + +from .dialogue_box import ( + draw_dialogue_box +) + + +def github_init(deploy_location, git_commands): + user_details_defined = git_check_user_details(deploy_location, git_commands) + if not user_details_defined: + git_set_user_details(deploy_location, git_commands) + + username, password = git_get_username_password() + remote_url = f'https://{username}:{password}@github.com/{username}/{username}.github.io.git' + + subprocess.run(git_commands["git_init"], cwd=deploy_location, check=True, text=True, capture_output=True) + subprocess.run(git_commands["git_add"], cwd=deploy_location, check=True, text=True, capture_output=True) + subprocess.run(git_commands["git_commit"], cwd=deploy_location, check=True, text=True, capture_output=True) + subprocess.run(git_commands["git_branch"], cwd=deploy_location, check=True, text=True, capture_output=True) + subprocess.run((git_commands["git_add_url"]).append(remote_url), cwd=deploy_location, check=True, text=True, + capture_output=True) + subprocess.run(git_commands["git_push"], cwd=deploy_location, check=True, text=True, capture_output=True) + + +def git_set_user_details(deploy_location, git_commands): + while True: + email = draw_dialogue_box('Github Deploy', 'Enter your github email', 'textbox') + name = draw_dialogue_box('Github Deploy', 'Enter your name', 'textbox') + input_confirmation = draw_dialogue_box( + 'Github Deploy', + 'Entered Information:\n'+'Name: '+name+'\n'+'Email: '+email+'\nPress "No" to re-enter details', + 'confirmation' + ) + if input_confirmation: + break + subprocess.run(git_commands["git_config_email"] + [email], cwd=deploy_location, check=True, text=True, + capture_output=True) + subprocess.run(git_commands["git_config_name"] + [name], cwd=deploy_location, check=True, + text=True, capture_output=True) + + +def git_existing_repo_setup(deploy_location, git_commands): + + while True: + repo_url = draw_dialogue_box('Github Deploy', 'Enter Repository URL', 'textbox') + input_confirmation = draw_dialogue_box( + 'Github Deploy', + 'Entered Information:\n'+'Repo URL: '+repo_url+'\nPress "No" to re-enter details', + 'confirmation' + ) + if input_confirmation: + break + if not repo_url.endswith('.git'): + repo_url = repo_url + '.git' + + dist_folder_name = ((repo_url.split('/')).pop()).removesuffix('.git') + subprocess.run(git_commands["git_clone"] + [repo_url], cwd=settings.DEPLOY_CONFIG["DEPLOY_LOCATION"], check=True, + text=True, capture_output=True) + git_update_viewable_ui(deploy_location, dist_folder_name) + + +def git_check_user_details(deploy_location, git_commands): + try: + subprocess.run(git_commands["git_config_name"], cwd=deploy_location, check=True, text=True, capture_output=True) + subprocess.run(git_commands["git_config_email"], cwd=deploy_location, check=True, text=True, capture_output=True) + return True + except: + return False + + +def git_update_viewable_ui(deploy_location, dist_folder_name, build_frontend=False): + shutil.move(deploy_location, f'{deploy_location}.temp') + if build_frontend: + subprocess.run(["npm", 'run', 'build:ghpages'], cwd=settings.DEPLOY_CONFIG["VIEWABLE_UI_LOCATION"], check=True, + text=True, capture_output=True) + shutil.move(f'{settings.DEPLOY_CONFIG["DEPLOY_LOCATION"]}/{dist_folder_name}', f'{deploy_location}') + shutil.copy(f'{deploy_location}.temp/index.html', deploy_location) + shutil.copy(f'{deploy_location}.temp/404.html', deploy_location) + shutil.copytree(f'{deploy_location}.temp/assets', f'{deploy_location}/assets', dirs_exist_ok=True) + if os.path.exists(f'{deploy_location}.temp/data'): + shutil.copytree(f'{deploy_location}.temp/data', f'{deploy_location}/data', dirs_exist_ok=True) + shutil.rmtree(f'{deploy_location}.temp') + + +def git_get_username_password(): + while True: + username = draw_dialogue_box('Github Deploy', 'Enter your username', 'textbox') + password = draw_dialogue_box('Github Deploy', 'Enter your github token', 'password') + input_confirmation = draw_dialogue_box( + 'Github Deploy', + 'Entered Information:\n'+'Username: '+username+'\n'+'Password: '+password*len(password) + + '\nPress "No" to re-enter details', + 'confirmation' + ) + if input_confirmation: + break + return username, password + + +def github_pages_deploy(deploy_location, git_commands): + user_details_defined = git_check_user_details(deploy_location, git_commands) + if not user_details_defined: + git_set_user_details(deploy_location, git_commands) + subprocess.run(git_commands["git_pull"], cwd=deploy_location, check=True, text=True, capture_output=True) + print("completed git pull") + origin_url_subprocess = subprocess.run(git_commands["git_get_origin_url"], cwd=deploy_location, check=True, + text=True, capture_output=True) + origin_url = origin_url_subprocess.stdout.strip() + print("Got origin as "+str(origin_url)) + parsed_url = urllib.parse.urlparse(origin_url) + print(parsed_url) + if not '@' in parsed_url.netloc: + username = draw_dialogue_box('Github Deploy', 'Enter your username', 'textbox') + password = draw_dialogue_box('Github Deploy', 'Enter your github token', 'password') + netloc = f"{username}:{password}@{parsed_url.hostname}" + new_url = urllib.parse.urlunparse(parsed_url._replace(netloc=netloc)) + subprocess.run(git_commands["git_set_origin_url"] + [new_url], cwd=deploy_location, check=True, text=True, + capture_output=True) + print("Origin URL changed") + subprocess.run(git_commands["git_add"], cwd=deploy_location, check=True, text=True, capture_output=True) + subprocess.run(git_commands["git_commit"], cwd=deploy_location, check=True, text=True, capture_output=True) + subprocess.run(git_commands["git_push"], cwd=deploy_location, check=True, text=True, capture_output=True) + + +def create_404_page(deploy_location): + html_content = """ + + + + + Rangoio + + + + + + """ + + with open(f'{deploy_location}/404.html', 'w') as file: + file.write(html_content) + + print("404 page created successfully.") + \ No newline at end of file diff --git a/backend/apimanager/publish_views.py b/backend/apimanager/publish_views.py index 883c5a2..3e1ee33 100644 --- a/backend/apimanager/publish_views.py +++ b/backend/apimanager/publish_views.py @@ -5,10 +5,16 @@ import ast from rest_framework import status from rest_framework.views import APIView from rest_framework.response import Response +from django.conf import settings from django.core.files.base import ContentFile -#Custom Imports -from .custom_storage import CustomStorage +from .custom_storage import ( + CustomStorage +) + +from .utilities import ( + copy_content +) from .models import ( UserData, @@ -22,10 +28,12 @@ from .publish_methods import ( github_deploy ) + class PublishMethods(APIView): def get(self, request, format=None): return Response(deployment_methods, status=status.HTTP_200_OK) + class Publish(APIView): def get(self, request, deploy_type, format=None): if deploy_type not in deployment_methods: @@ -37,7 +45,6 @@ class Publish(APIView): response = self.execute_deploy(deploy_type) return Response(response['message'], response['status']) - def delete_old_data(self): data_directory = 'deploy/data' @@ -52,7 +59,11 @@ class Publish(APIView): self.create_theme_data_json(UserData.objects.first(), storage) self.create_category_data_json(Category, storage) self.create_blog_data_json(Blog.objects.all(), storage) - self.merge_media() + copy_content( + settings.DEPLOY_CONFIG["EDITOR_MEDIA_LOCATION"], + settings.DEPLOY_CONFIG["EDITOR_DATA_LOCATION"], + 'folder', + ) def create_user_data_json(self, instance, storage): json_content = { @@ -90,7 +101,6 @@ class Publish(APIView): self.create_instance_data(instance_data, model_instance.objects.get(category_id=eachInstance.category_id), storage) self.save_json(categories, 'category/category-metadata.json', storage) - def create_blog_data_json(self, instance, storage): if not instance.exists(): pass @@ -107,18 +117,6 @@ class Publish(APIView): } self.save_json(instance_data, f'blog/{instance_data["id"]}/blog-data.json', storage) - def merge_media(self): - source_dir = 'media/data' - destination_dir = 'deploy/data' - if not os.path.exists(source_dir): - print("The source directory does not exist.") - else: - try: - shutil.copytree(source_dir, destination_dir, dirs_exist_ok=True) - print(f"Directory copied successfully from {source_dir} to {destination_dir}") - except Exception as e: - print(f"Error occurred: {e}") - def create_instance_data(self, instance_data, blogs_by_category_instance, storage): instance_data["blogMetadata"]=[] blogs = blogs_by_category_instance.blogs.all() @@ -141,6 +139,7 @@ class Publish(APIView): if storage.exists(file_name): storage.delete(file_name) storage.save(file_name, ContentFile(data_json.encode('utf-8'))) + def sanitize_media_link(self, string, content_type='element'): if not string: return '' @@ -149,8 +148,6 @@ class Publish(APIView): else: return string.replace('http://127.0.0.1:8000/media/data/', '') - - def execute_deploy(self, deploy_type): response = { 'message': 'Something failed', diff --git a/backend/apimanager/utilities.py b/backend/apimanager/utilities.py new file mode 100644 index 0000000..99ea8fb --- /dev/null +++ b/backend/apimanager/utilities.py @@ -0,0 +1,20 @@ +import os +import shutil + + +def copy_content(source, destination, content_type, copy_type='merge'): + if not os.path.exists(source): + print(f'The source {content_type} does not exist.') + else: + try: + if content_type == 'folder': + if copy_type == 'remove_and_copy' and os.path.exists(destination): + shutil.rmtree(destination) + shutil.copytree(source, destination, dirs_exist_ok=True) + else: + if copy_type == 'remove_and_copy' and os.path.exists(destination): + os.remove(destination) + shutil.copy(source, destination) + print(f'{content_type} copied successfully from {source} to {destination}') + except Exception as e: + print(f'Error occurred: {e}') \ No newline at end of file diff --git a/backend/backend/settings.py b/backend/backend/settings.py index 4da9fe9..1419ecf 100644 --- a/backend/backend/settings.py +++ b/backend/backend/settings.py @@ -43,7 +43,9 @@ INSTALLED_APPS = [ DEPLOY_CONFIG = { "VIEWABLE_UI_LOCATION": os.path.join(BASE_DIR, '../frontend/viewable-ui'), - "DEPLOY_LOCATION": os.path.join(BASE_DIR, '../frontend/viewable-ui/dist') + "DEPLOY_LOCATION": os.path.join(BASE_DIR, '../frontend/viewable-ui/dist'), + "EDITOR_DATA_LOCATION": os.path.join(BASE_DIR, 'deploy/data'), + "EDITOR_MEDIA_LOCATION": os.path.join(BASE_DIR, 'media/data') } REST_FRAMEWORK = {