Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. import string
  2. import random
  3. from django.contrib.auth.forms import AuthenticationForm
  4. from django.core.urlresolvers import reverse
  5. from django.utils.translation import ugettext_lazy as _
  6. from django.core.exceptions import ObjectDoesNotExist
  7. from django import forms
  8. from django.db.models import get_model
  9. from django.contrib.auth.models import User
  10. from django.contrib.auth import forms as auth_forms
  11. from django.conf import settings
  12. from django.core import validators
  13. from django.core.exceptions import ValidationError
  14. from django.utils.http import int_to_base36
  15. from django.contrib.sites.models import get_current_site
  16. from django.contrib.auth.tokens import default_token_generator
  17. from oscar.core.loading import get_profile_class, get_class
  18. Dispatcher = get_class('customer.utils', 'Dispatcher')
  19. CommunicationEventType = get_model('customer', 'communicationeventtype')
  20. ProductAlert = get_model('customer', 'ProductAlert')
  21. def generate_username():
  22. uname = ''.join([random.choice(string.letters + string.digits + '_') for i in range(30)])
  23. try:
  24. User.objects.get(username=uname)
  25. return generate_username()
  26. except User.DoesNotExist:
  27. return uname
  28. class PasswordResetForm(auth_forms.PasswordResetForm):
  29. communication_type_code = "PASSWORD_RESET"
  30. def save(self, domain_override=None,
  31. subject_template_name='registration/password_reset_subject.txt',
  32. email_template_name='registration/password_reset_email.html',
  33. use_https=False, token_generator=default_token_generator,
  34. from_email=None, request=None, **kwargs):
  35. """
  36. Generates a one-use only link for resetting password and sends to the
  37. user.
  38. """
  39. site = get_current_site(request)
  40. if domain_override is not None:
  41. site.domain = site.name = domain_override
  42. for user in self.users_cache:
  43. # Build reset url
  44. reset_url = "%s://%s%s" % (
  45. 'https' if use_https else 'http',
  46. site.domain,
  47. reverse('password-reset-confirm', kwargs={
  48. 'uidb36': int_to_base36(user.id),
  49. 'token': token_generator.make_token(user)}))
  50. ctx = {
  51. 'site': site,
  52. 'reset_url': reset_url}
  53. messages = CommunicationEventType.objects.get_and_render(
  54. code=self.communication_type_code, context=ctx)
  55. Dispatcher().dispatch_user_messages(user, messages)
  56. class EmailAuthenticationForm(AuthenticationForm):
  57. """
  58. Extends the standard django AuthenticationForm, to support 75 character
  59. usernames. 75 character usernames are needed to support the EmailOrUsername
  60. auth backend.
  61. """
  62. username = forms.EmailField(label=_('Email Address'))
  63. class CommonPasswordValidator(validators.BaseValidator):
  64. # See http://www.smartplanet.com/blog/business-brains/top-20-most-common-passwords-of-all-time-revealed-8216123456-8216princess-8216qwerty/4519
  65. forbidden_passwords = [
  66. 'password',
  67. '1234',
  68. '12345'
  69. '123456',
  70. '123456y',
  71. '123456789',
  72. 'iloveyou',
  73. 'princess',
  74. 'monkey',
  75. 'rockyou',
  76. 'babygirl',
  77. 'monkey',
  78. 'qwerty',
  79. '654321',
  80. 'dragon',
  81. 'pussy',
  82. 'baseball',
  83. 'football',
  84. 'letmein',
  85. 'monkey',
  86. '696969',
  87. 'abc123',
  88. 'qwe123',
  89. 'qweasd',
  90. 'mustang',
  91. 'michael',
  92. 'shadow',
  93. 'master',
  94. 'jennifer',
  95. '111111',
  96. '2000',
  97. 'jordan',
  98. 'superman'
  99. 'harley'
  100. ]
  101. message = _("Please choose a less common password")
  102. code = 'password'
  103. def __init__(self, password_file=None):
  104. self.limit_value = password_file
  105. def clean(self, value):
  106. return value.strip()
  107. def compare(self, value, limit):
  108. return value in self.forbidden_passwords
  109. def get_forbidden_passwords(self):
  110. if self.limit_value is None:
  111. return self.forbidden_passwords
  112. class EmailUserCreationForm(forms.ModelForm):
  113. email = forms.EmailField(label=_('Email Address'))
  114. password1 = forms.CharField(label=_('Password'), widget=forms.PasswordInput,
  115. validators=[validators.MinLengthValidator(6),
  116. CommonPasswordValidator()])
  117. password2 = forms.CharField(label=_('Confirm Password'), widget=forms.PasswordInput)
  118. class Meta:
  119. model = User
  120. fields = ('email',)
  121. def clean_email(self):
  122. email = self.cleaned_data['email'].lower()
  123. try:
  124. User.objects.get(email=email)
  125. except User.DoesNotExist:
  126. return email
  127. raise forms.ValidationError(_("A user with that email address already exists."))
  128. def clean_password2(self):
  129. password1 = self.cleaned_data.get('password1', '')
  130. password2 = self.cleaned_data.get('password2', '')
  131. if password1 != password2:
  132. raise forms.ValidationError(_("The two password fields didn't match."))
  133. return password2
  134. def save(self, commit=True):
  135. user = super(EmailUserCreationForm, self).save(commit=False)
  136. user.set_password(self.cleaned_data['password1'])
  137. user.username = generate_username()
  138. if commit:
  139. user.save()
  140. return user
  141. class SearchByDateRangeForm(forms.Form):
  142. date_from = forms.DateField(required=False, label=_("From"))
  143. date_to = forms.DateField(required=False, label=_("To"))
  144. def clean(self):
  145. if self.is_valid() and not self.cleaned_data['date_from'] and not self.cleaned_data['date_to']:
  146. raise forms.ValidationError(_("At least one date field is required."))
  147. return super(SearchByDateRangeForm, self).clean()
  148. def description(self):
  149. if not self.is_bound or not self.is_valid():
  150. return _('All orders')
  151. date_from = self.cleaned_data['date_from']
  152. date_to = self.cleaned_data['date_to']
  153. if date_from and date_to:
  154. return _('Orders placed between %(date_from)s and %(date_to)s') % {
  155. 'date_from': date_from,
  156. 'date_to': date_to}
  157. elif date_from:
  158. return _('Orders placed since %s') % date_from
  159. elif date_to:
  160. return _('Orders placed until %s') % date_to
  161. def get_filters(self):
  162. date_from = self.cleaned_data['date_from']
  163. date_to = self.cleaned_data['date_to']
  164. if date_from and date_to:
  165. return {'date_placed__range': [date_from, date_to]}
  166. elif date_from and not date_to:
  167. return {'date_placed__gt': date_from}
  168. elif not date_from and date_to:
  169. return {'date_placed__lt': date_to}
  170. return {}
  171. class UserForm(forms.ModelForm):
  172. def __init__(self, user, *args, **kwargs):
  173. self.user = user
  174. kwargs['instance'] = user
  175. super(UserForm, self).__init__(*args, **kwargs)
  176. def clean_email(self):
  177. """
  178. Make sure that the email address is aways unique as it is
  179. used instead of the username. This is necessary because the
  180. unique-ness of email addresses is *not* enforced on the model
  181. level in ``django.contrib.auth.models.User``.
  182. """
  183. email = self.cleaned_data['email']
  184. try:
  185. User.objects.exclude(
  186. id=self.user.id).get(email=email)
  187. except User.DoesNotExist:
  188. return email
  189. else:
  190. raise ValidationError(
  191. _("A user with this email address already exists")
  192. )
  193. class Meta:
  194. model = User
  195. exclude = ('username', 'password', 'is_staff', 'is_superuser',
  196. 'is_active', 'last_login', 'date_joined',
  197. 'user_permissions', 'groups')
  198. if hasattr(settings, 'AUTH_PROFILE_MODULE'):
  199. Profile = get_profile_class()
  200. class UserAndProfileForm(forms.ModelForm):
  201. first_name = forms.CharField(
  202. label=_('First name'), max_length=128, required=False)
  203. last_name = forms.CharField(
  204. label=_('Last name'), max_length=128, required=False)
  205. email = forms.EmailField(label=_('Email address'))
  206. # Fields from user model
  207. user_fields = ('first_name', 'last_name', 'email')
  208. def __init__(self, user, *args, **kwargs):
  209. self.user = user
  210. try:
  211. instance = user.get_profile()
  212. except ObjectDoesNotExist:
  213. # User has no profile, try a blank one
  214. instance = Profile(user=user)
  215. kwargs['instance'] = instance
  216. super(UserAndProfileForm, self).__init__(*args, **kwargs)
  217. # Add user fields
  218. self.fields['first_name'].initial = self.instance.user.first_name
  219. self.fields['last_name'].initial = self.instance.user.last_name
  220. self.fields['email'].initial = self.instance.user.email
  221. # Ensure user fields are above profile
  222. order = list(self.user_fields)
  223. for field_name in self.fields.keys():
  224. if field_name not in self.user_fields:
  225. order.append(field_name)
  226. self.fields.keyOrder = order
  227. class Meta:
  228. model = Profile
  229. exclude = ('user',)
  230. def clean_email(self):
  231. email = self.cleaned_data['email']
  232. try:
  233. User.objects.exclude(
  234. id=self.user.id).get(email=email)
  235. except User.DoesNotExist:
  236. return email
  237. else:
  238. raise ValidationError(
  239. _("A user with this email address already exists")
  240. )
  241. def save(self, *args, **kwargs):
  242. user = self.instance.user
  243. user.first_name = self.cleaned_data['first_name']
  244. user.last_name = self.cleaned_data['last_name']
  245. user.email = self.cleaned_data['email']
  246. user.save()
  247. return super(ProfileForm, self).save(*args, **kwargs)
  248. ProfileForm = UserAndProfileForm
  249. else:
  250. ProfileForm = UserForm
  251. class ProductAlertForm(forms.ModelForm):
  252. email = forms.EmailField(required=True, label=_(u'Send notification to'),
  253. widget=forms.TextInput(attrs={
  254. 'placeholder': _('Enter your email')
  255. }))
  256. def __init__(self, user, product, *args, **kwargs):
  257. self.user = user
  258. self.product = product
  259. super(ProductAlertForm, self).__init__(*args, **kwargs)
  260. # Only show email field to unauthenticated users
  261. if user and user.is_authenticated():
  262. self.fields['email'].widget = forms.HiddenInput()
  263. self.fields['email'].required = False
  264. def save(self, commit=True):
  265. alert = super(ProductAlertForm, self).save(commit=False)
  266. if self.user.is_authenticated():
  267. alert.user = self.user
  268. alert.product = self.product
  269. if commit:
  270. alert.save()
  271. return alert
  272. def clean(self):
  273. cleaned_data = self.cleaned_data
  274. email = cleaned_data.get('email')
  275. if email:
  276. try:
  277. ProductAlert.objects.get(
  278. product=self.product, email=email,
  279. status=ProductAlert.ACTIVE)
  280. except ProductAlert.DoesNotExist:
  281. pass
  282. else:
  283. raise forms.ValidationError(_(
  284. "There is already an active stock alert for %s") % email)
  285. elif self.user.is_authenticated():
  286. try:
  287. ProductAlert.objects.get(product=self.product,
  288. user=self.user,
  289. status=ProductAlert.ACTIVE)
  290. except ProductAlert.DoesNotExist:
  291. pass
  292. else:
  293. raise forms.ValidationError(_(
  294. "You already have an active alert for this product"))
  295. return cleaned_data
  296. class Meta:
  297. model = ProductAlert
  298. exclude = ('user', 'key',
  299. 'status', 'date_confirmed', 'date_cancelled', 'date_closed',
  300. 'product')