mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 07:05:41 +00:00 
			
		
		
		
	@@ -13,7 +13,12 @@ from crispy_forms.helper import FormHelper
 | 
				
			|||||||
from crispy_forms.layout import Layout, Field
 | 
					from crispy_forms.layout import Layout, Field
 | 
				
			||||||
from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppendedText, StrictButton, Div
 | 
					from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppendedText, StrictButton, Div
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from allauth.account.forms import SignupForm, set_form_field_order
 | 
				
			||||||
 | 
					from allauth.account.adapter import DefaultAccountAdapter
 | 
				
			||||||
 | 
					from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from part.models import PartCategory
 | 
					from part.models import PartCategory
 | 
				
			||||||
 | 
					from common.models import InvenTreeSetting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HelperForm(forms.ModelForm):
 | 
					class HelperForm(forms.ModelForm):
 | 
				
			||||||
@@ -144,7 +149,6 @@ class EditUserForm(HelperForm):
 | 
				
			|||||||
            'username',
 | 
					            'username',
 | 
				
			||||||
            'first_name',
 | 
					            'first_name',
 | 
				
			||||||
            'last_name',
 | 
					            'last_name',
 | 
				
			||||||
            'email'
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -204,3 +208,76 @@ class SettingCategorySelectForm(forms.ModelForm):
 | 
				
			|||||||
                css_class='row',
 | 
					                css_class='row',
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# override allauth
 | 
				
			||||||
 | 
					class CustomSignupForm(SignupForm):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Override to use dynamic settings
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        kwargs['email_required'] = InvenTreeSetting.get_setting('LOGIN_MAIL_REQUIRED')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # check for two mail fields
 | 
				
			||||||
 | 
					        if InvenTreeSetting.get_setting('LOGIN_SIGNUP_MAIL_TWICE'):
 | 
				
			||||||
 | 
					            self.fields["email2"] = forms.EmailField(
 | 
				
			||||||
 | 
					                label=_("E-mail (again)"),
 | 
				
			||||||
 | 
					                widget=forms.TextInput(
 | 
				
			||||||
 | 
					                    attrs={
 | 
				
			||||||
 | 
					                        "type": "email",
 | 
				
			||||||
 | 
					                        "placeholder": _("E-mail address confirmation"),
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # check for two password fields
 | 
				
			||||||
 | 
					        if not InvenTreeSetting.get_setting('LOGIN_SIGNUP_PWD_TWICE'):
 | 
				
			||||||
 | 
					            self.fields.pop("password2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # reorder fields
 | 
				
			||||||
 | 
					        set_form_field_order(self, ["username", "email", "email2", "password1", "password2", ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def clean(self):
 | 
				
			||||||
 | 
					        cleaned_data = super().clean()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # check for two mail fields
 | 
				
			||||||
 | 
					        if InvenTreeSetting.get_setting('LOGIN_SIGNUP_MAIL_TWICE'):
 | 
				
			||||||
 | 
					            email = cleaned_data.get("email")
 | 
				
			||||||
 | 
					            email2 = cleaned_data.get("email2")
 | 
				
			||||||
 | 
					            if (email and email2) and email != email2:
 | 
				
			||||||
 | 
					                self.add_error("email2", _("You must type the same email each time."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return cleaned_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RegistratonMixin:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Mixin to check if registration should be enabled
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def is_open_for_signup(self, request):
 | 
				
			||||||
 | 
					        if InvenTreeSetting.get_setting('EMAIL_HOST', None) and InvenTreeSetting.get_setting('LOGIN_ENABLE_REG', True):
 | 
				
			||||||
 | 
					            return super().is_open_for_signup(request)
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CustomAccountAdapter(RegistratonMixin, DefaultAccountAdapter):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Override of adapter to use dynamic settings
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def send_mail(self, template_prefix, email, context):
 | 
				
			||||||
 | 
					        """only send mail if backend configured"""
 | 
				
			||||||
 | 
					        if InvenTreeSetting.get_setting('EMAIL_HOST', None):
 | 
				
			||||||
 | 
					            return super().send_mail(template_prefix, email, context)
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CustomSocialAccountAdapter(RegistratonMixin, DefaultSocialAccountAdapter):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Override of adapter to use dynamic settings
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def is_auto_signup_allowed(self, request, sociallogin):
 | 
				
			||||||
 | 
					        if InvenTreeSetting.get_setting('LOGIN_SIGNUP_SSO_AUTO', True):
 | 
				
			||||||
 | 
					            return super().is_auto_signup_allowed(request, sociallogin)
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,15 +64,15 @@ class AuthRequiredMiddleware(object):
 | 
				
			|||||||
            # No authorization was found for the request
 | 
					            # No authorization was found for the request
 | 
				
			||||||
            if not authorized:
 | 
					            if not authorized:
 | 
				
			||||||
                # A logout request will redirect the user to the login screen
 | 
					                # A logout request will redirect the user to the login screen
 | 
				
			||||||
                if request.path_info == reverse_lazy('logout'):
 | 
					                if request.path_info == reverse_lazy('account_logout'):
 | 
				
			||||||
                    return HttpResponseRedirect(reverse_lazy('login'))
 | 
					                    return HttpResponseRedirect(reverse_lazy('account_login'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                path = request.path_info
 | 
					                path = request.path_info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # List of URL endpoints we *do not* want to redirect to
 | 
					                # List of URL endpoints we *do not* want to redirect to
 | 
				
			||||||
                urls = [
 | 
					                urls = [
 | 
				
			||||||
                    reverse_lazy('login'),
 | 
					                    reverse_lazy('account_login'),
 | 
				
			||||||
                    reverse_lazy('logout'),
 | 
					                    reverse_lazy('account_logout'),
 | 
				
			||||||
                    reverse_lazy('admin:login'),
 | 
					                    reverse_lazy('admin:login'),
 | 
				
			||||||
                    reverse_lazy('admin:logout'),
 | 
					                    reverse_lazy('admin:logout'),
 | 
				
			||||||
                ]
 | 
					                ]
 | 
				
			||||||
@@ -80,7 +80,7 @@ class AuthRequiredMiddleware(object):
 | 
				
			|||||||
                if path not in urls and not path.startswith('/api/'):
 | 
					                if path not in urls and not path.startswith('/api/'):
 | 
				
			||||||
                    # Save the 'next' parameter to pass through to the login view
 | 
					                    # Save the 'next' parameter to pass through to the login view
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return redirect('%s?next=%s' % (reverse_lazy('login'), request.path))
 | 
					                    return redirect('%s?next=%s' % (reverse_lazy('account_login'), request.path))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        response = self.get_response(request)
 | 
					        response = self.get_response(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -249,6 +249,7 @@ INSTALLED_APPS = [
 | 
				
			|||||||
    'django.contrib.sessions',
 | 
					    'django.contrib.sessions',
 | 
				
			||||||
    'django.contrib.messages',
 | 
					    'django.contrib.messages',
 | 
				
			||||||
    'django.contrib.staticfiles',
 | 
					    'django.contrib.staticfiles',
 | 
				
			||||||
 | 
					    'django.contrib.sites',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # InvenTree apps
 | 
					    # InvenTree apps
 | 
				
			||||||
    'build.apps.BuildConfig',
 | 
					    'build.apps.BuildConfig',
 | 
				
			||||||
@@ -279,6 +280,10 @@ INSTALLED_APPS = [
 | 
				
			|||||||
    'error_report',                         # Error reporting in the admin interface
 | 
					    'error_report',                         # Error reporting in the admin interface
 | 
				
			||||||
    'django_q',
 | 
					    'django_q',
 | 
				
			||||||
    'formtools',                            # Form wizard tools
 | 
					    'formtools',                            # Form wizard tools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    'allauth',                              # Base app for SSO
 | 
				
			||||||
 | 
					    'allauth.account',                      # Extend user with accounts
 | 
				
			||||||
 | 
					    'allauth.socialaccount',                # Use 'social' providers
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MIDDLEWARE = CONFIG.get('middleware', [
 | 
					MIDDLEWARE = CONFIG.get('middleware', [
 | 
				
			||||||
@@ -298,7 +303,8 @@ MIDDLEWARE = CONFIG.get('middleware', [
 | 
				
			|||||||
MIDDLEWARE.append('error_report.middleware.ExceptionProcessor')
 | 
					MIDDLEWARE.append('error_report.middleware.ExceptionProcessor')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AUTHENTICATION_BACKENDS = CONFIG.get('authentication_backends', [
 | 
					AUTHENTICATION_BACKENDS = CONFIG.get('authentication_backends', [
 | 
				
			||||||
    'django.contrib.auth.backends.ModelBackend'
 | 
					    'django.contrib.auth.backends.ModelBackend',
 | 
				
			||||||
 | 
					    'allauth.account.auth_backends.AuthenticationBackend',      # SSO login via external providers
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If the debug toolbar is enabled, add the modules
 | 
					# If the debug toolbar is enabled, add the modules
 | 
				
			||||||
@@ -646,3 +652,34 @@ MESSAGE_TAGS = {
 | 
				
			|||||||
    messages.ERROR: 'alert alert-block alert-danger',
 | 
					    messages.ERROR: 'alert alert-block alert-danger',
 | 
				
			||||||
    messages.INFO: 'alert alert-block alert-info',
 | 
					    messages.INFO: 'alert alert-block alert-info',
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SITE_ID = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Load the allauth social backends
 | 
				
			||||||
 | 
					SOCIAL_BACKENDS = CONFIG.get('social_backends', [])
 | 
				
			||||||
 | 
					for app in SOCIAL_BACKENDS:
 | 
				
			||||||
 | 
					    INSTALLED_APPS.append(app)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SOCIALACCOUNT_PROVIDERS = CONFIG.get('social_providers', [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# settings for allauth
 | 
				
			||||||
 | 
					ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = get_setting('INVENTREE_LOGIN_CONFIRM_DAYS', CONFIG.get('login_confirm_days', 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ACCOUNT_LOGIN_ATTEMPTS_LIMIT = get_setting('INVENTREE_LOGIN_ATTEMPTS', CONFIG.get('login_attempts', 5))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# override forms / adapters
 | 
				
			||||||
 | 
					ACCOUNT_FORMS = {
 | 
				
			||||||
 | 
					    'login': 'allauth.account.forms.LoginForm',
 | 
				
			||||||
 | 
					    'signup': 'InvenTree.forms.CustomSignupForm',
 | 
				
			||||||
 | 
					    'add_email': 'allauth.account.forms.AddEmailForm',
 | 
				
			||||||
 | 
					    'change_password': 'allauth.account.forms.ChangePasswordForm',
 | 
				
			||||||
 | 
					    'set_password': 'allauth.account.forms.SetPasswordForm',
 | 
				
			||||||
 | 
					    'reset_password': 'allauth.account.forms.ResetPasswordForm',
 | 
				
			||||||
 | 
					    'reset_password_from_key': 'allauth.account.forms.ResetPasswordKeyForm',
 | 
				
			||||||
 | 
					    'disconnect': 'allauth.socialaccount.forms.DisconnectForm',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SOCIALACCOUNT_ADAPTER = 'InvenTree.forms.CustomSocialAccountAdapter'
 | 
				
			||||||
 | 
					ACCOUNT_ADAPTER = 'InvenTree.forms.CustomAccountAdapter'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,6 +111,10 @@ class URLTest(TestCase):
 | 
				
			|||||||
        if url.startswith("admin:"):
 | 
					        if url.startswith("admin:"):
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO can this be more elegant?
 | 
				
			||||||
 | 
					        if url.startswith("account_"):
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if pk:
 | 
					        if pk:
 | 
				
			||||||
            # We will assume that there is at least one item in the database
 | 
					            # We will assume that there is at least one item in the database
 | 
				
			||||||
            reverse(url, kwargs={"pk": 1})
 | 
					            reverse(url, kwargs={"pk": 1})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,6 @@ Passes URL lookup downstream to each app as required.
 | 
				
			|||||||
from django.conf.urls import url, include
 | 
					from django.conf.urls import url, include
 | 
				
			||||||
from django.urls import path
 | 
					from django.urls import path
 | 
				
			||||||
from django.contrib import admin
 | 
					from django.contrib import admin
 | 
				
			||||||
from django.contrib.auth import views as auth_views
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from company.urls import company_urls
 | 
					from company.urls import company_urls
 | 
				
			||||||
from company.urls import manufacturer_part_urls
 | 
					from company.urls import manufacturer_part_urls
 | 
				
			||||||
@@ -38,7 +37,7 @@ from rest_framework.documentation import include_docs_urls
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from .views import auth_request
 | 
					from .views import auth_request
 | 
				
			||||||
from .views import IndexView, SearchView, DatabaseStatsView
 | 
					from .views import IndexView, SearchView, DatabaseStatsView
 | 
				
			||||||
from .views import SettingsView, EditUserView, SetPasswordView
 | 
					from .views import SettingsView, EditUserView, SetPasswordView, CustomEmailView, CustomConnectionsView, CustomPasswordResetFromKeyView
 | 
				
			||||||
from .views import CurrencyRefreshView
 | 
					from .views import CurrencyRefreshView
 | 
				
			||||||
from .views import AppearanceSelectView, SettingCategorySelectView
 | 
					from .views import AppearanceSelectView, SettingCategorySelectView
 | 
				
			||||||
from .views import DynamicJsView
 | 
					from .views import DynamicJsView
 | 
				
			||||||
@@ -143,9 +142,6 @@ urlpatterns = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
 | 
					    url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    url(r'^login/?', auth_views.LoginView.as_view(), name='login'),
 | 
					 | 
				
			||||||
    url(r'^logout/', auth_views.LogoutView.as_view(template_name='registration/logged_out.html'), name='logout'),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    url(r'^settings/', include(settings_urls)),
 | 
					    url(r'^settings/', include(settings_urls)),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    url(r'^edit-user/', EditUserView.as_view(), name='edit-user'),
 | 
					    url(r'^edit-user/', EditUserView.as_view(), name='edit-user'),
 | 
				
			||||||
@@ -154,7 +150,6 @@ urlpatterns = [
 | 
				
			|||||||
    url(r'^admin/error_log/', include('error_report.urls')),
 | 
					    url(r'^admin/error_log/', include('error_report.urls')),
 | 
				
			||||||
    url(r'^admin/shell/', include('django_admin_shell.urls')),
 | 
					    url(r'^admin/shell/', include('django_admin_shell.urls')),
 | 
				
			||||||
    url(r'^admin/', admin.site.urls, name='inventree-admin'),
 | 
					    url(r'^admin/', admin.site.urls, name='inventree-admin'),
 | 
				
			||||||
    url(r'accounts/', include('django.contrib.auth.urls')),
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    url(r'^index/', IndexView.as_view(), name='index'),
 | 
					    url(r'^index/', IndexView.as_view(), name='index'),
 | 
				
			||||||
    url(r'^search/', SearchView.as_view(), name='search'),
 | 
					    url(r'^search/', SearchView.as_view(), name='search'),
 | 
				
			||||||
@@ -166,6 +161,13 @@ urlpatterns = [
 | 
				
			|||||||
    url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
 | 
					    url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    url(r'^markdownx/', include('markdownx.urls')),
 | 
					    url(r'^markdownx/', include('markdownx.urls')),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Single Sign On / allauth
 | 
				
			||||||
 | 
					    # overrides of urlpatterns
 | 
				
			||||||
 | 
					    url(r'^accounts/email/', CustomEmailView.as_view(), name='account_email'),
 | 
				
			||||||
 | 
					    url(r'^accounts/social/connections/', CustomConnectionsView.as_view(), name='socialaccount_connections'),
 | 
				
			||||||
 | 
					    url(r"^accounts/password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$", CustomPasswordResetFromKeyView.as_view(), name="account_reset_password_from_key"),
 | 
				
			||||||
 | 
					    url(r'^accounts/', include('allauth.urls')),  # included urlpatterns
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Server running in "DEBUG" mode?
 | 
					# Server running in "DEBUG" mode?
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,13 +17,19 @@ from django.urls import reverse_lazy
 | 
				
			|||||||
from django.shortcuts import redirect
 | 
					from django.shortcuts import redirect
 | 
				
			||||||
from django.conf import settings
 | 
					from django.conf import settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
 | 
					from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.views import View
 | 
					from django.views import View
 | 
				
			||||||
from django.views.generic import ListView, DetailView, CreateView, FormView, DeleteView, UpdateView
 | 
					from django.views.generic import ListView, DetailView, CreateView, FormView, DeleteView, UpdateView
 | 
				
			||||||
from django.views.generic.base import RedirectView, TemplateView
 | 
					from django.views.generic.base import RedirectView, TemplateView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from djmoney.contrib.exchange.models import ExchangeBackend, Rate
 | 
					from djmoney.contrib.exchange.models import ExchangeBackend, Rate
 | 
				
			||||||
 | 
					from allauth.account.forms import AddEmailForm
 | 
				
			||||||
 | 
					from allauth.socialaccount.forms import DisconnectForm
 | 
				
			||||||
 | 
					from allauth.account.models import EmailAddress
 | 
				
			||||||
 | 
					from allauth.account.views import EmailView, PasswordResetFromKeyView
 | 
				
			||||||
 | 
					from allauth.socialaccount.views import ConnectionsView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from common.settings import currency_code_default, currency_codes
 | 
					from common.settings import currency_code_default, currency_codes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from part.models import Part, PartCategory
 | 
					from part.models import Part, PartCategory
 | 
				
			||||||
@@ -810,9 +816,47 @@ class SettingsView(TemplateView):
 | 
				
			|||||||
        except:
 | 
					        except:
 | 
				
			||||||
            ctx["locale_stats"] = {}
 | 
					            ctx["locale_stats"] = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Forms and context for allauth
 | 
				
			||||||
 | 
					        ctx['add_email_form'] = AddEmailForm
 | 
				
			||||||
 | 
					        ctx["can_add_email"] = EmailAddress.objects.can_add_email(self.request.user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Form and context for allauth social-accounts
 | 
				
			||||||
 | 
					        ctx["request"] = self.request
 | 
				
			||||||
 | 
					        ctx['social_form'] = DisconnectForm(request=self.request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return ctx
 | 
					        return ctx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AllauthOverrides(LoginRequiredMixin):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Override allauths views to always redirect to success_url
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def get(self, request, *args, **kwargs):
 | 
				
			||||||
 | 
					        # always redirect to settings
 | 
				
			||||||
 | 
					        return HttpResponseRedirect(self.success_url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CustomEmailView(AllauthOverrides, EmailView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Override of allauths EmailView to always show the settings but leave the functions allow
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    success_url = reverse_lazy("settings")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CustomConnectionsView(AllauthOverrides, ConnectionsView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Override of allauths ConnectionsView to always show the settings but leave the functions allow
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    success_url = reverse_lazy("settings")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CustomPasswordResetFromKeyView(PasswordResetFromKeyView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Override of allauths PasswordResetFromKeyView to always show the settings but leave the functions allow
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    success_url = reverse_lazy("account_login")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CurrencyRefreshView(RedirectView):
 | 
					class CurrencyRefreshView(RedirectView):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    POST endpoint to refresh / update exchange rates
 | 
					    POST endpoint to refresh / update exchange rates
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -830,6 +830,50 @@ class InvenTreeSetting(BaseInvenTreeSetting):
 | 
				
			|||||||
            'default': True,
 | 
					            'default': True,
 | 
				
			||||||
            'validator': bool,
 | 
					            'validator': bool,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # login / SSO
 | 
				
			||||||
 | 
					        'LOGIN_ENABLE_PWD_FORGOT': {
 | 
				
			||||||
 | 
					            'name': _('Enable password forgot'),
 | 
				
			||||||
 | 
					            'description': _('Enable password forgot function on the login-pages'),
 | 
				
			||||||
 | 
					            'default': True,
 | 
				
			||||||
 | 
					            'validator': bool,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'LOGIN_ENABLE_REG': {
 | 
				
			||||||
 | 
					            'name': _('Enable registration'),
 | 
				
			||||||
 | 
					            'description': _('Enable self-registration for users on the login-pages'),
 | 
				
			||||||
 | 
					            'default': False,
 | 
				
			||||||
 | 
					            'validator': bool,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'LOGIN_ENABLE_SSO': {
 | 
				
			||||||
 | 
					            'name': _('Enable SSO'),
 | 
				
			||||||
 | 
					            'description': _('Enable SSO on the login-pages'),
 | 
				
			||||||
 | 
					            'default': False,
 | 
				
			||||||
 | 
					            'validator': bool,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'LOGIN_MAIL_REQUIRED': {
 | 
				
			||||||
 | 
					            'name': _('E-Mail required'),
 | 
				
			||||||
 | 
					            'description': _('Require user to supply mail on signup'),
 | 
				
			||||||
 | 
					            'default': False,
 | 
				
			||||||
 | 
					            'validator': bool,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'LOGIN_SIGNUP_SSO_AUTO': {
 | 
				
			||||||
 | 
					            'name': _('Auto-fill SSO users'),
 | 
				
			||||||
 | 
					            'description': _('Automatically fill out user-details from SSO account-data'),
 | 
				
			||||||
 | 
					            'default': True,
 | 
				
			||||||
 | 
					            'validator': bool,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'LOGIN_SIGNUP_MAIL_TWICE': {
 | 
				
			||||||
 | 
					            'name': _('Mail twice'),
 | 
				
			||||||
 | 
					            'description': _('On signup ask users twice for their mail'),
 | 
				
			||||||
 | 
					            'default': False,
 | 
				
			||||||
 | 
					            'validator': bool,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        'LOGIN_SIGNUP_PWD_TWICE': {
 | 
				
			||||||
 | 
					            'name': _('Password twice'),
 | 
				
			||||||
 | 
					            'description': _('On signup ask users twice for their password'),
 | 
				
			||||||
 | 
					            'default': True,
 | 
				
			||||||
 | 
					            'validator': bool,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -141,6 +141,14 @@ static_root: '/home/inventree/data/static'
 | 
				
			|||||||
#  - git
 | 
					#  - git
 | 
				
			||||||
#  - ssh
 | 
					#  - ssh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Login configuration
 | 
				
			||||||
 | 
					# How long do confirmation mail last?
 | 
				
			||||||
 | 
					# Use environment variable INVENTREE_LOGIN_CONFIRM_DAYS
 | 
				
			||||||
 | 
					#login_confirm_days: 3
 | 
				
			||||||
 | 
					# How many wrong login attempts are permitted?
 | 
				
			||||||
 | 
					# Use environment variable INVENTREE_LOGIN_ATTEMPTS
 | 
				
			||||||
 | 
					#login_attempts: 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Permit custom authentication backends
 | 
					# Permit custom authentication backends
 | 
				
			||||||
#authentication_backends:
 | 
					#authentication_backends:
 | 
				
			||||||
#  - 'django.contrib.auth.backends.ModelBackend'
 | 
					#  - 'django.contrib.auth.backends.ModelBackend'
 | 
				
			||||||
@@ -157,3 +165,14 @@ static_root: '/home/inventree/data/static'
 | 
				
			|||||||
#  - 'django.contrib.messages.middleware.MessageMiddleware'
 | 
					#  - 'django.contrib.messages.middleware.MessageMiddleware'
 | 
				
			||||||
#  - 'django.middleware.clickjacking.XFrameOptionsMiddleware'
 | 
					#  - 'django.middleware.clickjacking.XFrameOptionsMiddleware'
 | 
				
			||||||
#  - 'InvenTree.middleware.AuthRequiredMiddleware'
 | 
					#  - 'InvenTree.middleware.AuthRequiredMiddleware'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add SSO login-backends
 | 
				
			||||||
 | 
					# social_backends:
 | 
				
			||||||
 | 
					#  - 'allauth.socialaccount.providers.keycloak'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add specific settings
 | 
				
			||||||
 | 
					# social_providers:
 | 
				
			||||||
 | 
					#   keycloak:
 | 
				
			||||||
 | 
					#     KEYCLOAK_URL: 'https://keycloak.custom/auth'
 | 
				
			||||||
 | 
					#     KEYCLOAK_REALM: 'master'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -351,6 +351,12 @@ def object_link(url_name, pk, ref):
 | 
				
			|||||||
    return mark_safe('<b><a href="{}">{}</a></b>'.format(ref_url, ref))
 | 
					    return mark_safe('<b><a href="{}">{}</a></b>'.format(ref_url, ref))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@register.simple_tag()
 | 
				
			||||||
 | 
					def mail_configured():
 | 
				
			||||||
 | 
					    """ Return if mail is configured """
 | 
				
			||||||
 | 
					    return bool(settings.EMAIL_HOST)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class I18nStaticNode(StaticNode):
 | 
					class I18nStaticNode(StaticNode):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    custom StaticNode
 | 
					    custom StaticNode
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								InvenTree/templates/InvenTree/settings/login.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								InvenTree/templates/InvenTree/settings/login.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					{% extends "panel.html" %}
 | 
				
			||||||
 | 
					{% load i18n %}
 | 
				
			||||||
 | 
					{% load inventree_extras %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block label %}login{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block heading %}
 | 
				
			||||||
 | 
					{% trans "Login Settings" %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<table class='table table-striped table-condensed'>
 | 
				
			||||||
 | 
					    {% include "InvenTree/settings/header.html" %}
 | 
				
			||||||
 | 
					    <tbody>
 | 
				
			||||||
 | 
					        {% include "InvenTree/settings/setting.html" with key="LOGIN_ENABLE_REG" icon="fa-info-circle" %}
 | 
				
			||||||
 | 
					        {% include "InvenTree/settings/setting.html" with key="LOGIN_ENABLE_SSO" icon="fa-info-circle" %}
 | 
				
			||||||
 | 
					        {% include "InvenTree/settings/setting.html" with key="LOGIN_ENABLE_PWD_FORGOT" icon="fa-info-circle" %}
 | 
				
			||||||
 | 
					        {% include "InvenTree/settings/setting.html" with key="LOGIN_MAIL_REQUIRED" icon="fa-info-circle" %}
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					            <td>{% trans 'Signup' %}</td>
 | 
				
			||||||
 | 
					            <td colspan='4'></td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					        {% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_MAIL_TWICE" icon="fa-info-circle" %}
 | 
				
			||||||
 | 
					        {% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_PWD_TWICE" icon="fa-info-circle" %}
 | 
				
			||||||
 | 
					        {% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_SSO_AUTO" icon="fa-info-circle" %}
 | 
				
			||||||
 | 
					    </tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
@@ -68,6 +68,12 @@
 | 
				
			|||||||
        </a>
 | 
					        </a>
 | 
				
			||||||
    </li>
 | 
					    </li>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <li class='list-group-item' title='{% trans "Login" %}'>
 | 
				
			||||||
 | 
					        <a href='#' class='nav-toggle' id='select-login'>
 | 
				
			||||||
 | 
					            <span class='fas fa-fingerprint'></span> {% trans "Login" %}
 | 
				
			||||||
 | 
					        </a>
 | 
				
			||||||
 | 
					    </li>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <li class='list-group-item' title='{% trans "Barcodes" %}'>
 | 
					    <li class='list-group-item' title='{% trans "Barcodes" %}'>
 | 
				
			||||||
        <a href='#' class='nav-toggle' id='select-barcodes'>
 | 
					        <a href='#' class='nav-toggle' id='select-barcodes'>
 | 
				
			||||||
            <span class='fas fa-qrcode'></span> {% trans "Barcodes" %}
 | 
					            <span class='fas fa-qrcode'></span> {% trans "Barcodes" %}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@
 | 
				
			|||||||
{% if user.is_staff %}
 | 
					{% if user.is_staff %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% include "InvenTree/settings/global.html" %}
 | 
					{% include "InvenTree/settings/global.html" %}
 | 
				
			||||||
 | 
					{% include "InvenTree/settings/login.html" %}
 | 
				
			||||||
{% include "InvenTree/settings/barcode.html" %}
 | 
					{% include "InvenTree/settings/barcode.html" %}
 | 
				
			||||||
{% include "InvenTree/settings/currencies.html" %}
 | 
					{% include "InvenTree/settings/currencies.html" %}
 | 
				
			||||||
{% include "InvenTree/settings/report.html" %}
 | 
					{% include "InvenTree/settings/report.html" %}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{% load i18n %}
 | 
					{% load i18n %}
 | 
				
			||||||
{% load inventree_extras %}
 | 
					{% load inventree_extras %}
 | 
				
			||||||
 | 
					{% load socialaccount %}
 | 
				
			||||||
 | 
					{% load crispy_forms_tags %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block label %}account{% endblock %}
 | 
					{% block label %}account{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -10,6 +12,8 @@
 | 
				
			|||||||
{% endblock %}
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block content %}
 | 
					{% block content %}
 | 
				
			||||||
 | 
					{% mail_configured as mail_conf %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class='btn-group' style='float: right;'>
 | 
					<div class='btn-group' style='float: right;'>
 | 
				
			||||||
    <div class='btn btn-primary' type='button' id='edit-user' title='{% trans "Edit User Information" %}'>
 | 
					    <div class='btn btn-primary' type='button' id='edit-user' title='{% trans "Edit User Information" %}'>
 | 
				
			||||||
        <span class='fas fa-user-cog'></span> {% trans "Edit" %}
 | 
					        <span class='fas fa-user-cog'></span> {% trans "Edit" %}
 | 
				
			||||||
@@ -32,12 +36,119 @@
 | 
				
			|||||||
        <td>{% trans "Last Name" %}</td>
 | 
					        <td>{% trans "Last Name" %}</td>
 | 
				
			||||||
        <td>{{ user.last_name }}</td>
 | 
					        <td>{{ user.last_name }}</td>
 | 
				
			||||||
    </tr>
 | 
					    </tr>
 | 
				
			||||||
    <tr>
 | 
					 | 
				
			||||||
        <td>{% trans "Email Address" %}</td>
 | 
					 | 
				
			||||||
        <td>{{ user.email }}</td>
 | 
					 | 
				
			||||||
    </tr>
 | 
					 | 
				
			||||||
</table>
 | 
					</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class='panel-heading'>
 | 
				
			||||||
 | 
					    <h4>{% trans "E-Mail" %}</h4>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
					    {% if user.emailaddress_set.all %}
 | 
				
			||||||
 | 
					    <p>{% trans 'The following e-mail addresses are associated with your account:' %}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <form action="{% url 'account_email' %}" class="email_list" method="post">
 | 
				
			||||||
 | 
					    {% csrf_token %}
 | 
				
			||||||
 | 
					        <fieldset class="blockLabels">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {% for emailaddress in user.emailaddress_set.all %}
 | 
				
			||||||
 | 
					            <div class="ctrlHolder">
 | 
				
			||||||
 | 
					                <label for="email_radio_{{forloop.counter}}" class="{% if emailaddress.primary %}primary_email{%endif%}">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <input id="email_radio_{{forloop.counter}}" type="radio" name="email" {% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{%endif %} value="{{emailaddress.email}}"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            {{ emailaddress.email }}
 | 
				
			||||||
 | 
					                {% if emailaddress.verified %}
 | 
				
			||||||
 | 
					                <span class="verified">{% trans "Verified" %}</span>
 | 
				
			||||||
 | 
					                {% else %}
 | 
				
			||||||
 | 
					                <span class="unverified">{% trans "Unverified" %}</span>
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					                {% if emailaddress.primary %}<span class="primary">{% trans "Primary" %}</span>{% endif %}
 | 
				
			||||||
 | 
					            </label>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        {% endfor %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="buttonHolder">
 | 
				
			||||||
 | 
					            <button class="btn btn-primary secondaryAction" type="submit" name="action_primary" >{% trans 'Make Primary' %}</button>
 | 
				
			||||||
 | 
					            <button class="btn btn-primary secondaryAction" type="submit" name="action_send" {% if not mail_conf %}disabled{% endif %}>{% trans 'Re-send Verification' %}</button>
 | 
				
			||||||
 | 
					            <button class="btn btn-primary primaryAction" type="submit" name="action_remove" >{% trans 'Remove' %}</button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        </fieldset>
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% else %}
 | 
				
			||||||
 | 
					    <p><strong>{% trans 'Warning:'%}</strong>
 | 
				
			||||||
 | 
					        {% trans "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if can_add_email %}
 | 
				
			||||||
 | 
					        <br>
 | 
				
			||||||
 | 
					        <h4>{% trans "Add E-mail Address" %}</h4>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <form method="post" action="{% url 'account_email' %}" class="add_email">
 | 
				
			||||||
 | 
					            {% csrf_token %}
 | 
				
			||||||
 | 
					            {{ add_email_form|crispy }}
 | 
				
			||||||
 | 
					            <button class="btn btn-primary" name="action_add" type="submit">{% trans "Add E-mail" %}</button>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					    <br>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class='panel-heading'>
 | 
				
			||||||
 | 
					    <h4>{% trans "Social Accounts" %}</h4>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
					    {% if social_form.accounts %}
 | 
				
			||||||
 | 
					    <p>{% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}</p>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <form method="post" action="{% url 'socialaccount_connections' %}">
 | 
				
			||||||
 | 
					    {% csrf_token %}
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    <fieldset>
 | 
				
			||||||
 | 
					    {% if social_form.non_field_errors %}
 | 
				
			||||||
 | 
					    <div id="errorMsg">{{ social_form.non_field_errors }}</div>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    {% for base_account in social_form.accounts %}
 | 
				
			||||||
 | 
					    {% with base_account.get_provider_account as account %}
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					    <label for="id_account_{{ base_account.id }}">
 | 
				
			||||||
 | 
					    <input id="id_account_{{ base_account.id }}" type="radio" name="account" value="{{ base_account.id }}"/>
 | 
				
			||||||
 | 
					    <span class="socialaccount_provider {{ base_account.provider }} {{ account.get_brand.id }}">
 | 
				
			||||||
 | 
					        <span class='brand-icon' brand_name='{{account.get_brand.id}}'></span>{{account.get_brand.name}}</span>
 | 
				
			||||||
 | 
					    {{ account }}
 | 
				
			||||||
 | 
					    </label>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    {% endwith %}
 | 
				
			||||||
 | 
					    {% endfor %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					    <button class="btn btn-primary" type="submit">{% trans 'Remove' %}</button>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    </fieldset>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    {% else %}
 | 
				
			||||||
 | 
					    <p>{% trans 'You currently have no social network accounts connected to this account.' %}</p>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <br>
 | 
				
			||||||
 | 
					    <h4>{% trans 'Add a 3rd Party Account' %}</h4>
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					    {% include "socialaccount/snippets/provider_list.html" with process="connect" %}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    {% include "socialaccount/snippets/login_extra.html" %}
 | 
				
			||||||
 | 
					    <br>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class='panel-heading'>
 | 
					<div class='panel-heading'>
 | 
				
			||||||
    <h4>{% trans "Theme Settings" %}</h4>
 | 
					    <h4>{% trans "Theme Settings" %}</h4>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
@@ -105,4 +216,18 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block js_ready %}
 | 
				
			||||||
 | 
					(function() {
 | 
				
			||||||
 | 
					  var message = "{% trans 'Do you really want to remove the selected e-mail address?' %}";
 | 
				
			||||||
 | 
					  var actions = document.getElementsByName('action_remove');
 | 
				
			||||||
 | 
					  if (actions.length) {
 | 
				
			||||||
 | 
					    actions[0].addEventListener("click", function(e) {
 | 
				
			||||||
 | 
					      if (! confirm(message)) {
 | 
				
			||||||
 | 
					        e.preventDefault();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					})();
 | 
				
			||||||
{% endblock %}
 | 
					{% endblock %}
 | 
				
			||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
{% load static %}
 | 
					{% load static %}
 | 
				
			||||||
{% load i18n %}
 | 
					{% load i18n %}
 | 
				
			||||||
{% load crispy_forms_tags %}
 | 
					 | 
				
			||||||
{% load inventree_extras %}
 | 
					{% load inventree_extras %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
@@ -12,57 +11,79 @@
 | 
				
			|||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
					<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- CSS -->
 | 
					<!-- CSS -->
 | 
				
			||||||
 | 
					<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
 | 
				
			||||||
 | 
					<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
 | 
					<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
 | 
				
			||||||
<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
 | 
					<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
 | 
					<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
 | 
					<link rel="stylesheet" href="{% get_color_theme_css user.get_username %}">
 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/fontawesome.js' %}"></script>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
    .login-error {
 | 
					 | 
				
			||||||
        color: #F88;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
<title>
 | 
					<title>
 | 
				
			||||||
    {% inventree_title %} 
 | 
					    {% inventree_title %} | {% block head_title %}{% endblock %}
 | 
				
			||||||
</title>
 | 
					</title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block extra_head %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<body class='login-screen'>
 | 
					<body class='login-screen'>
 | 
				
			||||||
 | 
					    <!-- 
 | 
				
			||||||
 | 
					        Background Image Attribution: https://unsplash.com/photos/Ixvv3YZkd7w
 | 
				
			||||||
 | 
					    -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class='main body-wrapper login-screen'>
 | 
					    <div class='main body-wrapper login-screen'>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div class='login-container'>
 | 
					        <div class='login-container'>
 | 
				
			||||||
        <div class="row">
 | 
					        <div class="row">
 | 
				
			||||||
            <div class='container-fluid'>
 | 
					            <div class='container-fluid'>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <div class='clearfix content-heading login-header'>
 | 
					                <div class='clearfix content-heading login-header'>
 | 
				
			||||||
                    <img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
 | 
					                    <img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
 | 
				
			||||||
                    <span><h3>{% inventree_title %} </h3></span>
 | 
					                    <span><h3>{% inventree_title %}</h3></span>
 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                    <hr>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <div class='container-fluid'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <p>{% trans "Forgotten your password?" %}</p>
 | 
					 | 
				
			||||||
                        <p>{% trans "Enter your email address below." %}</p>
 | 
					 | 
				
			||||||
                        <p>{% trans "An email will be sent with password reset instructions." %}</p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <form method="POST">
 | 
					 | 
				
			||||||
                            {% csrf_token %}
 | 
					 | 
				
			||||||
                            {{ form.as_p }}                    
 | 
					 | 
				
			||||||
                            <button class="btn btn-primary" type="submit">{% trans "Send email" %}</button>
 | 
					 | 
				
			||||||
                        </form>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					                <hr>
 | 
				
			||||||
 | 
					                <div class='container-fluid'>{% block content %}{% endblock %}</div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</div>
 | 
					        {% block extra_body %}
 | 
				
			||||||
 | 
					        {% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</body>
 | 
					        {% include 'notification.html' %}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- Scripts -->
 | 
				
			||||||
 | 
					<script type="text/javascript" src="{% static 'script/jquery_3.3.1_jquery.min.js' %}"></script>
 | 
				
			||||||
 | 
					<!-- general InvenTree -->
 | 
				
			||||||
 | 
					<script type='text/javascript' src="{% static 'script/inventree/notification.js' %}"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- dynamic javascript templates -->
 | 
				
			||||||
 | 
					<script type='text/javascript' src="{% url 'inventree.js' %}"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
 | 
				
			||||||
 | 
					<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>
 | 
				
			||||||
 | 
					<script type='text/javascript' src="{% static 'fontawesome/js/fontawesome.js' %}"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script type='text/javascript'>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(document).ready(function () {
 | 
				
			||||||
 | 
					    // notifications
 | 
				
			||||||
 | 
					    {% if messages %}
 | 
				
			||||||
 | 
					    {% for message in messages %}
 | 
				
			||||||
 | 
					    showAlertOrCache('alert-info', '{{message}}', true);
 | 
				
			||||||
 | 
					    {% endfor %}
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    showCachedAlerts();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inventreeDocReady();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										31
									
								
								InvenTree/templates/account/email_confirm.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								InvenTree/templates/account/email_confirm.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					{% extends "account/base.html" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% load i18n %}
 | 
				
			||||||
 | 
					{% load account %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block head_title %}{% trans "Confirm E-mail Address" %}{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					<h1>{% trans "Confirm E-mail Address" %}</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if confirmation %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% user_display confirmation.email_address.user as user_display %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>{% blocktrans with confirmation.email_address.email as email %}Please confirm that <a href="mailto:{{ email }}">{{ email }}</a> is an e-mail address for user {{ user_display }}.{% endblocktrans %}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<form method="post" action="{% url 'account_confirm_email' confirmation.key %}">
 | 
				
			||||||
 | 
					{% csrf_token %}
 | 
				
			||||||
 | 
					    <button type="submit" class="btn btn-primary btn-block">{% trans 'Confirm' %}</button>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% else %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% url 'account_email' as email_url %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>{% blocktrans %}This e-mail confirmation link expired or is invalid. Please <a href="{{ email_url }}">issue a new e-mail confirmation request</a>.{% endblocktrans %}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
							
								
								
									
										52
									
								
								InvenTree/templates/account/login.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								InvenTree/templates/account/login.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					{% extends "account/base.html" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% load i18n account socialaccount crispy_forms_tags inventree_extras %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block head_title %}{% trans "Sign In" %}{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% settings_value 'LOGIN_ENABLE_REG' as enable_reg %}
 | 
				
			||||||
 | 
					{% settings_value 'LOGIN_ENABLE_PWD_FORGOT' as enable_pwd_forgot %}
 | 
				
			||||||
 | 
					{% settings_value 'LOGIN_ENABLE_SSO' as enable_sso %}
 | 
				
			||||||
 | 
					{% mail_configured as mail_conf %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h1>{% trans "Sign In" %}</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if enable_reg %}
 | 
				
			||||||
 | 
					{% get_providers as socialaccount_providers %}
 | 
				
			||||||
 | 
					{% if socialaccount_providers %}
 | 
				
			||||||
 | 
					<p>{% blocktrans with site.name as site_name %}Please sign in with one
 | 
				
			||||||
 | 
					of your existing third party accounts or  <a class="btn btn-primary btn-small" href="{{ signup_url }}">sign up</a>
 | 
				
			||||||
 | 
					for a account and sign in below:{% endblocktrans %}</p>
 | 
				
			||||||
 | 
					{% else %}
 | 
				
			||||||
 | 
					<p>{% blocktrans %}If you have not created an account yet, then please
 | 
				
			||||||
 | 
					<a href="{{ signup_url }}">sign up</a> first.{% endblocktrans %}</p>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<form class="login" method="POST" action="{% url 'account_login' %}">
 | 
				
			||||||
 | 
					  {% csrf_token %}
 | 
				
			||||||
 | 
					  {{ form|crispy }}
 | 
				
			||||||
 | 
					  {% if redirect_field_value %}
 | 
				
			||||||
 | 
					  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
 | 
				
			||||||
 | 
					  {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <div class="btn-toolbar">
 | 
				
			||||||
 | 
					    <button class="btn btn-primary col-md-8" type="submit">{% trans "Sign In" %}</button>
 | 
				
			||||||
 | 
					    {% if mail_conf and enable_pwd_forgot %}
 | 
				
			||||||
 | 
					    <a class="btn btn-primary" href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if enable_sso %}
 | 
				
			||||||
 | 
					<br>
 | 
				
			||||||
 | 
					<h4 class="text-center">{% trans 'or use SSO' %}</h4>
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
					  {% include "socialaccount/snippets/provider_list.html" with process="login" %}
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% include "socialaccount/snippets/login_extra.html" %}
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
							
								
								
									
										21
									
								
								InvenTree/templates/account/logout.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								InvenTree/templates/account/logout.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					{% extends "account/base.html" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% load i18n %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block head_title %}{% trans "Sign Out" %}{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					<h1>{% trans "Sign Out" %}</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>{% trans 'Are you sure you want to sign out?' %}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<form method="post" action="{% url 'account_logout' %}">
 | 
				
			||||||
 | 
					  {% csrf_token %}
 | 
				
			||||||
 | 
					  {% if redirect_field_value %}
 | 
				
			||||||
 | 
					  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/>
 | 
				
			||||||
 | 
					  {% endif %}
 | 
				
			||||||
 | 
					  <button type="submit" class="btn btn-primary btn-block">{% trans 'Sign Out' %}</button>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
							
								
								
									
										30
									
								
								InvenTree/templates/account/password_reset.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								InvenTree/templates/account/password_reset.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					{% extends "account/base.html" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% load i18n account crispy_forms_tags inventree_extras %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block head_title %}{% trans "Password Reset" %}{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% settings_value 'LOGIN_ENABLE_PWD_FORGOT' as enable_pwd_forgot %}
 | 
				
			||||||
 | 
					{% mail_configured as mail_conf %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <h1>{% trans "Password Reset" %}</h1>
 | 
				
			||||||
 | 
					    {% if user.is_authenticated %}
 | 
				
			||||||
 | 
					    {% include "account/snippets/already_logged_in.html" %}
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if mail_conf and enable_pwd_forgot %}
 | 
				
			||||||
 | 
					    <p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <form method="POST" action="{% url 'account_reset_password' %}" class="password_reset">
 | 
				
			||||||
 | 
					        {% csrf_token %}
 | 
				
			||||||
 | 
					        {{ form|crispy }}
 | 
				
			||||||
 | 
					        <input type="submit" class="btn btn-primary btn-block" value="{% trans 'Reset My Password' %}" />
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					    {% else %}
 | 
				
			||||||
 | 
					    <div class='alert alert-block alert-danger'>
 | 
				
			||||||
 | 
					        <p>{% trans "This function is currently disabled. Please contact an administrator." %}</p>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
							
								
								
									
										23
									
								
								InvenTree/templates/account/password_reset_from_key.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								InvenTree/templates/account/password_reset_from_key.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					{% extends "account/base.html" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% load i18n crispy_forms_tags %}
 | 
				
			||||||
 | 
					{% block head_title %}{% trans "Change Password" %}{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					    <h1>{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if token_fail %}
 | 
				
			||||||
 | 
					        {% url 'account_reset_password' as passwd_reset_url %}
 | 
				
			||||||
 | 
					        <p>{% blocktrans %}The password reset link was invalid, possibly because it has already been used.  Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktrans %}</p>
 | 
				
			||||||
 | 
					    {% else %}
 | 
				
			||||||
 | 
					        {% if form %}
 | 
				
			||||||
 | 
					            <form method="POST" action="{{ action_url }}">
 | 
				
			||||||
 | 
					                {% csrf_token %}
 | 
				
			||||||
 | 
					                {{ form|crispy }}
 | 
				
			||||||
 | 
					                <input type="submit" name="action" class="btn btn-primary btn-block" value="{% trans 'change password' %}"/>
 | 
				
			||||||
 | 
					            </form>
 | 
				
			||||||
 | 
					        {% else %}
 | 
				
			||||||
 | 
					            <p>{% trans 'Your password is now changed.' %}</p>
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
							
								
								
									
										40
									
								
								InvenTree/templates/account/signup.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								InvenTree/templates/account/signup.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					{% extends "account/base.html" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% load i18n crispy_forms_tags inventree_extras %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block head_title %}{% trans "Signup" %}{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					{% settings_value 'LOGIN_ENABLE_REG' as enable_reg %}
 | 
				
			||||||
 | 
					{% settings_value 'LOGIN_ENABLE_SSO' as enable_sso %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h1>{% trans "Sign Up" %}</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>{% blocktrans %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if enable_reg %}
 | 
				
			||||||
 | 
					<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
 | 
				
			||||||
 | 
					  {% csrf_token %}
 | 
				
			||||||
 | 
					  {{ form|crispy }}
 | 
				
			||||||
 | 
					  {% if redirect_field_value %}
 | 
				
			||||||
 | 
					  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
 | 
				
			||||||
 | 
					  {% endif %}
 | 
				
			||||||
 | 
					  <button type="submit" class="btn btn-primary btn-block">{% trans "Sign Up" %}</button>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if enable_sso %}
 | 
				
			||||||
 | 
					<br>
 | 
				
			||||||
 | 
					<h4>{% trans 'Or use a SSO-provider for signup' %}</h4>
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
					    {% include "socialaccount/snippets/provider_list.html" with process="login" %}
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% include "socialaccount/snippets/login_extra.html" %}
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% else %}
 | 
				
			||||||
 | 
					<div class='alert alert-block alert-danger'>
 | 
				
			||||||
 | 
					    <p>{% trans "This function is currently disabled. Please contact an administrator." %}</p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
@@ -177,6 +177,11 @@ function inventreeDocReady() {
 | 
				
			|||||||
            'ui-autocomplete': 'dropdown-menu search-menu',
 | 
					            'ui-autocomplete': 'dropdown-menu search-menu',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Generate brand-icons
 | 
				
			||||||
 | 
					    $('.brand-icon').each(function(i, obj) {
 | 
				
			||||||
 | 
					        loadBrandIcon($(this), $(this).attr('brand_name'));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function isFileTransfer(transfer) {
 | 
					function isFileTransfer(transfer) {
 | 
				
			||||||
@@ -275,3 +280,13 @@ function inventreeLoad(name, defaultValue) {
 | 
				
			|||||||
        return value;
 | 
					        return value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function loadBrandIcon(element, name) {
 | 
				
			||||||
 | 
					    // check if icon exists
 | 
				
			||||||
 | 
					    var icon = window.FontAwesome.icon({prefix: 'fab', iconName: name});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (icon) {
 | 
				
			||||||
 | 
					        // add icon to button
 | 
				
			||||||
 | 
					        element.addClass('fab fa-' + name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,9 +82,9 @@
 | 
				
			|||||||
                {% if user.is_staff %}
 | 
					                {% if user.is_staff %}
 | 
				
			||||||
                <li><a href="/admin/"><span class="fas fa-user"></span> {% trans "Admin" %}</a></li>
 | 
					                <li><a href="/admin/"><span class="fas fa-user"></span> {% trans "Admin" %}</a></li>
 | 
				
			||||||
                {% endif %}
 | 
					                {% endif %}
 | 
				
			||||||
                <li><a href="{% url 'logout' %}"><span class="fas fa-sign-out-alt"></span> {% trans "Logout" %}</a></li>
 | 
					                <li><a href="{% url 'account_logout' %}"><span class="fas fa-sign-out-alt"></span> {% trans "Logout" %}</a></li>
 | 
				
			||||||
                {% else %}
 | 
					                {% else %}
 | 
				
			||||||
                <li><a href="{% url 'login' %}"><span class="fas fa-sign-in-alt"></span> {% trans "Login" %}</a></li>
 | 
					                <li><a href="{% url 'account_login' %}"><span class="fas fa-sign-in-alt"></span> {% trans "Login" %}</a></li>
 | 
				
			||||||
                {% endif %}
 | 
					                {% endif %}
 | 
				
			||||||
                <hr>
 | 
					                <hr>
 | 
				
			||||||
                <li><a href="{% url 'settings' %}"><span class="fas fa-cog"></span> {% trans "Settings" %}</a></li>
 | 
					                <li><a href="{% url 'settings' %}"><span class="fas fa-cog"></span> {% trans "Settings" %}</a></li>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,59 +1,10 @@
 | 
				
			|||||||
{% load static %}
 | 
					{% extends "registration/logged_out.html" %}
 | 
				
			||||||
{% load i18n %}
 | 
					{% load i18n %}
 | 
				
			||||||
{% load crispy_forms_tags %}
 | 
					 | 
				
			||||||
{% load inventree_extras %}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!DOCTYPE html>
 | 
					{% block content %}
 | 
				
			||||||
<html lang="en">
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- Required meta tags -->
 | 
					<p>{% translate "You were logged out successfully." %}</p>
 | 
				
			||||||
<meta charset="utf-8">
 | 
					 | 
				
			||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!-- CSS -->
 | 
					<p><a href="{% url 'admin:index' %}">{% translate 'Log in again' %}</a></p>
 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
 | 
					{% endblock %}
 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/fontawesome.js' %}"></script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
    .login-error {
 | 
					 | 
				
			||||||
        color: #F88;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<title>
 | 
					 | 
				
			||||||
    {% inventree_title %} 
 | 
					 | 
				
			||||||
</title>
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<body class='login-screen'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <div class='main body-wrapper login-screen'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div class='login-container'>
 | 
					 | 
				
			||||||
        <div class="row">
 | 
					 | 
				
			||||||
            <div class='container-fluid'>
 | 
					 | 
				
			||||||
                <div class='clearfix content-heading login-header'>
 | 
					 | 
				
			||||||
                    <img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
 | 
					 | 
				
			||||||
                    <span><h3>{% inventree_title %} </h3></span>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                    <hr>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <div class='container-fluid'>
 | 
					 | 
				
			||||||
                        <p>{% trans "You have been logged out" %}</p>
 | 
					 | 
				
			||||||
                        <p><a href='{% url "login" %}'>{% trans "Return to login screen" %}</a></p>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,105 +0,0 @@
 | 
				
			|||||||
{% load static %}
 | 
					 | 
				
			||||||
{% load i18n %}
 | 
					 | 
				
			||||||
{% load inventree_extras %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang="en">
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- Required meta tags -->
 | 
					 | 
				
			||||||
<meta charset="utf-8">
 | 
					 | 
				
			||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- CSS -->
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/fontawesome.js' %}"></script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
    .login-error {
 | 
					 | 
				
			||||||
        color: #F88;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<title>
 | 
					 | 
				
			||||||
    {% inventree_title %} 
 | 
					 | 
				
			||||||
</title>
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<body class='login-screen'>
 | 
					 | 
				
			||||||
<!-- 
 | 
					 | 
				
			||||||
    Background Image Attribution: https://unsplash.com/photos/Ixvv3YZkd7w
 | 
					 | 
				
			||||||
-->
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class='main body-wrapper login-screen'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div class='login-container'>
 | 
					 | 
				
			||||||
        <div class="row">
 | 
					 | 
				
			||||||
            <div class='container-fluid'>
 | 
					 | 
				
			||||||
                <div class='clearfix content-heading login-header'>
 | 
					 | 
				
			||||||
                    <img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
 | 
					 | 
				
			||||||
                    <span><h3>{% inventree_title %} </h3></span>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                    <hr>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <div class='container-fluid'>
 | 
					 | 
				
			||||||
                    <form method="post" action=''>
 | 
					 | 
				
			||||||
                        {% csrf_token %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        {% load crispy_forms_tags %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <div id="div_id_username" class="form-group">
 | 
					 | 
				
			||||||
                            <label for="id_username" class="control-label  requiredField">{% trans "Username" %}<span class="asteriskField">*</span></label>
 | 
					 | 
				
			||||||
                            <div class="controls ">
 | 
					 | 
				
			||||||
                                <div class='input-group'>
 | 
					 | 
				
			||||||
                                    <div class='input-group-addon'>
 | 
					 | 
				
			||||||
                                        <span class='fas fa-user'></span>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                    <input type="text" name="username" autofocus autocapitalize="none" autocomplete="username" maxlength="150" class="textinput textInput form-control" required id="id_username" placeholder='{% trans "Enter username" %}'>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </div>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <div id="div_id_password" class="form-group">
 | 
					 | 
				
			||||||
                            <label for="id_password" class="control-label requiredField">{% trans "Password" %}<span class="asteriskField">*</span></label>
 | 
					 | 
				
			||||||
                            <div class='controls'>
 | 
					 | 
				
			||||||
                                <div class="input-group">
 | 
					 | 
				
			||||||
                                    <div class='input-group-addon'>
 | 
					 | 
				
			||||||
                                        <span class='fas fa-key'></span>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                    <input type="password" name="password" autocomplete="current-password" class="textinput textInput form-control" required id="id_password" placeholder='{% trans "Enter password" %}'>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </div>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        {% if form.errors %}
 | 
					 | 
				
			||||||
                        <div class='login-error'>
 | 
					 | 
				
			||||||
                            <strong>{% trans "Username / password combination is incorrect" %}</strong>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        {% endif %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <hr>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <button class='pull-right btn btn-primary login-button' type="submit">{% trans "Login" %}</button>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    </form>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    {% if email_configured %}
 | 
					 | 
				
			||||||
                    <hr><br>
 | 
					 | 
				
			||||||
                    <p>{% trans "Forgotten your password?" %} - <a href='{% url "password_reset" %}'>{% trans "Click here to reset" %}</a></p>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                    {% endif %}
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
@@ -1,59 +0,0 @@
 | 
				
			|||||||
{% load static %}
 | 
					 | 
				
			||||||
{% load i18n %}
 | 
					 | 
				
			||||||
{% load crispy_forms_tags %}
 | 
					 | 
				
			||||||
{% load inventree_extras %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang="en">
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- Required meta tags -->
 | 
					 | 
				
			||||||
<meta charset="utf-8">
 | 
					 | 
				
			||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- CSS -->
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/fontawesome.js' %}"></script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
    .login-error {
 | 
					 | 
				
			||||||
        color: #F88;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<title>
 | 
					 | 
				
			||||||
    {% inventree_title %} 
 | 
					 | 
				
			||||||
</title>
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<body class='login-screen'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <div class='main body-wrapper login-screen'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div class='login-container'>
 | 
					 | 
				
			||||||
        <div class="row">
 | 
					 | 
				
			||||||
            <div class='container-fluid'>
 | 
					 | 
				
			||||||
                <div class='clearfix content-heading login-header'>
 | 
					 | 
				
			||||||
                    <img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
 | 
					 | 
				
			||||||
                    <span><h3>{% inventree_title %} </h3></span>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                    <hr>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <div class='container-fluid'>
 | 
					 | 
				
			||||||
                        <p>{% trans "Password reset complete" %}</p>
 | 
					 | 
				
			||||||
                        <p><a href='{% url "login" %}'>{% trans "Return to login screen" %}</a></p>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
@@ -1,69 +0,0 @@
 | 
				
			|||||||
{% load static %}
 | 
					 | 
				
			||||||
{% load i18n %}
 | 
					 | 
				
			||||||
{% load crispy_forms_tags %}
 | 
					 | 
				
			||||||
{% load inventree_extras %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang="en">
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- Required meta tags -->
 | 
					 | 
				
			||||||
<meta charset="utf-8">
 | 
					 | 
				
			||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- CSS -->
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/fontawesome.js' %}"></script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
    .login-error {
 | 
					 | 
				
			||||||
        color: #F88;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<title>
 | 
					 | 
				
			||||||
    {% inventree_title %} 
 | 
					 | 
				
			||||||
</title>
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<body class='login-screen'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <div class='main body-wrapper login-screen'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div class='login-container'>
 | 
					 | 
				
			||||||
        <div class="row">
 | 
					 | 
				
			||||||
            <div class='container-fluid'>
 | 
					 | 
				
			||||||
                <div class='clearfix content-heading login-header'>
 | 
					 | 
				
			||||||
                    <img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
 | 
					 | 
				
			||||||
                    <span><h3>{% inventree_title %} </h3></span>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                    <hr>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    <div class='container-fluid'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        {% if validlink %}
 | 
					 | 
				
			||||||
                        <h3>{% trans "Change password" %}</h3>
 | 
					 | 
				
			||||||
                        <form method="post">
 | 
					 | 
				
			||||||
                          {% csrf_token %}
 | 
					 | 
				
			||||||
                          {{ form.as_p }}
 | 
					 | 
				
			||||||
                          <button class="btn btn-primary" type="submit">{% trans "Change password" %}</button>
 | 
					 | 
				
			||||||
                        </form>
 | 
					 | 
				
			||||||
                      {% else %}
 | 
					 | 
				
			||||||
                        <p>
 | 
					 | 
				
			||||||
                            {% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}
 | 
					 | 
				
			||||||
                        </p>
 | 
					 | 
				
			||||||
                      {% endif %}
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
@@ -1,65 +0,0 @@
 | 
				
			|||||||
{% load static %}
 | 
					 | 
				
			||||||
{% load i18n %}
 | 
					 | 
				
			||||||
{% load crispy_forms_tags %}
 | 
					 | 
				
			||||||
{% load inventree_extras %}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang="en">
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- Required meta tags -->
 | 
					 | 
				
			||||||
<meta charset="utf-8">
 | 
					 | 
				
			||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- CSS -->
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
 | 
					 | 
				
			||||||
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/solid.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/brands.js' %}"></script>
 | 
					 | 
				
			||||||
<script type='text/javascript' src="{% static 'fontawesome/js/fontawesome.js' %}"></script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
    .login-error {
 | 
					 | 
				
			||||||
        color: #F88;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<title>
 | 
					 | 
				
			||||||
    {% inventree_title %} 
 | 
					 | 
				
			||||||
</title>
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<body class='login-screen'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <div class='main body-wrapper login-screen'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div class='login-container'>
 | 
					 | 
				
			||||||
        <div class="row">
 | 
					 | 
				
			||||||
            <div class='container-fluid'>
 | 
					 | 
				
			||||||
                <div class='clearfix content-heading login-header'>
 | 
					 | 
				
			||||||
                    <img class="pull-left" src="{% static 'img/inventree.png' %}" width="60" height="60"/>
 | 
					 | 
				
			||||||
                    <span><h3>{% inventree_title %} </h3></span>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                    <hr>
 | 
					 | 
				
			||||||
                    <div class='container-fluid'>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <p>
 | 
					 | 
				
			||||||
                            {% trans "We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly." %}
 | 
					 | 
				
			||||||
                        </p>
 | 
					 | 
				
			||||||
                        <p>
 | 
					 | 
				
			||||||
                            {% trans "If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder." %}
 | 
					 | 
				
			||||||
                        </p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        <hr>
 | 
					 | 
				
			||||||
                        <a href='{% url "login" %}'>{% trans "Return to login screen" %}</a>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					{% load socialaccount %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% get_providers as socialaccount_providers %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% for provider in socialaccount_providers %}
 | 
				
			||||||
 | 
					{% if provider.id == "openid" %}
 | 
				
			||||||
 | 
					{% for brand in provider.get_brands %}
 | 
				
			||||||
 | 
					  <a title="{{brand.name}}" 
 | 
				
			||||||
 | 
					     class="btn btn-primary socialaccount_provider {{provider.id}} {{brand.id}}" 
 | 
				
			||||||
 | 
					     href="{% provider_login_url provider.id openid=brand.openid_url process=process %}"
 | 
				
			||||||
 | 
					     ><span class='brand-icon' brand_name='{{provider.id}}'></span> {{brand.name}}</a>
 | 
				
			||||||
 | 
					{% endfor %}
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					  <a title="{{provider.name}}" class="btn btn-primary socialaccount_provider {{provider.id}}" 
 | 
				
			||||||
 | 
					     href="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}"
 | 
				
			||||||
 | 
					     ><span class='brand-icon' brand_name='{{provider.id}}'></span> {{provider.name}}</a>
 | 
				
			||||||
 | 
					{% endfor %}
 | 
				
			||||||
@@ -67,7 +67,12 @@ class RuleSet(models.Model):
 | 
				
			|||||||
            'report_billofmaterialsreport',
 | 
					            'report_billofmaterialsreport',
 | 
				
			||||||
            'report_purchaseorderreport',
 | 
					            'report_purchaseorderreport',
 | 
				
			||||||
            'report_salesorderreport',
 | 
					            'report_salesorderreport',
 | 
				
			||||||
 | 
					            'account_emailaddress',
 | 
				
			||||||
 | 
					            'account_emailconfirmation',
 | 
				
			||||||
 | 
					            'sites_site',
 | 
				
			||||||
 | 
					            'socialaccount_socialaccount',
 | 
				
			||||||
 | 
					            'socialaccount_socialapp',
 | 
				
			||||||
 | 
					            'socialaccount_socialtoken',
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        'part_category': [
 | 
					        'part_category': [
 | 
				
			||||||
            'part_partcategory',
 | 
					            'part_partcategory',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,7 +68,9 @@ RUN apk add --no-cache git make bash \
 | 
				
			|||||||
    # PostgreSQL support
 | 
					    # PostgreSQL support
 | 
				
			||||||
    postgresql postgresql-contrib postgresql-dev libpq \
 | 
					    postgresql postgresql-contrib postgresql-dev libpq \
 | 
				
			||||||
    # MySQL/MariaDB support
 | 
					    # MySQL/MariaDB support
 | 
				
			||||||
    mariadb-connector-c mariadb-dev mariadb-client
 | 
					    mariadb-connector-c mariadb-dev mariadb-client \
 | 
				
			||||||
 | 
					    # Required for python cryptography support
 | 
				
			||||||
 | 
					    rust cargo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Install required base-level python packages
 | 
					# Install required base-level python packages
 | 
				
			||||||
COPY requirements.txt requirements.txt
 | 
					COPY requirements.txt requirements.txt
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,5 +35,6 @@ python-barcode[images]==0.13.1  # Barcode generator
 | 
				
			|||||||
qrcode[pil]==6.1                # QR code generator
 | 
					qrcode[pil]==6.1                # QR code generator
 | 
				
			||||||
django-q==1.3.4                 # Background task scheduling
 | 
					django-q==1.3.4                 # Background task scheduling
 | 
				
			||||||
django-formtools==2.3           # Form wizard tools
 | 
					django-formtools==2.3           # Form wizard tools
 | 
				
			||||||
 | 
					django-allauth==0.45.0          # SSO for external providers via OpenID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inventree                       # Install the latest version of the InvenTree API python library
 | 
					inventree                       # Install the latest version of the InvenTree API python library
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user