Changeset 2572
- Timestamp:
- 03/11/10 16:25:23 (5 months ago)
- Location:
- branches/0.9/pylucid_project
- Files:
-
- 4 added
- 14 removed
- 9 modified
-
apps/pylucid/models/log.py (modified) (2 diffs)
-
apps/pylucid_admin/admin_site.py (modified) (2 diffs)
-
media/PyLucid/pylucid_js_tools.js (modified) (2 diffs)
-
media/PyLucid/shared_sha_tools.js (modified) (1 diff)
-
media/PyLucid/sha_login_input_password.js (deleted)
-
pylucid_plugins/auth/auth.OLD_py (deleted)
-
pylucid_plugins/auth/auth_cfg.OLDpy (deleted)
-
pylucid_plugins/auth/forms.py (modified) (2 diffs)
-
pylucid_plugins/auth/preference_forms.py (modified) (1 diff)
-
pylucid_plugins/auth/templates/auth/django_login.html (added)
-
pylucid_plugins/auth/templates/auth/input_password.css (deleted)
-
pylucid_plugins/auth/templates/auth/input_password.html (deleted)
-
pylucid_plugins/auth/templates/auth/input_username.css (deleted)
-
pylucid_plugins/auth/templates/auth/input_username.html (deleted)
-
pylucid_plugins/auth/templates/auth/login_info.html (deleted)
-
pylucid_plugins/auth/templates/auth/new_password_form.css (deleted)
-
pylucid_plugins/auth/templates/auth/new_password_form.html (deleted)
-
pylucid_plugins/auth/templates/auth/new_password_form.js (deleted)
-
pylucid_plugins/auth/templates/auth/pass_reset_email.html (deleted)
-
pylucid_plugins/auth/templates/auth/pass_reset_form.html (deleted)
-
pylucid_plugins/auth/templates/auth/plaintext_login.html (deleted)
-
pylucid_plugins/auth/templates/auth/sha_form.html (added)
-
pylucid_plugins/auth/tests.py (added)
-
pylucid_plugins/auth/test_settings.py (added)
-
pylucid_plugins/auth/views.py (modified) (7 diffs)
-
pylucid_plugins/auth/__init__.py (modified) (1 diff)
-
utils/crypt.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/0.9/pylucid_project/apps/pylucid/models/log.py
r2494 r2572 59 59 return queryset 60 60 61 def request_limit(self, request, min_pause, ban_limit, app_label ):61 def request_limit(self, request, min_pause, ban_limit, app_label, no_page_msg=False): 62 62 """ 63 63 Monitor request min_pause and ban_limit. … … 84 84 if last_actions > 0: 85 85 msg = _("Request too fast!") 86 debug_msg = " (%s in the last %ssec. IP is blocked by %s overruns.)" % ( 87 last_actions, min_pause, ban_limit 88 ) 86 89 if settings.DEBUG: 87 msg += _(" Please wait min. %ssec.") % min_pause 88 request.page_msg.error(msg) 90 msg += debug_msg 91 if no_page_msg == False: 92 request.page_msg.error(msg) 89 93 LogEntry.objects.log_action( 90 app_label=app_label, action="request aborted", message= "(%s in the last %ssec.)" % (last_actions, min_pause),94 app_label=app_label, action="request aborted", message=debug_msg, 91 95 ) 92 raise self.model.RequestTooFast( )96 raise self.model.RequestTooFast(msg) 93 97 94 98 def log_action(self, app_label, action, request=None, message=None, long_message=None, data=None): -
branches/0.9/pylucid_project/apps/pylucid_admin/admin_site.py
r2482 r2572 4 4 from django.contrib import admin 5 5 from django.http import HttpResponseRedirect 6 7 from pylucid_project.apps.pylucid.models import PageTree, UserProfile8 9 6 10 7 … … 17 14 return super(PyLucidAdminSite, self).logout(request) 18 15 16 # Use the PyLucid own logout view, so the user it back on his cms page 19 17 url = "/?" + settings.PYLUCID.AUTH_LOGOUT_GET_VIEW 20 18 return HttpResponseRedirect(url) 21 19 22 def login(self, request):23 """24 Redirect to PyLucid's own login view.25 In debug mode:26 -user can suppress the redirect by adding any GET parameter. (e.g: domain.tld/admin/?foobar)27 -Don't redirect if PyLucid own login view can't work.28 29 TODO: prevent redirect loops30 """31 if PageTree.on_site.all().count() == 0 or UserProfile.on_site.all().count() == 0 or \32 (request.GET and settings.DEBUG):33 return super(PyLucidAdminSite, self).login(request)34 35 url = settings.PYLUCID.AUTH_NEXT_URL % {"path": "/", "next_url": request.get_full_path()}36 return HttpResponseRedirect(url)37 20 38 21 pylucid_admin_site = PyLucidAdminSite() 39 22 23 40 24 # Use all django contrib model admins in our own admin site ;) 41 25 pylucid_admin_site._registry = admin.site._registry -
branches/0.9/pylucid_project/media/PyLucid/pylucid_js_tools.js
r2524 r2572 45 45 46 46 log("redirect work-a-round: replace the complete page"); 47 log(data); 47 48 log("</body> index:" + data.indexOf("</body>")); 48 49 replace_complete_page(data) … … 69 70 if (!response_text) { 70 71 response_text = "<h1>Ajax response error without any response text.</h1>"; 72 response_text += "<p>textStatus:" + textStatus + "</p>" 73 response_text += "<p>errorThrown:" + errorThrown + "</p>" 74 replace_page_content(response_text, textStatus); 75 return 71 76 } 72 77 replace_complete_page(response_text); -
branches/0.9/pylucid_project/media/PyLucid/shared_sha_tools.js
r2002 r2572 3 3 */ 4 4 5 check_ok = false; 6 debug_msg = false; 7 8 // length of a SHA1 hexdigest string: 9 HASH_LEN = 40; 10 // length of the salt and challenge value string: 11 SALT_LEN = 5; 12 13 14 if (!document.getElementById) { 15 alert("Error: Your Browser is not supported!"); 16 } 17 18 if (navigator.cookieEnabled) { 19 if (navigator.cookieEnabled != true) { 20 alert("You must enable Cookies in your Browser!"); 21 } 22 } 23 24 /* ___________________________________________________________________________ 25 * needfull generic functions: 26 */ 27 28 function get_value(object_id) { 29 // get a form value 30 try { 31 return document.getElementById(object_id).value; 32 } catch (e) { 33 alert("get_value('"+object_id+"') error! " + e); 34 } 35 } 36 37 function set_value(object_id, value) { 38 // set a form value 39 try { 40 obj = document.getElementById(object_id).value = value; 41 } catch (e) { 42 alert("set_value('"+object_id+"', '"+value+"') error! " + e); 43 } 44 } 45 46 function set_focus(object_id) { 47 try { 48 debug("set focus on id:" + object_id); 49 document.getElementById(object_id).focus(); 50 } catch (e) { 51 alert("set_focus('"+object_id+"') error:" + e); 52 } 53 } 54 55 function hide_by_id(object_id) { 56 try { 57 debug("hide_by_id: "+object_id); 58 obj = document.getElementById(object_id); 59 obj.style.display = 'none'; 60 } catch (e) { 61 alert("hide_by_id('"+object_id+"') error:" + e); 62 } 63 } 64 function unhide_by_id(object_id) { 65 try { 66 debug("unhide_by_id: "+object_id); 67 obj = document.getElementById(object_id); 68 obj.style.display = 'block'; 69 } catch (e) { 70 alert("unhide_by_id('"+object_id+"') error:" + e); 71 } 72 } 73 74 function change_color(object_id, color_name) { 75 try { 76 debug("change_color: "+object_id); 77 obj = document.getElementById(object_id); 78 obj.style.backgroundColor = color_name; 79 } catch (e) { 80 alert("change_color('"+object_id+"', '"+color_name+"') error:" + e); 81 } 82 } 83 84 /* ___________________________________________________________________________ 85 * special functions: 86 */ 87 88 function check_ascii_only(data) { 5 function is_only_ascii(data) { 6 // Check if the given string contains only ASCII characters 89 7 for (var i = 1; i <= data.length; i++) { 90 unicode_charcode = data.charCodeAt(i); 91 if (unicode_charcode > 127) { 92 alert("Only ASCII letters are allowed!"); 8 if (data.charCodeAt(i) > 127) { 93 9 return false; 94 10 } 95 11 } 96 12 return true; 97 }13 } 98 14 99 function get_plaintext_pass(object_id) { 15 function sha_hexdigest(txt) { 16 // build the SHA hexdigest from the given string. Return false is anything is wrong. 100 17 try { 101 in_pass = get_value(object_id);102 debug("in_pass:" + in_pass);103 if (in_pass.length<8) {104 alert("Password min len 8! - current len:" + in_pass.length);105 set_focus(object_id)18 log("sha_hexdigest(" + txt + "):"); 19 SHA_hexdigest = hex_sha1(txt); // from: sha.js 20 len = SHA_hexdigest.length; 21 if (len != HASH_LEN) { 22 page_msg_error("sha_hexdigest() error! wrong length:" + len); 106 23 return false; 107 24 } 108 109 if (check_ascii_only(in_pass) == false) { 110 set_focus(object_id) 111 return false; 112 } 113 return in_pass; 25 log(SHA_hexdigest); 26 return SHA_hexdigest; 114 27 } catch (e) { 115 alert("get_plaintext_pass() error:" + e);28 page_msg_error("sha_hexdigest() error:" + e); 116 29 return false; 117 30 } 118 31 } 119 32 120 function make_SHA(txt) { 121 try { 122 debug("make_SHA(" + txt + "):"); 123 SHA_hexdigest = hex_sha1(txt); // from: sha.js 124 len = SHA_hexdigest.length; 125 if (len != HASH_LEN) { 126 alert("make_SHA() error! wrong length:" + len); 127 return false; 128 } 129 debug(SHA_hexdigest); 130 return SHA_hexdigest; 131 } catch (e) { 132 alert("make_SHA() error:" + e); 133 return false; 134 } 33 function _page_msg(msg){ 34 $("#js_page_msg").html(msg).css("display", "block").slideDown(); 135 35 } 136 137 138 /* ___________________________________________________________________________ 139 * debugging: 140 */ 141 142 function init_debug() { 143 /* Create a debug window, if it's not exists */ 144 try { 145 if (debug_msg != true) { return; } 146 try { 147 if (debug_window) { 148 return; 149 } 150 } catch (e) {} 151 debug_window = window.open("", "Debug", "dependent=yes, resizable=yes, scrollbars=yes, width=350, height=400, top=1, left=" + window.outerWidth); 152 153 debug_win = debug_window.document; 154 debug_win.writeln("<style>* { font-size: 0.85em; }</style>"); 155 156 var now = new Date(); 157 now = now.toLocaleString(); 158 159 debug_win.writeln("<h1>JS Debug - "+now+":</h1>"); 160 debug_win.writeln("---[DEBUG START]---"); 161 debug_win.writeln("cookie:" + document.cookie +"<br />"); 162 } catch (e) { 163 alert("init_debug() error:" + e); 164 } 36 function page_msg_error(msg) { 37 $("#js_page_msg").removeClass("page_msg_info page_msg_success").addClass("page_msg_error"); 38 _page_msg(msg); 165 39 } 166 167 168 function debug(msg) { 169 try { 170 if (debug_msg != true) { return; } 171 init_debug(); 172 debug_win.writeln(msg + "<br />"); 173 debug_window.focus(); 174 // scroll to the last lines 175 debug_window.scrollBy(0, 1000); 176 } catch (e) { 177 alert("debug('"+msg+"') error:" + e); 178 } 40 function page_msg_success(msg) { 41 $("#js_page_msg").removeClass("page_msg_info page_msg_success").addClass("page_msg_success"); 42 _page_msg(msg); 179 43 } 180 181 182 function debug_confirm() { 183 try { 184 if (debug_msg != true) { return; } 185 debug_window.focus(); 186 debug_win.writeln("---[DEBUG END]---"); 187 alert("OK for closing the debug window."); 188 debug_window.close(); 189 debug_window = false; 190 } catch (e) { 191 alert("debug_confirm() error:" + e); 192 } 44 function page_msg_info(msg) { 45 $("#js_page_msg").removeClass("page_msg_success page_msg_error").addClass("page_msg_info"); 46 _page_msg(msg); 193 47 } -
branches/0.9/pylucid_project/pylucid_plugins/auth/forms.py
r2507 r2572 8 8 9 9 from pylucid_project.utils import crypt 10 11 12 13 def get_newforms_data(key_name, cleaned_data): 14 if not key_name in cleaned_data: 15 raise forms.ValidationError(u"No '%s' data in the form." % key_name) 16 return cleaned_data[key_name] 17 18 19 def validate_sha1(key_name, cleaned_data): 20 """ 21 A universal routine to validate a SHA1 hexdigest for newforms. 22 """ 23 sha_value = get_newforms_data(key_name, cleaned_data) 24 25 if crypt.validate_sha_value(sha_value) == True: 26 return sha_value 27 else: 28 raise forms.ValidationError(u"Wrong '%s' data." % key_name) 29 30 31 class SHA_LoginForm(forms.Form): 10 from pylucid_project.apps.pylucid.models import UserProfile 11 12 class WrongUserError(Exception): 13 pass 14 15 class UsernameForm(forms.Form): 16 username = forms.CharField(max_length=_('30'), label=_('Username'), 17 help_text=_('Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores).') 18 ) 19 20 def get_user(self): 21 username = self.cleaned_data["username"] 22 try: 23 user = User.objects.get(username=username) 24 except User.DoesNotExist, e: 25 raise WrongUserError("User %r doesn't exists!" % username) 26 27 if not user.is_active: 28 raise WrongUserError("User %r is not active!" % user) 29 30 return user 31 32 def get_user_profile(self, user=None): 33 if user is None: 34 user = self.get_user() 35 try: 36 return user.get_profile() 37 except UserProfile.DoesNotExist, err: 38 raise WrongUserError("Can't get user profile: %r" % err) 39 40 def get_user_and_profile(self): 41 user = self.get_user() 42 user_profile = self.get_user_profile(user) 43 return user, user_profile 44 45 46 class ShaLoginForm(UsernameForm): 32 47 """ 33 48 Form for the SHA1-JavaScript-Login. 34 49 """ 35 sha_a2 = forms.CharField( 36 min_length=crypt.HASH_LEN, max_length=crypt.HASH_LEN 37 ) 38 sha_b = forms.CharField( 39 min_length=crypt.HASH_LEN / 2, max_length=crypt.HASH_LEN / 2 40 ) 41 42 #__________________________________________________________________________ 43 # Validate the SHA1 hexdigest values: 50 sha_a2 = forms.CharField(min_length=crypt.HASH_LEN, max_length=crypt.HASH_LEN) 51 sha_b = forms.CharField(min_length=crypt.HASH_LEN / 2, max_length=crypt.HASH_LEN / 2) 44 52 45 53 def clean_sha_a2(self): 46 return validate_sha1("sha_a2", self.cleaned_data) 54 sha_a2 = self.cleaned_data["sha_a2"] 55 if crypt.validate_sha_value(sha_a2) != True: 56 raise forms.ValidationError(u"sha_a2 is not valid SHA value.") 57 58 return sha_a2 47 59 48 60 def clean_sha_b(self): … … 51 63 some characers to use the rypt.validate_sha_value() method. 52 64 """ 53 sha_ value = get_newforms_data("sha_b", self.cleaned_data)65 sha_b = self.cleaned_data["sha_b"] 54 66 55 67 # Fill with null, to match the full SHA1 hexdigest length. 56 68 fill_len = crypt.HASH_LEN - (crypt.HASH_LEN / 2) 57 temp_value = ("0" * fill_len) + sha_value 58 59 if crypt.validate_sha_value(temp_value) == True: 60 return sha_value 61 else: 62 raise forms.ValidationError(u"Wrong sha_b data.") 63 64 65 class NewPasswordForm(forms.Form): 66 username = forms.CharField( 67 help_text="(required)", min_length=3, max_length=30 68 ) 69 70 # Should normaly never be send back! 71 raw_password = forms.CharField( 72 help_text="(required)", required=False, widget=forms.PasswordInput() 73 ) 74 75 sha_1 = forms.CharField( 76 label="SHA1 for django", 77 help_text="(automatic generated with JavaScript.)", 78 widget=forms.TextInput(attrs={"readonly":"readonly", "size":"40"}), 79 min_length=crypt.HASH_LEN, max_length=crypt.HASH_LEN 80 ) 81 sha_2 = forms.CharField( 82 label="SHA1 for PyLucid", 83 help_text="(automatic generated with JavaScript.)", 84 widget=forms.TextInput(attrs={"readonly":"readonly", "size":"40"}), 85 min_length=crypt.HASH_LEN, max_length=crypt.HASH_LEN 86 ) 87 88 #__________________________________________________________________________ 89 # Validate the SHA1 hexdigest values: 90 91 def clean_sha_1(self): 92 return validate_sha1("sha_1", self.cleaned_data) 93 94 def clean_sha_2(self): 95 return validate_sha1("sha_2", self.cleaned_data) 96 97 98 #______________________________________________________________________________ 99 # FORMS 100 101 #class BaseModelForm(forms.ModelForm): 102 # """ 103 # A model form witch don't validate unique fields. 104 # 105 # This ModelForm is only for generating the forms and not for create/update 106 # any database data. So a field unique Test would like generate Errors like: 107 # User with this Username already exists. 108 # 109 # see also: 110 # http://www.jensdiemer.de/_command/118/blog/detail/30/ (de) 111 # http://www.python-forum.de/topic-16000.html (de) 112 # """ 113 # def __init__(self, *args, **kwargs): 114 # """ Change field meta in a DRY way """ 115 # super(BaseModelForm, self).__init__(*args, **kwargs) 116 # 117 # self.model.full_validate = self._skip 118 # 119 # def _skip(self, *args, **kwargs): 120 # pass 121 # 122 # def validate_unique(self): 123 # pass 124 125 class UsernameForm(forms.Form): 126 """ 127 form for input the username, used in auth.login() 128 129 FIXME: This is not DRY. 130 """ 131 username = forms.CharField(max_length=_('30'), label=_('Username'), 132 help_text=_('Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores).') 133 ) 134 135 def is_valid(self): 136 """ do a secont validation: try to get the user from database and 137 check if he is active """ 138 is_valid = super(UsernameForm, self).is_valid() 139 if not is_valid: 140 return False 141 142 username = self.cleaned_data["username"] 143 try: 144 self.user = User.objects.get(username=username) 145 except User.DoesNotExist, e: 146 self._errors["username"] = ("User doesn't exist!",) 147 return False 148 149 return True 150 151 # class Meta: 152 # model = User 153 # fields = ("username",) 154 155 156 class PasswordForm(forms.Form): 157 """ 158 form for input the username, used in auth._sha_login() 159 160 FIXME: This is not DRY. 161 """ 162 password = forms.CharField(max_length=_('128'), label=_('Password'), widget=forms.PasswordInput() 163 ) 164 165 # def __init__(self, *args, **kwargs): 166 # """ Change field meta in a DRY way """ 167 # super(PasswordForm, self).__init__(*args, **kwargs) 168 # 169 # self.fields['password'].widget = forms.PasswordInput() 170 # self.fields['password'].help_text = "" 171 172 def is_valid(self, username): 173 is_valid = super(PasswordForm, self).is_valid() 174 if not is_valid: 175 return False 176 177 password = self.cleaned_data["password"] 178 self.user = auth.authenticate(username=username, password=password) 179 if not self.user: 180 self._errors["password"] = ("Wrong password!",) 181 return False 182 183 return True 184 185 # class Meta: 186 # model = User 187 # fields = ("password",) 188 189 190 class ResetForm(forms.Form): 191 """ 192 from for input username and email, used in auth.pass_reset() 193 """ 194 username = forms.CharField(max_length=_('30'), label=_('Username'), 195 help_text=_('Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores).') 196 ) 197 email = forms.EmailField(max_length=_('75'), label=_('E-mail address')) 198 199 # def __init__(self, *args, **kwargs): 200 # super(ResetForm, self).__init__(*args, **kwargs) 201 # # User.email is normaly a not required field, here it's required! 202 # self.fields['email'].required = True 203 204 # class Meta: 205 # model = User 206 # fields = ("username", "email") 69 temp_value = ("0" * fill_len) + sha_b 70 71 if crypt.validate_sha_value(temp_value) != True: 72 raise forms.ValidationError(u"sha_b is not a valid SHA value.") 73 74 return sha_b 75 76 # 77 #class NewPasswordForm(forms.Form): 78 # username = forms.CharField( 79 # help_text="(required)", min_length=3, max_length=30 80 # ) 81 # 82 # # Should normaly never be send back! 83 # raw_password = forms.CharField( 84 # help_text="(required)", required=False, widget=forms.PasswordInput() 85 # ) 86 # 87 # sha_1 = forms.CharField( 88 # label="SHA1 for django", 89 # help_text="(automatic generated with JavaScript.)", 90 # widget=forms.TextInput(attrs={"readonly":"readonly", "size":"40"}), 91 # min_length=crypt.HASH_LEN, max_length=crypt.HASH_LEN 92 # ) 93 # sha_2 = forms.CharField( 94 # label="SHA1 for PyLucid", 95 # help_text="(automatic generated with JavaScript.)", 96 # widget=forms.TextInput(attrs={"readonly":"readonly", "size":"40"}), 97 # min_length=crypt.HASH_LEN, max_length=crypt.HASH_LEN 98 # ) 99 # 100 # #__________________________________________________________________________ 101 # # Validate the SHA1 hexdigest values: 102 # 103 # def clean_sha_1(self): 104 # return validate_sha1("sha_1", self.cleaned_data) 105 # 106 # def clean_sha_2(self): 107 # return validate_sha1("sha_2", self.cleaned_data) 108 # 109 # 110 ##______________________________________________________________________________ 111 ## FORMS 112 # 113 ##class BaseModelForm(forms.ModelForm): 114 ## """ 115 ## A model form witch don't validate unique fields. 116 ## 117 ## This ModelForm is only for generating the forms and not for create/update 118 ## any database data. So a field unique Test would like generate Errors like: 119 ## User with this Username already exists. 120 ## 121 ## see also: 122 ## http://www.jensdiemer.de/_command/118/blog/detail/30/ (de) 123 ## http://www.python-forum.de/topic-16000.html (de) 124 ## """ 125 ## def __init__(self, *args, **kwargs): 126 ## """ Change field meta in a DRY way """ 127 ## super(BaseModelForm, self).__init__(*args, **kwargs) 128 ## 129 ## self.model.full_validate = self._skip 130 ## 131 ## def _skip(self, *args, **kwargs): 132 ## pass 133 ## 134 ## def validate_unique(self): 135 ## pass 136 # 137 #class UsernameForm(forms.Form): 138 # """ 139 # form for input the username, used in auth.login() 140 # 141 # FIXME: This is not DRY. 142 # """ 143 # 144 # 145 ## class Meta: 146 ## model = User 147 ## fields = ("username",) 148 # 149 # 150 #class PasswordForm(forms.Form): 151 # """ 152 # form for input the username, used in auth._sha_login() 153 # 154 # FIXME: This is not DRY. 155 # """ 156 # password = forms.CharField(max_length=_('128'), label=_('Password'), widget=forms.PasswordInput() 157 # ) 158 # 159 ## def __init__(self, *args, **kwargs): 160 ## """ Change field meta in a DRY way """ 161 ## super(PasswordForm, self).__init__(*args, **kwargs) 162 ## 163 ## self.fields['password'].widget = forms.PasswordInput() 164 ## self.fields['password'].help_text = "" 165 # 166 # def is_valid(self, username): 167 # is_valid = super(PasswordForm, self).is_valid() 168 # if not is_valid: 169 # return False 170 # 171 # password = self.cleaned_data["password"] 172 # self.user = auth.authenticate(username=username, password=password) 173 # if not self.user: 174 # self._errors["password"] = ("Wrong password!",) 175 # return False 176 # 177 # return True 178 # 179 ## class Meta: 180 ## model = User 181 ## fields = ("password",) 182 # 183 # 184 #class ResetForm(forms.Form): 185 # """ 186 # from for input username and email, used in auth.pass_reset() 187 # """ 188 # username = forms.CharField(max_length=_('30'), label=_('Username'), 189 # help_text=_('Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores).') 190 # ) 191 # email = forms.EmailField(max_length=_('75'), label=_('E-mail address')) 192 # 193 ## def __init__(self, *args, **kwargs): 194 ## super(ResetForm, self).__init__(*args, **kwargs) 195 ## # User.email is normaly a not required field, here it's required! 196 ## self.fields['email'].required = True 197 # 198 ## class Meta: 199 ## model = User 200 ## fields = ("username", "email") -
branches/0.9/pylucid_project/pylucid_plugins/auth/preference_forms.py
r2492 r2572 10 10 ban_limit = forms.IntegerField( 11 11 help_text=_("Numbers login log messages after IP would be banned."), 12 initial= 5, min_value=1, max_value=2012 initial=6, min_value=1, max_value=20 13 13 ) 14 14 min_pause = forms.IntegerField( 15 15 help_text=_("Minimum pause in seconds between two login log messages from the same user. (Used 'REMOTE_ADDR')"), 16 initial= 30, min_value=1, max_value=60016 initial=15, min_value=1, max_value=600 17 17 ) 18 18 -
branches/0.9/pylucid_project/pylucid_plugins/auth/views.py
r2494 r2572 21 21 from django.template import RequestContext 22 22 from django.contrib.sites.models import Site 23 from django.http import HttpResponse Redirect23 from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest 24 24 from django.utils.translation import ugettext as _ 25 25 from django.template.loader import render_to_string … … 27 27 28 28 29 from pylucid .shortcuts import render_pylucid_response30 from pylucid .models import LogEntry, BanEntry, UserProfile29 from pylucid_project.apps.pylucid.shortcuts import render_pylucid_response 30 from pylucid_project.apps.pylucid.models import LogEntry, BanEntry, UserProfile 31 31 32 32 from pylucid_project.utils import crypt 33 33 34 from pylucid_p lugins.auth.forms import UsernameForm, PasswordForm, SHA_LoginForm34 from pylucid_project.pylucid_plugins.auth.forms import WrongUserError, UsernameForm, ShaLoginForm 35 35 from pylucid_plugins.auth.preference_forms import AuthPreferencesForm 36 36 … … 47 47 48 48 49 # For the tag list from page_admin plugin: 50 LUCIDTAG_EXAMPLE = """{% lucidTag admin_menu %}""" 49 def _get_challenge(request): 50 """ create a new challenge, add it to session and return it""" 51 # Create a new random salt value for the password challenge: 52 challenge = crypt.get_new_salt() 53 54 # For later comparing with form data 55 request.session["challenge"] = challenge 56 57 return challenge 58 59 60 def _bad_request(debug_msg): 61 """ 62 Create a new LogEntry and return a HttpResponseBadRequest 63 """ 64 LogEntry.objects.log_action( 65 app_label="pylucid_plugin.auth", action="login error", message=debug_msg, 66 ) 67 if settings.DEBUG: 68 msg = debug_msg 69 else: 70 msg = "" 71 return HttpResponseBadRequest(msg) 72 73 74 def _is_post_ajax_request(request): 75 if not request.is_ajax(): 76 debug_msg = "request is not a ajax request" 77 return _bad_request(debug_msg) 78 79 if request.method != 'POST': 80 debug_msg = "request method %r wrong, only POST allowed" % request.method 81 return _bad_request(debug_msg) 51 82 52 83 … … 57 88 """ 58 89 if request.user.is_authenticated(): 59 # admin_logout reverse is still broken in django, see:60 # http://code.djangoproject.com/ticket/1108061 # http://code.djangoproject.com/attachment/ticket/1006162 #url = reverse("admin:logout")63 #url = reverse("admin:index") + "logout/" # TODO: Update this if django is bugfixed64 90 template_name = "auth/logout_link.html" 65 url = "?auth=logout" 91 if hasattr(request.PYLUCID, "pagetree"): 92 # We are on a normal cms page -> Dont's change the url 93 url = "" 94 else: 95 # We are in the django admin panel -> Go to root page 96 url = "/" 97 url += "?auth=logout" 66 98 else: 67 99 template_name = "auth/login_link.html" … … 71 103 72 104 105 def _wrong_login(request, debug_msg, user=None): 106 """ username or password is wrong. """ 107 if settings.DEBUG: 108 error_msg = debug_msg 109 else: 110 error_msg = _("Wrong username/password.") 111 112 # Protection against DOS attacks. 113 pref_form = AuthPreferencesForm() 114 preferences = pref_form.get_preferences() 115 min_pause = preferences["min_pause"] 116 ban_limit = preferences["ban_limit"] 117 try: 118 LogEntry.objects.request_limit( 119 request, min_pause, ban_limit, app_label="pylucid_plugin.auth", no_page_msg=True 120 ) 121 except LogEntry.RequestTooFast, err: 122 # min_pause is not observed 123 error_msg = err 124 125 # Log this error (Important: must be logged after LogEntry.objects.request_limit() stuff! 126 if user is not None: 127 data = {"user_username": user.username} 128 else: 129 data = None 130 LogEntry.objects.log_action( 131 app_label="pylucid_plugin.auth", action="login", message=debug_msg, data=data 132 ) 133 134 # create a new challenge and add it to session 135 challenge = _get_challenge(request) 136 137 response = "%s;%s" % (challenge, error_msg) 138 return HttpResponse(response, content_type="text/plain") 139 140 141 def _sha_auth(request): 142 """ 143 login the user with username and sha values. 144 """ 145 response = _is_post_ajax_request(request) 146 if response is not None: # It's not a Ajax POST request 147 return response # Return HttpResponseBadRequest 148 149 form = ShaLoginForm(request.POST) 150 if not form.is_valid(): 151 debug_msg = "ShaLoginForm is not valid: %r" % form.errors 152 return _bad_request(debug_msg) 153 154 try: 155 challenge = request.session.pop("challenge") 156 except KeyError, err: 157 debug_msg = "Can't get 'challenge' from session: %s" % err 158 return _bad_request(debug_msg) 159 160 try: 161 user1, user_profile = form.get_user_and_profile() 162 except WrongUserError, err: 163 debug_msg = "Can't get user and user profile: %s" % err 164 return _wrong_login(request, debug_msg) 165 166 sha_checksum = user_profile.sha_login_checksum 167 sha_a2 = form.cleaned_data["sha_a2"] 168 sha_b = form.cleaned_data["sha_b"] 169 170 # authenticate with: 171 # pylucid.system.auth_backends.SiteSHALoginAuthBackend 172 user2 = auth.authenticate( 173 user=user1, challenge=challenge, 174 sha_a2=sha_a2, sha_b=sha_b, 175 sha_checksum=sha_checksum 176 ) 177 if user2 is None: 178 debug_msg = "auth.authenticate() failed. (must be a wrong password)" 179 return _wrong_login(request, debug_msg, user1) 180 else: 181 # everything is ok -> log the user in and display "last login" page message 182 last_login = user2.last_login 183 auth.login(request, user2) 184 message = render_to_string('auth/login_info.html', {"last_login":last_login}) 185 request.page_msg.successful(message) 186 return HttpResponse("OK", content_type="text/plain") 187 188 189 def _get_salt(request): 190 """ 191 return the user password salt. 192 If the user doesn't exist or is not active, return a pseudo salt. 193 """ 194 response = _is_post_ajax_request(request) 195 if response is not None: # It's not a Ajax POST request 196 return response # Return HttpResponseBadRequest 197 198 user_profile = None 199 form = UsernameForm(request.POST) 200 if form.is_valid(): 201 try: 202 user_profile = form.get_user_profile() 203 except WrongUserError, err: 204 if settings.DEBUG: 205 request.page_msg.error(err) 206 207 if user_profile is None: # Wrong user? 208 username = request.POST["username"] 209 if settings.DEBUG: 210 request.page_msg.error("Wrong user %r !" % username) 211 salt = crypt.get_pseudo_salt(username) 212 else: 213 salt = user_profile.sha_login_salt 214 215 return HttpResponse(salt, content_type="text/plain") 216 217 218 def _login_view(request, next_url): 219 if request.method != 'GET': 220 debug_msg = "request method %r wrong, only GET allowed" % request.method 221 return _bad_request(debug_msg) # Return HttpResponseBadRequest 222 223 if "://" in next_url: # FIXME: How to validate this better? 224 # Don't redirect to other pages. 225 debug_msg = "next url %r seems to be wrong!" % next_url 226 return _bad_request(debug_msg) # Return HttpResponseBadRequest 227 228 form = ShaLoginForm() 229 230 # create a new challenge and add it to session 231 challenge = _get_challenge(request) 232 233 context = { 234 "challenge": challenge, 235 "salt_len": crypt.SALT_LEN, 236 "hash_len": crypt.HASH_LEN, 237 "get_salt_url": request.path + "?auth=get_salt", 238 "sha_auth_url": request.path + "?auth=sha_auth", 239 "next_url": next_url, 240 "form": form, 241 "pass_reset_link": "#TODO", 242 } 243 244 # return a string for replacing the normal cms page content 245 return render_pylucid_response(request, 'auth/sha_form.html', context, context_instance=RequestContext(request)) 73 246 74 247 … … 80 253 81 254 82 def _login(request, user, next_url):83 last_login = user.last_login84 85 auth.login(request, user)86 87 message = render_to_string('auth/login_info.html', {"last_login":last_login})88 request.page_msg.successful(message)89 90 return HttpResponseRedirect(next_url)91 92 93 def _plaintext_login(request, context, username, next_url):94 """ input the password and login if auth ok """95 if "password" in request.POST:96 password_form = PasswordForm(request.POST)97 if password_form.is_valid(username):98 user = password_form.user # User instance added in UsernameForm.is_valid()99 return _login(request, user, next_url)100 else:101 password_form = PasswordForm()102 103 context["form"] = password_form104 105 # return a string for replacing the normal cms page content106 return render_pylucid_response(request, 'auth/plaintext_login.html', context)107 108 109 110 def _sha_login(request, context, user, next_url):111 """112 Login via JS-SHA-Login.113 Display the JS-SHA-Login form and login if password is ok.114 """115 try:116 user_profile = user.get_profile()117 except UserProfile.DoesNotExist, err:118 try:119 UserProfile.objects.get(user=user)#.count()120 except UserProfile.DoesNotExist, err:121 # User profile doesn't generally not exist for this user. e.g. Update from v0.8.x ?122 msg = _("There exist no UserProfile for user %(user)r: %(err)s") % {"user":user, "err":err}123 else:124 # A UserProfile exist -> User can't access *this* site.125 site = Site.objects.get_current()126 msg = _("User %(user)r can't access this site: %(site)r") % {"user":user, "site": site}127 128 LogEntry.objects.log_action(129 app_label="pylucid_plugin.auth", action="login", message=msg130 )131 132 if settings.DEBUG:133 request.page_msg.error(msg)134 else:135 request.page_msg.error(_("User unknown."))136 137 return138 139 if "sha_a2" in request.POST and "sha_b" in request.POST:140 SHA_login_form = SHA_LoginForm(request.POST)141 if not SHA_login_form.is_valid():142 msg = _("Form data is not valid. Please correct.")143 request.page_msg.error(msg)144 LogEntry.objects.log_action(145 app_label="pylucid_plugin.auth", action="login",146 message="%s (%r)" % (msg, SHA_login_form.errors)147 )148 if DEBUG: request.page_msg(SHA_login_form.errors)149 else:150 sha_a2 = SHA_login_form.cleaned_data["sha_a2"]151 sha_b = SHA_login_form.cleaned_data["sha_b"]152 if DEBUG:153 request.page_msg("sha_a2:", sha_a2)154 request.page_msg("sha_b:", sha_b)155 156 # A submited SHA1-JS-Login form157 try:158 challenge = request.session['challenge']159 if DEBUG: request.page_msg("challenge:", challenge)160 except KeyError, e:161 msg = _("Session Error.")162 LogEntry.objects.log_action(163 app_label="pylucid_plugin.auth", action="login", message=msg,164 data={"user_username": user.username}165 )166 if DEBUG: msg = "%s (%s)" % (msg, e)167 request.page_msg.error(msg)168 return169 170 sha_checksum = user_profile.sha_login_checksum171 if DEBUG: request.page_msg("sha_checksum:", sha_checksum)172 173 # authenticate with:174 # pylucid.system.auth_backends.SiteSHALoginAuthBackend175 user2 = auth.authenticate(176 user=user, challenge=challenge,177 sha_a2=sha_a2, sha_b=sha_b,178 sha_checksum=sha_checksum179 )180 if user2:181 return _login(request, user2, next_url)182 183 msg = _("Wrong password.")184 LogEntry.objects.log_action(185 app_label="pylucid_plugin.auth", action="login", message=msg,186 data={"user_username": user.username}187 )188 request.page_msg.error(msg)189 else:190 SHA_login_form = UsernameForm()191 192 193 context["salt"] = user_profile.sha_login_salt194 if DEBUG:195 challenge = "debug" # Use same challenge in debug mode196 context["debug"] = "true" # For JavaScript debug197 else:198 # Create a new random salt value for the password challenge:199 challenge = crypt.get_new_salt()200 context["debug"] = "false"201 202 # For later comparing with form data203 request.session['challenge'] = challenge204 context["challenge"] = challenge205 206 context["form"] = SHA_login_form207 208 # return a string for replacing the normal cms page content209 return render_pylucid_response(request, 'auth/input_password.html', context,210 context_instance=RequestContext(request)211 )212 213 214 def _login_view(request, form_url, next_url):215 if DEBUG:216 request.page_msg(217 "Warning: DEBUG is ON! Should realy only use for debugging!"218 )219 220 pref_form = AuthPreferencesForm()221 preferences = pref_form.get_preferences()222 min_pause = preferences["min_pause"]223 ban_limit = preferences["ban_limit"]224 225 try:226 LogEntry.objects.request_limit(request, min_pause, ban_limit, app_label="pylucid_plugin.auth")227 except LogEntry.RequestTooFast:228 # min_pause is not observed, page_msg has been created -> display the normal cms page.229 return230 231 context = request.PYLUCID.context232 context["form_url"] = form_url233 234 if request.method == 'POST':235 username_form = UsernameForm(request.POST)236 if username_form.is_valid():237 user = username_form.user # User instance added in UsernameForm.is_valid()238 if not user.is_active:239 msg = _("Error: Your account is disabled!")240 LogEntry.objects.log_action(241 app_label="pylucid_plugin.auth", action="login", message=msg,242 data={"user_username": user.username}243 )244 request.page_msg.error(msg)245 return246 247 context["username"] = user.username248 249 if "plaintext_login" in request.POST:250 return _plaintext_login(request, context, user.username, next_url)251 else:252 return _sha_login(request, context, user, next_url)253 else:254 username_form = UsernameForm()255 256 context["form"] = username_form257 258 # return a string for replacing the normal cms page content259 return render_pylucid_response(request, 'auth/input_username.html', context)260 261 262 255 def http_get_view(request): 263 256 """ … … 265 258 """ 266 259 action = request.GET["auth"] 260 261 262 263 264 267 265 if action == "login": 268 next_url = request.GET.get("next_url", None) 269 if next_url: 270 form_url = settings.PYLUCID.AUTH_NEXT_URL % {"path": request.path, "next_url": next_url} 271 else: 272 next_url = request.path 273 form_url = "%s?%s" % (request.path, settings.PYLUCID.AUTH_GET_VIEW) 274 275 return _login_view(request, form_url, next_url) 266 # next_url = request.GET.get("next_url", None) 267 # if next_url: 268 # form_url = settings.PYLUCID.AUTH_NEXT_URL % {"path": request.path, "next_url": next_url} 269 # else: 270 # next_url = request.path 271 # form_url = "%s?%s" % (request.path, settings.PYLUCID.AUTH_GET_VIEW) 272 273 next_url = request.GET.get("next_url", request.path) 274 return _login_view(request, next_url) 275 elif action == "get_salt": 276 return _get_salt(request) 277 elif action == "sha_auth": 278 return _sha_auth(request) 276 279 elif action == "logout": 277 280 next_url = request.path 278 281 return _logout_view(request, next_url) 279 280 msg = _("Wrong get view parameter!") 281 LogEntry.objects.log_action(app_label="pylucid_plugin.auth", action="login", message=msg) 282 if settings.DEBUG: 283 request.page_msg.error(msg) 284 285 286 def authenticate(request): 287 """ 288 Login+Logout view via PluginPage 289 """ 290 if request.user.is_authenticated(): 291 return _logout_view(request) 292 else: 293 next_url = request.GET.get("next_url", None) 294 form_url = request.path 295 if next_url == None: 296 next_url = "/" 297 else: 298 form_url += "?next_url=" + next_url 299 300 return _login_view(request, form_url, next_url) 301 282 else: 283 debug_msg = "Wrong get view parameter!" 284 return _bad_request(debug_msg) # Return HttpResponseBadRequest 285 286 287 #def authenticate(request): 288 # """ 289 # Login+Logout view via PluginPage 290 # """ 291 # if request.user.is_authenticated(): 292 # return _logout_view(request) 293 # else: 294 # next_url = request.GET.get("next_url", None) 295 # form_url = request.path 296 # if next_url == None: 297 # next_url = "/" 298 # else: 299 # form_url += "?next_url=" + next_url 300 # 301 # return _login_view(request, form_url, next_url) -
branches/0.9/pylucid_project/pylucid_plugins/auth/__init__.py
r1634 r2572 1 1 # -*- coding: utf-8 -*- 2 3 from django.contrib.admin import AdminSite 4 5 # Change the template for django's normal login. 6 # So we can insert a link to JS-SHA-Login. 7 AdminSite.login_template = "auth/django_login.html" -
branches/0.9/pylucid_project/utils/crypt.py
r2161 r2572 135 135 return seed[:SALT_LEN] 136 136 137 def get_pseudo_salt(*args): 138 """ 139 generate a pseudo salt (used, if user is wrong) 140 """ 141 temp = "".join([repr(arg) for arg in args]) 142 return sha_constructor(temp).hexdigest()[:SALT_LEN] 143 137 144 138 145 def make_hash(txt, salt): … … 148 155 hash = sha_constructor(salt + smart_str(txt)).hexdigest() 149 156 return hash 157 150 158 151 159 def get_salt_and_hash(txt):