diff --git a/config/urls.py b/config/urls.py
index a6bb7c3..17d7f21 100644
--- a/config/urls.py
+++ b/config/urls.py
@@ -3,7 +3,6 @@
from django.contrib import admin
from django.urls import include, path
from django.views import defaults as default_views
-from django.views.decorators.cache import cache_page
from django.views.generic import TemplateView
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
from rest_framework.authtoken.views import obtain_auth_token
@@ -28,26 +27,26 @@
urlpatterns = [
# Podcast
- path("", cache_page(settings.CACHE_DEFAULT_TTL)(Core_HomepageView.as_view()), name="homepage"),
- path("player/", cache_page(settings.CACHE_DEFAULT_TTL)(Core_PlayerView.as_view()), name="player"),
- path("episode/", cache_page(settings.CACHE_SMART_TTL)(Core_EpisodeView.as_view()), name="episode"),
- path("settings/", cache_page(settings.CACHE_SMART_TTL)(Core_Settings.as_view()), name="settings"),
+ path("", Core_HomepageView.as_view(), name="homepage"),
+ path("player/", Core_PlayerView.as_view(), name="player"),
+ path("episode/", Core_EpisodeView.as_view(), name="episode"),
+ path("settings/", Core_Settings.as_view(), name="settings"),
path("playlist/", Core_PlaylistView.as_view(), name="playlist"),
path(
"add-datasource/",
- cache_page(settings.CACHE_DEFAULT_TTL)(Core_AddDataSourceView.as_view()),
+ Core_AddDataSourceView.as_view(),
name="add-datasource",
),
path(
"delete-datasource/",
- cache_page(settings.CACHE_DEFAULT_TTL)(Core_DeleteDataSourceView.as_view()),
+ Core_DeleteDataSourceView.as_view(),
name="delete-datasource",
),
*static("persist/", document_root=settings.PERSIST_AUDIO_ROOTDIR),
# Youtube Urls
path(
"yt/add-channel/",
- cache_page(settings.CACHE_DEFAULT_TTL)(Youtube_AddChannelView.as_view()),
+ Youtube_AddChannelView.as_view(),
name="yt-add-channel",
),
path(
@@ -57,7 +56,7 @@
),
path(
"yt/add-playlist/",
- cache_page(settings.CACHE_DEFAULT_TTL)(Youtube_AddPlaylistView.as_view()),
+ Youtube_AddPlaylistView.as_view(),
name="yt-add-playlist",
),
path(
@@ -68,7 +67,7 @@
# Spreaker Urls
path(
"sk/add-podcast/",
- cache_page(settings.CACHE_DEFAULT_TTL)(Spreaker_AddPodcastView.as_view()),
+ Spreaker_AddPodcastView.as_view(),
name="sk-add-podcast",
),
path(
diff --git a/core/templates/base.html b/core/templates/base.html
index f6806ff..eb69a74 100644
--- a/core/templates/base.html
+++ b/core/templates/base.html
@@ -65,19 +65,21 @@
Home (current)
-
- Episode
-
-
- Playlist
-
-
- Player
-
-
- {# URL provided by django-allauth/account/urls.py #}
- Sign Out
-
+ {% if user.is_authenticated %}
+
+ Episode
+
+
+ Playlist
+
+
+ Player
+
+
+ {# URL provided by django-allauth/account/urls.py #}
+ Sign Out
+
+ {% endif %}
diff --git a/core/templates/core/player.html b/core/templates/core/player.html
index 27f4bd2..a81e1b6 100644
--- a/core/templates/core/player.html
+++ b/core/templates/core/player.html
@@ -50,7 +50,7 @@
controls: true,
loop: false,
preload: "auto",
- poster: "/static/core/images/player.jpg",
+ poster: "/static/images/player.jpg",
audioPosterMode: true,
responsive: true,
aspectRatio: "16:9"
@@ -216,8 +216,7 @@ Player
Playlist
diff --git a/core/views.py b/core/views.py
index 6441795..f6df339 100644
--- a/core/views.py
+++ b/core/views.py
@@ -1,13 +1,17 @@
-from django.contrib.auth.mixins import LoginRequiredMixin
+from django.conf import settings
+from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.shortcuts import render
+from django.utils.decorators import method_decorator
from django.views import View
+from django.views.decorators.cache import cache_page
from core.models import DataSource, Episode, Playlist, Settings
# Create your views here.
-class Core_HomepageView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Core_HomepageView(View):
def get(self, request):
episode = Episode.objects.all().order_by("-episode_date")
playlist = Playlist.objects.all()
@@ -30,7 +34,8 @@ def get(self, request):
return render(request, "core/index.html", context=context)
-class Core_PlayerView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Core_PlayerView(View):
def get(self, request):
return render(request, "core/player.html")
@@ -41,17 +46,20 @@ def get(self, request):
return HttpResponse("ok")
-class Core_AddDataSourceView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Core_AddDataSourceView(View):
def get(self, request):
return render(request, "core/add_datasource.html")
-class Core_DeleteDataSourceView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Core_DeleteDataSourceView(View):
def get(self, request):
return render(request, "core/delete_datasource.html")
-class Core_Settings(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Core_Settings(View):
def get(self, request):
try:
total_size = Settings.objects.get(name="persist_total_size")
@@ -64,7 +72,8 @@ def get(self, request):
return render(request, "core/settings.html", context={"total_size": total_size, "total_count": total_count})
-class Core_EpisodeView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_SMART_TTL)], name="dispatch")
+class Core_EpisodeView(View):
def get(self, request):
episode_extended = []
playlist = Playlist.objects.all()
@@ -77,7 +86,8 @@ def get(self, request):
return render(request, "core/episode.html", context={"episodes": episode_extended})
-class Core_PlaylistView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_SMART_TTL)], name="dispatch")
+class Core_PlaylistView(View):
def get(self, request):
playlist = Playlist.objects.all()
return render(request, "core/playlist.html", context={"playlist": playlist})
diff --git a/docs/config.md b/docs/config.md
index 4d05c5f..e0cc14d 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -8,4 +8,6 @@
| CELERY_BROKER_URL | | redis://verbacap-redis:6379/0 | Redis URL for store a celery data |
| PERSIST_AUDIO_ROOTDIR | /persist/audio | /persist/audio | Persist Path to store the audio files |
| DJANGO_ACCOUNT_ALLOW_REGISTRATION | False | False | A boolean that turns on/off the user registration. |
-| DJANGO_ALLOWED_HOSTS | example.com | example.com | Django Allowed Hosts separated by comma |
\ No newline at end of file
+| DJANGO_ALLOWED_HOSTS | example.com | example.com | Django Allowed Hosts separated by comma |
+| DEBUG_INTERNALIPS | 127.0.0.1 | 127.0.0.1,192.168.1.1 | If Debug is enabled, you can add your ip below to show the debug toolbar |
+| CSRF_TRUSTED_ORIGINS | localhost,0.0.0.0,127.0.0.1 | 127.0.0.1 | CSRF_TRUSTED_ORIGINS exposed separated by comma |
\ No newline at end of file
diff --git a/docs/install.md b/docs/install.md
index 0dde4c7..2cd07f0 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -1,9 +1,10 @@
## Requirements
* Postgres 15+
-* Docker / Podman / ContainerD
+* Redis
+* Docker / Podman / ContainerD / Kubernetes
* HDD/SSD 2Gb +
-## Install on Docker like daemon
+## Install on Docker
1. Create a new user and assign full permission to the database in Postgres
2. Install `docker` and `docker-compose` ([More Info](https://docs.docker.com/engine/install/))
@@ -35,3 +36,32 @@ Insert the user and password of the super admin
7. Open your browser to [http://127.0.0.1:8080/](http://127.0.0.1:8080/)
8. Login with the super admin credential
+
+## Install via Helm
+1. Create a new user and assign full permission to the database in Postgres
+
+2. Install `helm` ([More Info](https://helm.sh/docs/intro/install/))
+
+3. Add the helm repository
+```
+helm repo add verbacap https://mirio.github.io/verbacap-chart/
+```
+
+4. Download the latest `values.yaml` and edit it based by your configuration
+```
+wget -q https://raw.githubusercontent.com/Mirio/verbacap-chart/main/charts/verbacap/values.yaml
+```
+
+5. Install it using Helm
+```
+helm install verbacap verbacap/verbacap -f values.yaml
+```
+
+6. Wait until the pod `verbacap-app` returns `Listening at: http://0.0.0.0:8000`
+
+7. Create a super admin user using:
+```
+kubectl exec -n NAMESPACE -it POD_ID /entrypoint.bash createadminuser
+```
+
+8. Open the browser and go to the web interface exposed.
\ No newline at end of file
diff --git a/spreaker/views.py b/spreaker/views.py
index 3f362de..93c17a3 100644
--- a/spreaker/views.py
+++ b/spreaker/views.py
@@ -1,7 +1,10 @@
-from django.contrib.auth.mixins import LoginRequiredMixin
+from django.conf import settings
+from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.shortcuts import render
+from django.utils.decorators import method_decorator
from django.views import View
+from django.views.decorators.cache import cache_page
from core.models import DataSource, Provider
from spreaker.forms import AddPodcastForm
@@ -9,7 +12,8 @@
# Create your views here.
-class Spreaker_AddPodcastView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Spreaker_AddPodcastView(View):
def get(self, request):
form = AddPodcastForm()
return render(request, "spreaker/add-podcast.html", context={"form": form})
@@ -45,7 +49,8 @@ def post(self, request):
)
-class Spreaker_DeletePodcastView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Spreaker_DeletePodcastView(View):
def get(self, request):
provider = Provider.objects.get(name="Spreaker")
return render(
diff --git a/verbacap/templates/account/login.html b/verbacap/templates/account/login.html
index ca18295..1a79cd9 100644
--- a/verbacap/templates/account/login.html
+++ b/verbacap/templates/account/login.html
@@ -8,7 +8,7 @@
{% translate "Sign In" %}
{% endblock head_title %}
{% block inner %}
- {% translate "Sign In" %}
+ {% translate "Sign In" %}
{% get_providers as socialaccount_providers %}
{% if socialaccount_providers %}
@@ -45,8 +45,10 @@
{% translate "Sign In" %}
name="{{ redirect_field_name }}"
value="{{ redirect_field_value }}" />
{% endif %}
- {% translate "Forgot Password?" %}
-
+
+
+
+
+
{% endblock inner %}
diff --git a/youtube/views.py b/youtube/views.py
index bc05d3d..7c02724 100644
--- a/youtube/views.py
+++ b/youtube/views.py
@@ -1,7 +1,10 @@
-from django.contrib.auth.mixins import LoginRequiredMixin
+from django.conf import settings
+from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.shortcuts import render
+from django.utils.decorators import method_decorator
from django.views import View
+from django.views.decorators.cache import cache_page
from core.models import DataSource, Provider
from youtube.forms import AddChannelForm, AddPlaylistForm
@@ -9,7 +12,8 @@
# Create your views here.
-class Youtube_AddPlaylistView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Youtube_AddPlaylistView(View):
def get(self, request):
form = AddPlaylistForm()
return render(request, "youtube/add-playlist.html", context={"form": form})
@@ -45,7 +49,8 @@ def post(self, request):
)
-class Youtube_DeletePlaylistView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Youtube_DeletePlaylistView(View):
def get(self, request):
provider = Provider.objects.get(name="Youtube-Playlist")
return render(
@@ -73,7 +78,8 @@ def post(self, request):
return render(request, "youtube/submit.html", context={"outmsg": outmsg}, status=status)
-class Youtube_AddChannelView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Youtube_AddChannelView(View):
def get(self, request):
form = AddChannelForm()
return render(request, "youtube/add-channel.html", context={"form": form})
@@ -109,7 +115,8 @@ def post(self, request):
)
-class Youtube_DeleteChannelView(LoginRequiredMixin, View):
+@method_decorator([login_required, cache_page(settings.CACHE_DEFAULT_TTL)], name="dispatch")
+class Youtube_DeleteChannelView(View):
def get(self, request):
provider = Provider.objects.get(name="Youtube")
return render(