diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2023-03-08 18:46:23 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2023-03-08 18:48:15 +0100 |
commit | f5796cb2bf4e3bbe3a71b9cdf9320aea690ddfd9 (patch) | |
tree | afb4925208a6ee8abc889d035ebd36ed39ca3128 /ishtar_common | |
parent | 4a1ebdc182c6e332fa46d47cea9ee6e3f8f9b646 (diff) | |
download | Ishtar-f5796cb2bf4e3bbe3a71b9cdf9320aea690ddfd9.tar.bz2 Ishtar-f5796cb2bf4e3bbe3a71b9cdf9320aea690ddfd9.zip |
UI: show/hide password on login
Diffstat (limited to 'ishtar_common')
-rw-r--r-- | ishtar_common/forms_common.py | 14 | ||||
-rw-r--r-- | ishtar_common/static/js/bootstrap-show-password/bootstrap-show-password.min.js | 2 | ||||
-rw-r--r-- | ishtar_common/templates/base.html | 1 | ||||
-rw-r--r-- | ishtar_common/urls_registration.py | 31 | ||||
-rw-r--r-- | ishtar_common/views.py | 6 |
5 files changed, 46 insertions, 8 deletions
diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 4286ae9fd..eb7e03f3a 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -32,6 +32,8 @@ import zipfile from django import forms from django.conf import settings from django.contrib.auth.models import User +from django.contrib.auth.forms import AuthenticationForm as AuthAuthenticationForm, \ + UsernameField from django.contrib.contenttypes.models import ContentType from django.core import validators from django.core.cache import cache @@ -135,6 +137,18 @@ def get_person_field(label=_("Person"), required=True, person_types=None): ) +class AuthenticationForm(AuthAuthenticationForm): + username = UsernameField(widget=forms.TextInput( + attrs={'autofocus': True, 'class': 'no-append'}) + ) + password = forms.CharField( + label=_("Password"), + strip=False, + widget=forms.PasswordInput( + attrs={'autocomplete': 'off', 'data-toggle': 'password'}) + ) + + class NewItemForm(forms.Form): def __init__(self, *args, **kwargs): self.limits = {} diff --git a/ishtar_common/static/js/bootstrap-show-password/bootstrap-show-password.min.js b/ishtar_common/static/js/bootstrap-show-password/bootstrap-show-password.min.js index a944d22c1..317ed06d3 100644 --- a/ishtar_common/static/js/bootstrap-show-password/bootstrap-show-password.min.js +++ b/ishtar_common/static/js/bootstrap-show-password/bootstrap-show-password.min.js @@ -3,4 +3,4 @@ * https://github.com/wenzhixin/bootstrap-show-password * version: 1.0.3 */ -!function(e){"use strict";var t=function(e){var t=arguments,s=!0,i=1;return e=e.replace(/%s/g,function(){var e=t[i++];return"undefined"==typeof e?(s=!1,""):e}),s?e:""},s=function(t,s){this.options=s,this.$element=e(t),this.isShown=!1,this.init()};s.DEFAULTS={placement:"after",white:!1,message:"Click here to show/hide password",eyeClass:"glyphicon",eyeOpenClass:"glyphicon-eye-open",eyeCloseClass:"glyphicon-eye-close"},s.prototype.init=function(){var s,i;"before"===this.options.placement?(s="insertBefore",i="input-prepend"):(this.options.placement="after",s="insertAfter",i="input-append"),this.$element.wrap(t('<div class="%s input-group" />',i)),this.$text=e('<input type="text" />')[s](this.$element).attr("class",this.$element.attr("class")).attr("style",this.$element.attr("style")).attr("placeholder",this.$element.attr("placeholder")).css("display",this.$element.css("display")).val(this.$element.val()).hide(),this.$element.prop("readonly")&&this.$text.prop("readonly",!0),this.$icon=e(['<span tabindex="100" title="'+this.options.message+'" class="add-on input-group-addon">','<i class="icon-eye-open'+(this.options.white?" icon-white":"")+" "+this.options.eyeClass+" "+this.options.eyeOpenClass+'"></i>',"</span>"].join(""))[s](this.$text).css("cursor","pointer"),this.$text.off("keyup").on("keyup",e.proxy(function(){this.isShown&&this.$element.val(this.$text.val()).trigger("change")},this)),this.$icon.off("click").on("click",e.proxy(function(){this.$text.val(this.$element.val()).trigger("change"),this.toggle()},this))},s.prototype.toggle=function(e){this[this.isShown?"hide":"show"](e)},s.prototype.show=function(t){var s=e.Event("show.bs.password",{relatedTarget:t});this.$element.trigger(s),this.isShown=!0,this.$element.hide(),this.$text.show(),this.$icon.find("i").removeClass("icon-eye-open "+this.options.eyeOpenClass).addClass("icon-eye-close "+this.options.eyeCloseClass),this.$text[this.options.placement](this.$element)},s.prototype.hide=function(t){var s=e.Event("hide.bs.password",{relatedTarget:t});this.$element.trigger(s),this.isShown=!1,this.$element.show(),this.$text.hide(),this.$icon.find("i").removeClass("icon-eye-close "+this.options.eyeCloseClass).addClass("icon-eye-open "+this.options.eyeOpenClass),this.$element[this.options.placement](this.$text)},s.prototype.val=function(e){return"undefined"==typeof e?this.$element.val():(this.$element.val(e).trigger("change"),this.$text.val(e),void 0)};var i=e.fn.password;e.fn.password=function(){var t,i=arguments[0],n=arguments,o=["show","hide","toggle","val"];return this.each(function(){var a=e(this),h=a.data("bs.password"),r=e.extend({},s.DEFAULTS,a.data(),"object"==typeof i&&i);if("string"==typeof i){if(e.inArray(i,o)<0)throw"Unknown method: "+i;t=h[i](n[1])}else h?h.init(r):(h=new s(a,r),a.data("bs.password",h))}),t?t:this},e.fn.password.Constructor=s,e.fn.password.noConflict=function(){return e.fn.password=i,this},e(function(){e('[data-toggle="password"]').password()})}(window.jQuery);
\ No newline at end of file +!function(e){"use strict";var t=function(e){var t=arguments,s=!0,i=1;return e=e.replace(/%s/g,function(){var e=t[i++];return"undefined"==typeof e?(s=!1,""):e}),s?e:""},s=function(t,s){this.options=s,this.$element=e(t),this.isShown=!1,this.init()};s.DEFAULTS={placement:"after",white:!1,message:"Click here to show/hide password",eyeClass:"fa",eyeOpenClass:"fa-eye",eyeCloseClass:"fa-eye-slash"},s.prototype.init=function(){var s,i;"before"===this.options.placement?(s="insertBefore",i="input-prepend"):(this.options.placement="after",s="insertAfter",i=""),this.$element.wrap(t('<div class="%sinput-group" />',i)),this.$text=e('<input type="text" />')[s](this.$element).attr("class",this.$element.attr("class")).attr("style",this.$element.attr("style")).attr("placeholder",this.$element.attr("placeholder")).css("display",this.$element.css("display")).val(this.$element.val()).hide(),this.$element.prop("readonly")&&this.$text.prop("readonly",!0),this.$icon=e(['<div tabindex="100" title="'+this.options.message+'" class="input-group-append">','<span class="input-group-text"><i class="icon-eye-open'+(this.options.white?" icon-white":"")+" "+this.options.eyeClass+" "+this.options.eyeOpenClass+'"></i></span>',"</div>"].join(""))[s](this.$text).css("cursor","pointer"),this.$text.off("keyup").on("keyup",e.proxy(function(){this.isShown&&this.$element.val(this.$text.val()).trigger("change")},this)),this.$icon.off("click").on("click",e.proxy(function(){this.$text.val(this.$element.val()).trigger("change"),this.toggle()},this))},s.prototype.toggle=function(e){this[this.isShown?"hide":"show"](e)},s.prototype.show=function(t){var s=e.Event("show.bs.password",{relatedTarget:t});this.$element.trigger(s),this.isShown=!0,this.$element.hide(),this.$text.show(),this.$icon.find("i").removeClass("icon-eye-open "+this.options.eyeOpenClass).addClass("icon-eye-close "+this.options.eyeCloseClass),this.$text[this.options.placement](this.$element)},s.prototype.hide=function(t){var s=e.Event("hide.bs.password",{relatedTarget:t});this.$element.trigger(s),this.isShown=!1,this.$element.show(),this.$text.hide(),this.$icon.find("i").removeClass("icon-eye-close "+this.options.eyeCloseClass).addClass("icon-eye-open "+this.options.eyeOpenClass),this.$element[this.options.placement](this.$text)},s.prototype.val=function(e){return"undefined"==typeof e?this.$element.val():(this.$element.val(e).trigger("change"),this.$text.val(e),void 0)};var i=e.fn.password;e.fn.password=function(){var t,i=arguments[0],n=arguments,o=["show","hide","toggle","val"];return this.each(function(){var a=e(this),h=a.data("bs.password"),r=e.extend({},s.DEFAULTS,a.data(),"object"==typeof i&&i);if("string"==typeof i){if(e.inArray(i,o)<0)throw"Unknown method: "+i;t=h[i](n[1])}else h?h.init(r):(h=new s(a,r),a.data("bs.password",h))}),t?t:this},e.fn.password.Constructor=s,e.fn.password.noConflict=function(){return e.fn.password=i,this},e(function(){e('[data-toggle="password"]').password()})}(window.jQuery); diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index 3fa049215..53ef4f35a 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -15,6 +15,7 @@ <script language="javascript" type="text/javascript" src="{{STATIC_URL}}popper.min.js?ver={{VERSION}}"></script> <script language="javascript" type="text/javascript" src="{{JQUERY_UI_URL}}jquery-ui.js?ver={{VERSION}}"></script> <script language="javascript" type="text/javascript" src="{{STATIC_URL}}bootstrap/bootstrap.js?ver={{VERSION}}"></script> + <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/bootstrap-show-password/bootstrap-show-password.min.js?ver={{VERSION}}"></script> <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/papaparse.min.js?ver={{VERSION}}"></script> <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/chosen/chosen.jquery.min.js?ver={{VERSION}}"></script> {# <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/prettyPhoto/js/jquery.prettyPhoto.js?ver={{VERSION}}"></script> #} diff --git a/ishtar_common/urls_registration.py b/ishtar_common/urls_registration.py index 36795b113..0a18ff060 100644 --- a/ishtar_common/urls_registration.py +++ b/ishtar_common/urls_registration.py @@ -1,11 +1,15 @@ -from django.conf.urls import include, url +from django.conf.urls import url +from django.urls import path from django.views.generic.base import TemplateView try: - from registration import views # debian + from registration import views as registration_views # debian except ModuleNotFoundError: - from django_registration import views # pip + from django_registration import views as registration_views # pip +from django.contrib.auth import views as auth_views + +from ishtar_common import views urlpatterns = [ url(r'^accounts/activate/complete/$', @@ -18,10 +22,10 @@ urlpatterns = [ # the view; that way it can return a sensible "invalid key" # message instead of a confusing 404. url(r'^accounts/activate/(?P<activation_key>\w+)/$', - views.ActivationView.as_view(), + registration_views.ActivationView.as_view(), name='registration_activate'), url(r'^accounts/register/$', - views.RegistrationView.as_view(), + registration_views.RegistrationView.as_view(), name='registration_register'), url(r'^accounts/register/complete/$', TemplateView.as_view( @@ -33,5 +37,20 @@ urlpatterns = [ template_name='registration/registration_closed.html' ), name='registration_disallowed'), - url("^accounts/", include('django.contrib.auth.urls')), + # url("^accounts/", include('django.contrib.auth.urls')), + path('accounts/login/', views.LoginView.as_view(), name='login'), + path('accounts/logout/', auth_views.LogoutView.as_view(), name='logout'), + + path('accounts/password_change/', auth_views.PasswordChangeView.as_view(), + name='password_change'), + path('accounts/password_change/done/', auth_views.PasswordChangeDoneView.as_view(), + name='password_change_done'), + + path('accounts/password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'), + path('accounts/password_reset/done/', auth_views.PasswordResetDoneView.as_view(), + name='password_reset_done'), + path('accounts/reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), + name='password_reset_confirm'), + path('accounts/reset/done/', auth_views.PasswordResetCompleteView.as_view(), + name='password_reset_complete'), ]
\ No newline at end of file diff --git a/ishtar_common/views.py b/ishtar_common/views.py index f9f84b533..b6b58fe05 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -31,7 +31,7 @@ from django.apps import apps from django.conf import settings from django.contrib.auth import logout from django.contrib.auth.decorators import login_required -from django.contrib.auth.views import redirect_to_login +from django.contrib.auth.views import redirect_to_login, LoginView as AuthLoginView from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist from django.db.models import Q @@ -167,6 +167,10 @@ def index(request): return render(request, "index.html", dct) +class LoginView(AuthLoginView): + form_class = forms.AuthenticationForm + + person_search_wizard = wizards.PersonSearch.as_view( [("general-person_search", forms.PersonFormSelection)], label=_("Person search"), |