From: Georgios Atheridis Date: Tue, 24 Jan 2023 13:39:27 +0000 (+0000) Subject: Changes to help with deployment X-Git-Url: https://git.atheridis.org/?a=commitdiff_plain;h=HEAD;p=ihaspeks%2Fclip-ranker.git Changes to help with deployment Made changes to settings so that it is easier to deploy the django application. Created instructions to deploy to Debian 11 and added extra help files to go along with the deployment. --- diff --git a/.gitignore b/.gitignore index b6e4761..e8796ee 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ coverage.xml local_settings.py db.sqlite3 db.sqlite3-journal +staticfiles/ # Flask stuff: instance/ diff --git a/README b/README new file mode 100644 index 0000000..6c5643c --- /dev/null +++ b/README @@ -0,0 +1,65 @@ +How to deploy on Debian 11 +========================== + + +Dependencies: +========================== +Python +-------------------------- +python3 + +Django +-------------------------- +python3-django +python3-django-allauth +python3-psycopg2 +python3-whitenoise +libjs-jquery + +Serving +-------------------------- +gunicorn +nginx + +SSL +-------------------------- +certbot +python3-certbot-nginx + +Postgres +-------------------------- +postgresql +postgresql-contrib + + +Installation Instructions: +========================== + 1. Install the necessary dependencies + 2. Create the directories; change example.com to your domain + a. /var/log/gunicorn/ + b. /var/run/gunicorn/ + c. /var/www/example.com/ + d. /usr/local/etc/gunicorn/ + 3. Copy example.com.service to /etc/systemd/system/ and change the name to your domain + 4. Edit the values of example.com.service by changing example.com to your domain + 5. Copy example.com.env to /usr/local/etc/gunicorn/ and change the name to your domain + 6. Edit the values of example.com.env + a. Generate a secret key by running generate_random_key.sh + 7. Change the user and group ownership of (2.abd) directories to www-data recursively + 8. In postgres create a user with a password and a database owned by the user + 9. Export your environment variables and inside core, run `python3 manage.py migrate` +10. Inside core, run `python3 manage.py createsuperuser` +11. Inside core, run `python3 manage.py collectstatic` +12. Copy the contents of core/ into /var/www/example.com/ +13. Copy example.com.nginx to /etc/nginx/sites-available/ and change the name +14. Edit the file example.com.nginx replacing example.com with your domain +15. Run certbot to verify your domain +16. Enable gunicorn `systemctl enable --now example.com.service` +17. Enable nginx `systemctl enable --now example.com.service` + + +Finalising Deployment: +========================== +1. Log into the admin panel of your website and edit / create site values in "Sites" +2. Create a Social Application. +3. Create a ResetData object. diff --git a/TODO b/TODO index 8308d21..d3533df 100644 --- a/TODO +++ b/TODO @@ -5,3 +5,17 @@ - Display clip info more clearly -- Clip comments? + +- Allow users to delete clips they've added during a block + +- Add left and right buttons on clips during ranking + +- Show a list of all clips during ranking with a button to quickly go to + +- A button to quickly go to the specific clip ranking from the results + +- Let users view clips uploaded by others and let them see the final page + +- Show historical rankings + +- If a clip has been ranked, show its ranking during the ranking phase diff --git a/core/core/settings.py b/core/core/settings.py index cac0464..b63bf9d 100644 --- a/core/core/settings.py +++ b/core/core/settings.py @@ -20,19 +20,22 @@ BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "django-insecure-!nzce=4gwub(n+!6@lh^vjl+m(*ibo42&gav2kvr@d4!$3ausi" # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = os.getenv("CLIP_RANKER_DEBUG", "") != "False" if DEBUG: import dotenv dotenv.load_dotenv() -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = os.getenv("CLIP_RANKER_ALLOWED_HOSTS", "").split(";") + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.getenv( + "CLIP_RANKER_SECRET_KEY", "04t8gx%o4!^1ae_@%3r@vb^=lx^r$%u*5&+88568$s%w)u1b@f" +) # Application definition @@ -62,6 +65,7 @@ MIDDLEWARE = [ "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", + "whitenoise.middleware.WhiteNoiseMiddleware", ] ROOT_URLCONF = "core.urls" @@ -92,12 +96,15 @@ WSGI_APPLICATION = "core.wsgi.application" DATABASES = { "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": BASE_DIR / "db.sqlite3", + "ENGINE": "django.db.backends.postgresql", + "NAME": os.getenv("CLIP_RANKER_DB_NAME"), + "USER": os.getenv("CLIP_RANKER_DB_USER"), + "PASSWORD": os.getenv("CLIP_RANKER_DB_PASS"), + "HOST": os.getenv("CLIP_RANKER_DB_HOST"), + "PORT": os.getenv("CLIP_RANKER_DB_PORT"), } } - # Password validation # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators @@ -132,9 +139,12 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.1/howto/static-files/ -STATIC_URL = "static/" +STATIC_URL = "/static/" + STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),) +STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") + # Default primary key field type # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field diff --git a/core/manager/migrations/0001_initial.py b/core/manager/migrations/0001_initial.py index a04301a..aac1326 100644 --- a/core/manager/migrations/0001_initial.py +++ b/core/manager/migrations/0001_initial.py @@ -1,5 +1,7 @@ -# Generated by Django 4.1.5 on 2023-01-22 12:47 +# Generated by Django 4.1.5 on 2023-01-25 14:32 +import datetime +from django.conf import settings from django.db import migrations, models import django.db.models.deletion @@ -9,16 +11,46 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ("socialaccount", "0003_extra_data_default_dict"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ + migrations.CreateModel( + name="ResetData", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("date_time", models.DateTimeField()), + ( + "end_date_time", + models.DateTimeField(default=datetime.datetime(2038, 1, 19, 3, 14)), + ), + ("max_clips", models.IntegerField(default=2)), + ("ranks", models.IntegerField(default=5)), + ("user_created_clip", models.BooleanField(default=True)), + ( + "clip_newer_than", + models.DateTimeField( + default=datetime.datetime(1970, 1, 1, 0, 0, 1) + ), + ), + ], + ), migrations.CreateModel( name="Clip", fields=[ ( "id", - models.CharField(max_length=100, primary_key=True, serialize=False), + models.CharField( + max_length=100, primary_key=True, serialize=False, unique=True + ), ), ("url", models.URLField(null=True)), ("embed_url", models.URLField(null=True)), @@ -34,13 +66,40 @@ class Migration(migrations.Migration): ("thumbnail_url", models.URLField(null=True)), ("duration", models.FloatField(null=True)), ("vod_offset", models.IntegerField(null=True)), + ("date_added", models.DateTimeField(null=True)), + ("rank", models.IntegerField(null=True)), + ( + "account", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.CreateModel( + name="AllowedChannel", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("broadcaster_id", models.CharField(max_length=100)), ( - "user", + "reset_data", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, - to="socialaccount.socialaccount", + to="manager.resetdata", ), ), ], + options={ + "unique_together": {("broadcaster_id", "reset_data")}, + }, ), ] diff --git a/core/manager/migrations/0002_rename_user_clip_account.py b/core/manager/migrations/0002_rename_user_clip_account.py deleted file mode 100644 index c1c4aaf..0000000 --- a/core/manager/migrations/0002_rename_user_clip_account.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 12:48 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0001_initial"), - ] - - operations = [ - migrations.RenameField( - model_name="clip", - old_name="user", - new_name="account", - ), - ] diff --git a/core/manager/migrations/0003_alter_clip_account.py b/core/manager/migrations/0003_alter_clip_account.py deleted file mode 100644 index 2d1f5c9..0000000 --- a/core/manager/migrations/0003_alter_clip_account.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 12:52 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ("manager", "0002_rename_user_clip_account"), - ] - - operations = [ - migrations.AlterField( - model_name="clip", - name="account", - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL - ), - ), - ] diff --git a/core/manager/migrations/0004_alter_clip_id.py b/core/manager/migrations/0004_alter_clip_id.py deleted file mode 100644 index 4709e22..0000000 --- a/core/manager/migrations/0004_alter_clip_id.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 13:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0003_alter_clip_account"), - ] - - operations = [ - migrations.AlterField( - model_name="clip", - name="id", - field=models.CharField( - max_length=100, primary_key=True, serialize=False, unique=True - ), - ), - ] diff --git a/core/manager/migrations/0005_myuser_alter_clip_account.py b/core/manager/migrations/0005_myuser_alter_clip_account.py deleted file mode 100644 index ffebc21..0000000 --- a/core/manager/migrations/0005_myuser_alter_clip_account.py +++ /dev/null @@ -1,50 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 13:30 - -from django.conf import settings -import django.contrib.auth.models -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ("auth", "0012_alter_user_first_name_max_length"), - ("manager", "0004_alter_clip_id"), - ] - - operations = [ - migrations.CreateModel( - name="MyUser", - fields=[ - ( - "user_ptr", - models.OneToOneField( - auto_created=True, - on_delete=django.db.models.deletion.CASCADE, - parent_link=True, - primary_key=True, - serialize=False, - to=settings.AUTH_USER_MODEL, - ), - ), - ("clip_amount", models.IntegerField(default=0)), - ], - options={ - "verbose_name": "user", - "verbose_name_plural": "users", - "abstract": False, - }, - bases=("auth.user",), - managers=[ - ("objects", django.contrib.auth.models.UserManager()), - ], - ), - migrations.AlterField( - model_name="clip", - name="account", - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, to="manager.myuser" - ), - ), - ] diff --git a/core/manager/migrations/0006_clip_date_added_alter_clip_account_delete_myuser.py b/core/manager/migrations/0006_clip_date_added_alter_clip_account_delete_myuser.py deleted file mode 100644 index f523efb..0000000 --- a/core/manager/migrations/0006_clip_date_added_alter_clip_account_delete_myuser.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 13:42 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ("manager", "0005_myuser_alter_clip_account"), - ] - - operations = [ - migrations.AddField( - model_name="clip", - name="date_added", - field=models.DateTimeField(null=True), - ), - migrations.AlterField( - model_name="clip", - name="account", - field=models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL - ), - ), - migrations.DeleteModel( - name="MyUser", - ), - ] diff --git a/core/manager/migrations/0007_resettime.py b/core/manager/migrations/0007_resettime.py deleted file mode 100644 index 6cafcbe..0000000 --- a/core/manager/migrations/0007_resettime.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 13:50 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0006_clip_date_added_alter_clip_account_delete_myuser"), - ] - - operations = [ - migrations.CreateModel( - name="ResetTime", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("date_time", models.DateTimeField()), - ], - ), - ] diff --git a/core/manager/migrations/0008_resettime_clip_amount.py b/core/manager/migrations/0008_resettime_clip_amount.py deleted file mode 100644 index c41dc35..0000000 --- a/core/manager/migrations/0008_resettime_clip_amount.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 13:58 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0007_resettime"), - ] - - operations = [ - migrations.AddField( - model_name="resettime", - name="clip_amount", - field=models.IntegerField(default=2), - ), - ] diff --git a/core/manager/migrations/0009_rename_clip_amount_resettime_max_clips.py b/core/manager/migrations/0009_rename_clip_amount_resettime_max_clips.py deleted file mode 100644 index d73a64e..0000000 --- a/core/manager/migrations/0009_rename_clip_amount_resettime_max_clips.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 14:00 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0008_resettime_clip_amount"), - ] - - operations = [ - migrations.RenameField( - model_name="resettime", - old_name="clip_amount", - new_name="max_clips", - ), - ] diff --git a/core/manager/migrations/0010_rename_resettime_resetdata.py b/core/manager/migrations/0010_rename_resettime_resetdata.py deleted file mode 100644 index f3619e5..0000000 --- a/core/manager/migrations/0010_rename_resettime_resetdata.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 14:02 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0009_rename_clip_amount_resettime_max_clips"), - ] - - operations = [ - migrations.RenameModel( - old_name="ResetTime", - new_name="ResetData", - ), - ] diff --git a/core/manager/migrations/0011_clip_rank.py b/core/manager/migrations/0011_clip_rank.py deleted file mode 100644 index 2c76633..0000000 --- a/core/manager/migrations/0011_clip_rank.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-22 16:24 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0010_rename_resettime_resetdata"), - ] - - operations = [ - migrations.AddField( - model_name="clip", - name="rank", - field=models.IntegerField(null=True), - ), - ] diff --git a/core/manager/migrations/0012_resetdata_ranks.py b/core/manager/migrations/0012_resetdata_ranks.py deleted file mode 100644 index a4c260f..0000000 --- a/core/manager/migrations/0012_resetdata_ranks.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-23 00:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0011_clip_rank"), - ] - - operations = [ - migrations.AddField( - model_name="resetdata", - name="ranks", - field=models.IntegerField(default=5), - ), - ] diff --git a/core/manager/migrations/0013_resetdata_clip_limit_to_channels_and_more.py b/core/manager/migrations/0013_resetdata_clip_limit_to_channels_and_more.py deleted file mode 100644 index 62a60d9..0000000 --- a/core/manager/migrations/0013_resetdata_clip_limit_to_channels_and_more.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-23 11:51 - -import datetime -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0012_resetdata_ranks"), - ] - - operations = [ - migrations.AddField( - model_name="resetdata", - name="clip_limit_to_channels", - field=models.JSONField(null=True), - ), - migrations.AddField( - model_name="resetdata", - name="clip_newer_than", - field=models.DateTimeField(default=datetime.datetime(1970, 1, 1, 0, 0, 1)), - ), - migrations.AddField( - model_name="resetdata", - name="user_created_clip", - field=models.BooleanField(default=True), - ), - ] diff --git a/core/manager/migrations/0014_allowedchannel.py b/core/manager/migrations/0014_allowedchannel.py deleted file mode 100644 index ec93b98..0000000 --- a/core/manager/migrations/0014_allowedchannel.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-23 12:03 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0013_resetdata_clip_limit_to_channels_and_more"), - ] - - operations = [ - migrations.CreateModel( - name="AllowedChannel", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("broadcaster_id", models.CharField(max_length=100)), - ( - "reset_data", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to="manager.resetdata", - ), - ), - ], - ), - ] diff --git a/core/manager/migrations/0015_remove_resetdata_clip_limit_to_channels_and_more.py b/core/manager/migrations/0015_remove_resetdata_clip_limit_to_channels_and_more.py deleted file mode 100644 index 3ad93f1..0000000 --- a/core/manager/migrations/0015_remove_resetdata_clip_limit_to_channels_and_more.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 4.1.5 on 2023-01-23 12:14 - -import datetime -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("manager", "0014_allowedchannel"), - ] - - operations = [ - migrations.RemoveField( - model_name="resetdata", - name="clip_limit_to_channels", - ), - migrations.AddField( - model_name="resetdata", - name="end_date_time", - field=models.DateTimeField(default=datetime.datetime(2038, 1, 19, 3, 14)), - ), - ] diff --git a/core/manager/request_clip.py b/core/manager/request_clip.py index cf7ccdb..a3d963e 100644 --- a/core/manager/request_clip.py +++ b/core/manager/request_clip.py @@ -127,9 +127,8 @@ def request_clip(user, clip: str): if not allowed_channels.exists(): raise ChannelNotAllowedError - if ( - reset_data.clip_newer_than - > datetime.datetime.strptime(data["created_at"], "%Y-%m-%dT%H:%M:%S%z") + if reset_data.clip_newer_than > datetime.datetime.strptime( + data["created_at"], "%Y-%m-%dT%H:%M:%S%z" ): raise ClipTooOldError diff --git a/core/manager/templates/manager/clip_viewer.html b/core/manager/templates/manager/clip_viewer.html index 3660ffa..c9d77fa 100644 --- a/core/manager/templates/manager/clip_viewer.html +++ b/core/manager/templates/manager/clip_viewer.html @@ -3,7 +3,7 @@

uploaded by: {{ video.account.username }}