diff --git a/cookbook/helper/AllAuthCustomAdapter.py b/cookbook/helper/AllAuthCustomAdapter.py index ba76bfca..64bf3c4d 100644 --- a/cookbook/helper/AllAuthCustomAdapter.py +++ b/cookbook/helper/AllAuthCustomAdapter.py @@ -9,7 +9,11 @@ class AllAuthCustomAdapter(DefaultAccountAdapter): """ Whether to allow sign ups. """ - allow_signups = super( - AllAuthCustomAdapter, self).is_open_for_signup(request) - # Override with setting, otherwise default to super. - return getattr(settings, 'ACCOUNT_ALLOW_SIGNUPS', allow_signups) + if request.resolver_match.view_name == 'account_signup': + return False + else: + return super(AllAuthCustomAdapter, self).is_open_for_signup(request) + + # disable password reset for now + def send_mail(self, template_prefix, email, context): + pass diff --git a/cookbook/helper/permission_helper.py b/cookbook/helper/permission_helper.py index 7093ac77..f6db4d81 100644 --- a/cookbook/helper/permission_helper.py +++ b/cookbook/helper/permission_helper.py @@ -119,7 +119,7 @@ def group_required(*groups_required): def in_groups(u): return has_group_permission(u, groups_required) - return user_passes_test(in_groups) + return user_passes_test(in_groups, login_url='view_no_group') class GroupRequiredMixin(object): @@ -138,8 +138,7 @@ class GroupRequiredMixin(object): ) return HttpResponseRedirect(reverse_lazy('index')) - return super(GroupRequiredMixin, self) \ - .dispatch(request, *args, **kwargs) + return super(GroupRequiredMixin, self).dispatch(request, *args, **kwargs) class OwnerRequiredMixin(object): diff --git a/cookbook/templates/account/login.html b/cookbook/templates/account/login.html new file mode 100644 index 00000000..6e3336e3 --- /dev/null +++ b/cookbook/templates/account/login.html @@ -0,0 +1,56 @@ +{% extends "base.html" %} +{% load crispy_forms_filters %} +{% load i18n %} + +{% load account socialaccount %} + +{% block title %}{% trans 'Login' %}{% endblock %} + +{% block content %} + +
+
+

{% trans "Sign In" %}

+
+
+ + +
+
+ +
+
+ + {% get_providers as socialaccount_providers %} + + {% if socialaccount_providers %} +
+
+
{% trans "Social Login" %}
+ {% trans 'You can use any of the following providers to sign in.' %} + +
+
+ + + + {% include "socialaccount/snippets/login_extra.html" %} + + +
+
+ {% endif %} + + +{% endblock %} \ No newline at end of file diff --git a/cookbook/templates/account/logout.html b/cookbook/templates/account/logout.html new file mode 100644 index 00000000..a4e29808 --- /dev/null +++ b/cookbook/templates/account/logout.html @@ -0,0 +1,22 @@ +{% extends "base.html" %} +{% load crispy_forms_filters %} +{% load i18n %} + +{% block title %}{% trans 'Sign Out' %}{% endblock %} + + +{% block content %} +

{% trans "Sign Out" %}

+ +

{% trans 'Are you sure you want to sign out?' %}

+ +
+ {% csrf_token %} + {% if redirect_field_value %} + + {% endif %} + +
+ + +{% endblock %} \ No newline at end of file diff --git a/cookbook/templates/account/password_reset.html b/cookbook/templates/account/password_reset.html new file mode 100644 index 00000000..a579ce9a --- /dev/null +++ b/cookbook/templates/account/password_reset.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} +{% load crispy_forms_filters %} +{% load i18n %} + +{% block title %}{% trans 'Password Reset' %}{% endblock %} + + +{% block content %} + {% trans 'Password reset is not implemented for the time being!' %} + +{% endblock %} \ No newline at end of file diff --git a/cookbook/templates/account/password_reset_done.html b/cookbook/templates/account/password_reset_done.html new file mode 100644 index 00000000..a579ce9a --- /dev/null +++ b/cookbook/templates/account/password_reset_done.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} +{% load crispy_forms_filters %} +{% load i18n %} + +{% block title %}{% trans 'Password Reset' %}{% endblock %} + + +{% block content %} + {% trans 'Password reset is not implemented for the time being!' %} + +{% endblock %} \ No newline at end of file diff --git a/cookbook/templates/registration/signup.html b/cookbook/templates/account/signup.html similarity index 100% rename from cookbook/templates/registration/signup.html rename to cookbook/templates/account/signup.html diff --git a/cookbook/templates/no_groups_info.html b/cookbook/templates/no_groups_info.html new file mode 100644 index 00000000..53b5f04c --- /dev/null +++ b/cookbook/templates/no_groups_info.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load static %} +{% load i18n %} + +{% block title %}{% trans "Offline" %}{% endblock %} + + +{% block content %} + +
+ +

{% trans 'No Permissions' %}

+
+ + {% trans 'You do not have any groups and therefor cannot use this application. Please contact your administrator.' %}
+ +
+ +{% endblock %} + diff --git a/cookbook/templates/registration/login.html b/cookbook/templates/registration/login.html deleted file mode 100644 index 40b0497e..00000000 --- a/cookbook/templates/registration/login.html +++ /dev/null @@ -1,52 +0,0 @@ -{% extends "base.html" %} -{% load i18n %} - -{% block title %}{% trans 'Login' %}{% endblock %} - -{% block content %} - - {% if form.errors %} - - - {% endif %} - - -
- {% csrf_token %} -
- -
- -
- -
- {% if form.username.errors %} - - {% endif %} -
- -
- -
- -
- {% if form.password.errors %} - - {% endif %} -
- - - -
-
- - -{% endblock %} \ No newline at end of file diff --git a/cookbook/urls.py b/cookbook/urls.py index ada427a5..ad6a7d98 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -39,6 +39,7 @@ router.register(r'supermarket', api.SupermarketViewSet) urlpatterns = [ path('', views.index, name='index'), path('setup/', views.setup, name='view_setup'), + path('no-group', views.no_groups, name='view_no_group'), path('signup/', views.signup, name='view_signup'), path('system/', views.system, name='view_system'), path('search/', views.search, name='view_search'), diff --git a/cookbook/views/views.py b/cookbook/views/views.py index ce3a9b0d..57cf0e31 100644 --- a/cookbook/views/views.py +++ b/cookbook/views/views.py @@ -23,7 +23,7 @@ from cookbook.filters import RecipeFilter from cookbook.forms import (CommentForm, Recipe, RecipeBookEntryForm, User, UserCreateForm, UserNameForm, UserPreference, UserPreferenceForm) -from cookbook.helper.permission_helper import group_required, share_link_valid +from cookbook.helper.permission_helper import group_required, share_link_valid, has_group_permission from cookbook.models import (Comment, CookLog, InviteLink, MealPlan, RecipeBook, RecipeBookEntry, ViewLog) from cookbook.tables import (CookLogTable, RecipeTable, RecipeTableSmall, @@ -34,8 +34,7 @@ from recipes.version import BUILD_REF, VERSION_NUMBER def index(request): if not request.user.is_authenticated: - if (User.objects.count() < 1 - and 'django.contrib.auth.backends.RemoteUserBackend' not in settings.AUTHENTICATION_BACKENDS): # noqa: E501 + if User.objects.count() < 1 and 'django.contrib.auth.backends.RemoteUserBackend' not in settings.AUTHENTICATION_BACKENDS: return HttpResponseRedirect(reverse_lazy('view_setup')) return HttpResponseRedirect(reverse_lazy('view_search')) try: @@ -45,15 +44,13 @@ def index(request): UserPreference.BOOKS: reverse_lazy('view_books'), } - return HttpResponseRedirect( - page_map.get(request.user.userpreference.default_page) - ) + return HttpResponseRedirect(page_map.get(request.user.userpreference.default_page)) except UserPreference.DoesNotExist: - return HttpResponseRedirect(reverse('account_login') + '?next=' + request.path) + return HttpResponseRedirect(reverse('view_no_group') + '?next=' + request.path) def search(request): - if request.user.is_authenticated: + if has_group_permission(request.user, ('guest',)): f = RecipeFilter( request.GET, queryset=Recipe.objects.all().order_by('name') @@ -88,19 +85,27 @@ def search(request): {'recipes': table, 'filter': f, 'last_viewed': last_viewed} ) else: - return HttpResponseRedirect(reverse('account_login') + '?next=' + request.path) + return HttpResponseRedirect(reverse('view_no_group') + '?next=' + request.path) + + +def no_groups(request): + if not request.user.is_authenticated: + return HttpResponseRedirect(reverse('account_login') + '?next=' + request.GET['next']) + if request.user.is_authenticated and request.user.groups.count() > 0: + return HttpResponseRedirect(reverse('index')) + return render(request, 'no_groups_info.html') def recipe_view(request, pk, share=None): recipe = get_object_or_404(Recipe, pk=pk) - if not request.user.is_authenticated and not share_link_valid(recipe, share): + if not has_group_permission(request.user, ('guest',)) and not share_link_valid(recipe, share): messages.add_message( request, messages.ERROR, _('You do not have the required permissions to view this page!') ) - return HttpResponseRedirect(reverse('account_login') + '?next=' + request.path) + return HttpResponseRedirect(reverse('view_no_group') + '?next=' + request.path) comments = Comment.objects.filter(recipe=recipe) @@ -197,22 +202,6 @@ def books(request): return render(request, 'books.html', {'book_list': book_list}) -def get_start_end_from_week(p_year, p_week): - first_day_of_week = datetime.strptime( - f'{p_year}-W{int(p_week) - 1}-1', "%Y-W%W-%w" - ).date() - last_day_of_week = first_day_of_week + timedelta(days=6.9) - return first_day_of_week, last_day_of_week - - -def get_days_from_week(start, end): - delta = end - start - days = [] - for i in range(delta.days + 1): - days.append(start + timedelta(days=i)) - return days - - @group_required('user') def meal_plan(request): return render(request, 'meal_plan.html', {}) @@ -466,7 +455,7 @@ def signup(request, token): form.fields['name'].initial = link.username form.fields['name'].disabled = True return render( - request, 'registration/signup.html', {'form': form, 'link': link} + request, 'account/signup.html', {'form': form, 'link': link} ) messages.add_message( diff --git a/docs/install/docker.md b/docs/install/docker.md index 3cb9c140..ba6421b0 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -32,6 +32,20 @@ Please make sure, if you run your image this way, to consult the [.env.template](https://raw.githubusercontent.com/vabene1111/recipes/master/.env.template) file in the GitHub repository to verify if additional environment variables are required for your setup. +### Versions + +There are different versions (tags) released on docker hub. + +- **latest** Default image. The one you should use if you don't know that you need anything else. +- **beta** Partially stable version that gets updated every now and then. Expect to have some problems. +- **develop** If you want the most bleeding edge version with potentially many breaking changes feel free to use this version (I don't recommend it!). +- **X.Y.Z** each released version has its own image. If you need to revert to an old version or want to make sure you stay on one specific use these tags. + +!!! danger "No Downgrading" + There is currently no way to migrate back to an older version as there is no mechanism to downgrade the database. + You could probably do it but I cannot help you with that. Choose wisely if you want to use the unstable images. + That said **beta** should usually be working if you like frequent updates and new stuff. + ## Docker Compose The main, and also recommended, installation option is to install this application using Docker Compose.