1class AppSettings(object):
2
3    class AuthenticationMethod:
4        USERNAME = 'username'
5        EMAIL = 'email'
6        USERNAME_EMAIL = 'username_email'
7
8    class EmailVerificationMethod:
9        # After signing up, keep the user account inactive until the email
10        # address is verified
11        MANDATORY = 'mandatory'
12        # Allow login with unverified e-mail (e-mail verification is
13        # still sent)
14        OPTIONAL = 'optional'
15        # Don't send e-mail verification mails during signup
16        NONE = 'none'
17
18    def __init__(self, prefix):
19        self.prefix = prefix
20        # If login is by email, email must be required
21        assert (not self.AUTHENTICATION_METHOD ==
22                self.AuthenticationMethod.EMAIL) or self.EMAIL_REQUIRED
23        # If login includes email, login must be unique
24        assert (self.AUTHENTICATION_METHOD ==
25                self.AuthenticationMethod.USERNAME) or self.UNIQUE_EMAIL
26        assert (self.EMAIL_VERIFICATION !=
27                self.EmailVerificationMethod.MANDATORY) \
28            or self.EMAIL_REQUIRED
29        if not self.USER_MODEL_USERNAME_FIELD:
30            assert not self.USERNAME_REQUIRED
31            assert self.AUTHENTICATION_METHOD \
32                not in (self.AuthenticationMethod.USERNAME,
33                        self.AuthenticationMethod.USERNAME_EMAIL)
34
35    def _setting(self, name, dflt):
36        from django.conf import settings
37        getter = getattr(settings,
38                         'ALLAUTH_SETTING_GETTER',
39                         lambda name, dflt: getattr(settings, name, dflt))
40        return getter(self.prefix + name, dflt)
41
42    @property
43    def DEFAULT_HTTP_PROTOCOL(self):
44        return self._setting("DEFAULT_HTTP_PROTOCOL", "http").lower()
45
46    @property
47    def EMAIL_CONFIRMATION_EXPIRE_DAYS(self):
48        """
49        Determines the expiration date of e-mail confirmation mails (#
50        of days)
51        """
52        from django.conf import settings
53        return self._setting("EMAIL_CONFIRMATION_EXPIRE_DAYS",
54                             getattr(settings, "EMAIL_CONFIRMATION_DAYS", 3))
55
56    @property
57    def EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL(self):
58        """
59        The URL to redirect to after a successful e-mail confirmation, in
60        case of an authenticated user
61        """
62        return self._setting("EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL",
63                             None)
64
65    @property
66    def EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL(self):
67        """
68        The URL to redirect to after a successful e-mail confirmation, in
69        case no user is logged in
70        """
71        from django.conf import settings
72        return self._setting("EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL",
73                             settings.LOGIN_URL)
74
75    @property
76    def EMAIL_CONFIRMATION_COOLDOWN(self):
77        """
78        The cooldown in seconds during which, after an email confirmation has
79        been sent, a second confirmation email will not be sent.
80        """
81        return self._setting("EMAIL_CONFIRMATION_COOLDOWN", 3 * 60)
82
83    @property
84    def EMAIL_REQUIRED(self):
85        """
86        The user is required to hand over an e-mail address when signing up
87        """
88        return self._setting("EMAIL_REQUIRED", False)
89
90    @property
91    def EMAIL_VERIFICATION(self):
92        """
93        See e-mail verification method
94        """
95        ret = self._setting("EMAIL_VERIFICATION",
96                            self.EmailVerificationMethod.OPTIONAL)
97        # Deal with legacy (boolean based) setting
98        if ret is True:
99            ret = self.EmailVerificationMethod.MANDATORY
100        elif ret is False:
101            ret = self.EmailVerificationMethod.OPTIONAL
102        return ret
103
104    @property
105    def AUTHENTICATION_METHOD(self):
106        ret = self._setting("AUTHENTICATION_METHOD",
107                            self.AuthenticationMethod.USERNAME)
108        return ret
109
110    @property
111    def EMAIL_MAX_LENGTH(self):
112        """
113        Adjust max_length of e-mail addresses
114        """
115        return self._setting("EMAIL_MAX_LENGTH", 254)
116
117    @property
118    def UNIQUE_EMAIL(self):
119        """
120        Enforce uniqueness of e-mail addresses
121        """
122        return self._setting("UNIQUE_EMAIL", True)
123
124    @property
125    def SIGNUP_EMAIL_ENTER_TWICE(self):
126        """
127        Signup email verification
128        """
129        return self._setting("SIGNUP_EMAIL_ENTER_TWICE", False)
130
131    @property
132    def SIGNUP_PASSWORD_ENTER_TWICE(self):
133        """
134        Signup password verification
135        """
136        legacy = self._setting('SIGNUP_PASSWORD_VERIFICATION', True)
137        return self._setting('SIGNUP_PASSWORD_ENTER_TWICE', legacy)
138
139    @property
140    def PASSWORD_MIN_LENGTH(self):
141        """
142        Minimum password Length
143        """
144        from django.conf import settings
145        ret = None
146        if not settings.AUTH_PASSWORD_VALIDATORS:
147            ret = self._setting("PASSWORD_MIN_LENGTH", 6)
148        return ret
149
150    @property
151    def EMAIL_SUBJECT_PREFIX(self):
152        """
153        Subject-line prefix to use for email messages sent
154        """
155        return self._setting("EMAIL_SUBJECT_PREFIX", None)
156
157    @property
158    def SIGNUP_FORM_CLASS(self):
159        """
160        Signup form
161        """
162        return self._setting("SIGNUP_FORM_CLASS", None)
163
164    @property
165    def USERNAME_REQUIRED(self):
166        """
167        The user is required to enter a username when signing up
168        """
169        return self._setting("USERNAME_REQUIRED", True)
170
171    @property
172    def USERNAME_MIN_LENGTH(self):
173        """
174        Minimum username Length
175        """
176        return self._setting("USERNAME_MIN_LENGTH", 1)
177
178    @property
179    def USERNAME_BLACKLIST(self):
180        """
181        List of usernames that are not allowed
182        """
183        return self._setting("USERNAME_BLACKLIST", [])
184
185    @property
186    def PASSWORD_INPUT_RENDER_VALUE(self):
187        """
188        render_value parameter as passed to PasswordInput fields
189        """
190        return self._setting("PASSWORD_INPUT_RENDER_VALUE", False)
191
192    @property
193    def ADAPTER(self):
194        return self._setting('ADAPTER',
195                             'allauth.account.adapter.DefaultAccountAdapter')
196
197    @property
198    def CONFIRM_EMAIL_ON_GET(self):
199        return self._setting('CONFIRM_EMAIL_ON_GET', False)
200
201    @property
202    def AUTHENTICATED_LOGIN_REDIRECTS(self):
203        return self._setting('AUTHENTICATED_LOGIN_REDIRECTS', True)
204
205    @property
206    def LOGIN_ON_EMAIL_CONFIRMATION(self):
207        """
208        Automatically log the user in once they confirmed their email address
209        """
210        return self._setting('LOGIN_ON_EMAIL_CONFIRMATION', False)
211
212    @property
213    def LOGIN_ON_PASSWORD_RESET(self):
214        """
215        Automatically log the user in immediately after resetting
216        their password.
217        """
218        return self._setting('LOGIN_ON_PASSWORD_RESET', False)
219
220    @property
221    def LOGOUT_REDIRECT_URL(self):
222        return self._setting('LOGOUT_REDIRECT_URL', '/')
223
224    @property
225    def LOGOUT_ON_GET(self):
226        return self._setting('LOGOUT_ON_GET', False)
227
228    @property
229    def LOGOUT_ON_PASSWORD_CHANGE(self):
230        return self._setting('LOGOUT_ON_PASSWORD_CHANGE', False)
231
232    @property
233    def USER_MODEL_USERNAME_FIELD(self):
234        return self._setting('USER_MODEL_USERNAME_FIELD', 'username')
235
236    @property
237    def USER_MODEL_EMAIL_FIELD(self):
238        return self._setting('USER_MODEL_EMAIL_FIELD', 'email')
239
240    @property
241    def SESSION_COOKIE_AGE(self):
242        """
243        Deprecated -- use Django's settings.SESSION_COOKIE_AGE instead
244        """
245        from django.conf import settings
246        return self._setting('SESSION_COOKIE_AGE', settings.SESSION_COOKIE_AGE)
247
248    @property
249    def SESSION_REMEMBER(self):
250        """
251        Controls the life time of the session. Set to `None` to ask the user
252        ("Remember me?"), `False` to not remember, and `True` to always
253        remember.
254        """
255        return self._setting('SESSION_REMEMBER', None)
256
257    @property
258    def TEMPLATE_EXTENSION(self):
259        """
260        A string defining the template extension to use, defaults to `html`.
261        """
262        return self._setting('TEMPLATE_EXTENSION', 'html')
263
264    @property
265    def FORMS(self):
266        return self._setting('FORMS', {})
267
268    @property
269    def LOGIN_ATTEMPTS_LIMIT(self):
270        """
271        Number of failed login attempts. When this number is
272        exceeded, the user is prohibited from logging in for the
273        specified `LOGIN_ATTEMPTS_TIMEOUT`
274        """
275        return self._setting('LOGIN_ATTEMPTS_LIMIT', 5)
276
277    @property
278    def LOGIN_ATTEMPTS_TIMEOUT(self):
279        """
280        Time period from last unsuccessful login attempt, during
281        which the user is prohibited from trying to log in.  Defaults to
282        5 minutes.
283        """
284        return self._setting('LOGIN_ATTEMPTS_TIMEOUT', 60 * 5)
285
286    @property
287    def EMAIL_CONFIRMATION_HMAC(self):
288        return self._setting('EMAIL_CONFIRMATION_HMAC', True)
289
290    @property
291    def SALT(self):
292        return self._setting('SALT', 'account')
293
294    @property
295    def PRESERVE_USERNAME_CASING(self):
296        return self._setting('PRESERVE_USERNAME_CASING', True)
297
298    @property
299    def USERNAME_VALIDATORS(self):
300        from django.core.exceptions import ImproperlyConfigured
301        from allauth.utils import import_attribute
302        from allauth.utils import get_user_model
303
304        path = self._setting('USERNAME_VALIDATORS', None)
305        if path:
306            ret = import_attribute(path)
307            if not isinstance(ret, list):
308                raise ImproperlyConfigured(
309                    'ACCOUNT_USERNAME_VALIDATORS is expected to be a list')
310        else:
311            if self.USER_MODEL_USERNAME_FIELD is not None:
312                ret = get_user_model()._meta.get_field(
313                    self.USER_MODEL_USERNAME_FIELD).validators
314            else:
315                ret = []
316        return ret
317
318
319# Ugly? Guido recommends this himself ...
320# http://mail.python.org/pipermail/python-ideas/2012-May/014969.html
321import sys  # noqa
322
323
324app_settings = AppSettings('ACCOUNT_')
325app_settings.__name__ = __name__
326sys.modules[__name__] = app_settings
327