diff --git a/dr_botzo/dr_botzo/context_processors.py b/dr_botzo/dr_botzo/context_processors.py new file mode 100644 index 0000000..6359a89 --- /dev/null +++ b/dr_botzo/dr_botzo/context_processors.py @@ -0,0 +1,14 @@ +"""Site processors to add additional template tags and whatnot.""" + +from django.contrib.sites.shortcuts import get_current_site +from django.utils.functional import SimpleLazyObject + + +def site(request): + site = SimpleLazyObject(lambda: get_current_site(request)) + protocol = 'https' if request.is_secure() else 'http' + + return { + 'site': site, + 'site_root': SimpleLazyObject(lambda: "{0}://{1}".format(protocol, site.domain)), + } diff --git a/dr_botzo/dr_botzo/settings.py b/dr_botzo/dr_botzo/settings.py index 19b43aa..fcf93a7 100644 --- a/dr_botzo/dr_botzo/settings.py +++ b/dr_botzo/dr_botzo/settings.py @@ -11,6 +11,8 @@ https://docs.djangoproject.com/en/1.6/ref/settings/ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os +from django.core.urlresolvers import reverse_lazy + BASE_DIR = os.path.dirname(os.path.dirname(__file__)) @@ -38,6 +40,7 @@ INSTALLED_APPS = ( 'django.contrib.sites', 'django_extensions', 'adminplus', + 'registration', 'rest_framework', 'countdown', 'dispatch', @@ -76,6 +79,7 @@ TEMPLATES = [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', + 'dr_botzo.context_processors.site', ], }, }, @@ -132,6 +136,16 @@ REST_FRAMEWORK = { } +EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' +EMAIL_FILE_PATH = BASE_DIR + + +# registration +LOGIN_REDIRECT_URL = reverse_lazy('index') +ACCOUNT_ACTIVATION_DAYS = 7 +REGISTRATION_AUTO_LOGIN = True + + # IRC bot stuff # tuple of hostname, port number, and password (or None) diff --git a/dr_botzo/dr_botzo/urls.py b/dr_botzo/dr_botzo/urls.py index 6196d80..16760f5 100644 --- a/dr_botzo/dr_botzo/urls.py +++ b/dr_botzo/dr_botzo/urls.py @@ -13,5 +13,6 @@ urlpatterns = patterns('', url(r'^markov/', include('markov.urls')), url(r'^races/', include('races.urls')), + url(r'^accounts/', include('registration.backends.default.urls')), url(r'^admin/', include(admin.site.urls)), ) diff --git a/dr_botzo/static/css/core.css b/dr_botzo/static/css/core.css index 98d7c54..5bfc478 100644 --- a/dr_botzo/static/css/core.css +++ b/dr_botzo/static/css/core.css @@ -1,323 +1,11 @@ -* { - margin: 0; - padding: 0; -} - html, body { - font-family: "Helvetica", "Arial", sans-serif; + font-family: "Oxygen", "Helvetica", "Arial", sans-serif; color: #333333; - background: #EFEFEF; + background: #FAFAFA; height: 100%; } -a:link, a:visited, a:hover, a:active { - color: #333333; -} - -table { - padding: 5px; -} - -#mainwrapper { - min-height: 100%; - position: relative; - - width: 900px; - margin-left: auto; - margin-right: auto; -} - -#header { - color: white; - background: #811610; - font-size: 11pt; - - padding: 5px 10px; - - border-left: 1px solid #CCCCCC; - border-right: 1px solid #CCCCCC; -} - -#header a:link, #header a:visited, #header a:hover, #header a:active { - color: white; - text-decoration: none; -} - -#header ul { - list-style-type: none; - margin: 0; - padding: 0; -} - -#header li { - display: inline; -} - -#header #subnav { - float: right; -} - -#messages { - background: #EFEFEF; - border: 1px solid #BBBBBB; - - width: 50%; - margin-left: auto; - margin-right: auto; - - padding: 10px; - padding-left: 20px; - margin-bottom: 50px; -} - -#messages ul { - list-style-type: none; - padding-left: 10px; -} - -#messages .debug { - color: cyan; -} - -#messages .info { - color: black; -} - -#messages .success { - color: green; -} - -#messages .warning { - color: orange; -} - -#messages .error { - color: red; -} - -#body { - background: white; - - font-size: 11pt; - padding-top: 20px; - padding-bottom: 50px; - - border-left: 1px solid #CCCCCC; - border-right: 1px solid #CCCCCC; -} - -#loginform { - background: #EFEFEF; - - width: 50%; - margin-left: auto; - margin-right: auto; - margin-top: 50px; - padding: 10px; - - border: 1px solid #BBBBBB; -} - #content { - margin-left: 25px; - margin-right: 25px; - line-height: 150%; + padding: 0 25px; + padding-top: 75px; } - -#content h1, #content h2, #content h3, #content h4, #content h5, #content h6 { - color: #811610; - margin-top: 25px; - margin-bottom: 25px; - clear: both; -} - -#content p, #content ul, #content ol { - margin-bottom: 20px; -} - -#content hr { - margin-top: 10px; - margin-bottom: 10px; -} - -#content blockquote { - margin: 5px; - padding: 5px; - margin-left: 20px; - border: 1px solid #e0e0e0; -} - -#content .journal-entry { - margin-bottom: 20px; -} - -#content .unpub-warning { - color: red; -} - -#content .entry-header a:link, -#content .entry-header a:visited, -#content .entry-header a:hover, -#content .entry-header a:active { - color: #811610; - text-decoration: none; -} - -#content .entry-sep { - width: 30%; - margin-left: auto; - margin-right: auto; - border-top: 1px solid #e0e0e0; - margin-top: 35px; - margin-bottom: 50px; -} - -#content ol, #content ul { - margin-left: 20px; -} - -#content hr { - width: 50%; - margin-top: 25px; - margin-bottom: 25px; - margin-left: auto; - margin-right: auto; - color: #CCCCCC; -} - -#actions { - margin-left: 100px; - margin-right: 100px; -} - -div.actions { - margin-bottom: 50px; -} - -div.actionblock { - margin-top: 10px; - padding: 5px; -} - -div.actionform { - margin-top: 10px; -} - -#editform #id_title, #editform #id_tag_str { - width: 75%; -} - -.submission table th { - text-align: right; -} - -.errorlist { - border: 1px solid red; - background: #FF8888; - margin-bottom: 5px; -} - -.journal-entry .entry-header { - margin-bottom: 0px; -} - -.journal-entry .entry-header h1 { - font-size: 24pt; -} - -.journal-entry .entry-body { - clear: both; - padding: 5px; -} - -.journal-entry .entry-subheader { - font-size: 9pt; - padding: 5px 5px 5px 25px; - position: relative; - top: -5px; -} - -.journal-entry .entry-footer { - font-size: 8pt; - color: #888888; - padding: 5px 5px 5px 0; -} - -.journal-entry .entry-footer a:link, -.journal-entry .entry-footer a:visited, -.journal-entry .entry-footer a:hover, -.journal-entry .entry-footer a:active { - font-size: 8pt; - color: #888888; -} - -#pagination { - background: white; - width: 60%; - margin-left: auto; - margin-right: auto; - text-align: center; -} - -.page-previous { - margin-right: 15px; -} - -.page-next { - margin-left: 15px; -} - -.article-image-left { - float: left; - margin: 10px; - margin-top: 0; - margin-left: 0; -} - -.article-image-right { - float: right; - margin: 10px; - margin-top: 0; - margin-right: 0; -} - -.px400 { - width: 400px; - height: auto; -} - -.shadow { - box-shadow: 2px 2px 3px #aaaaaa; -} - -.thumbnail-image { - width: 150px; - height: auto; - margin: 5px; -} - -#footer { - width: 100%; - height: 25px; - background: #EFEFEF; - - padding: 10px 0; - - border-top: 1px solid #BBBBBB; - - font-size: 9pt; - color: #666666; - text-align: center; -} - -#footer p { - margin-bottom: 0; -} - -#footer a:link, #footer a:visited, #footer a:hover, #footer a:active { - color: #666666; -} - -/* - vi:tabstop=4:expandtab:autoindent - */ diff --git a/dr_botzo/static/css/registration.css b/dr_botzo/static/css/registration.css new file mode 100644 index 0000000..02390b7 --- /dev/null +++ b/dr_botzo/static/css/registration.css @@ -0,0 +1,44 @@ +.registration_wrap form { + margin-left: 10%; + margin-right: 10%; + clear: both; +} + +.registration_wrap label { + display: inline-block; + width: 30%; +} + +.registration_wrap input[type="text"], +.registration_wrap input[type="email"], +.registration_wrap input[type="password"] { + width: 100%; +} + +.registration_wrap .helptext { + color: #888888; + font-size: 0.75em; + display: block; +} + +.registration_wrap input[type="submit"] { + line-height: 350px; + width: 25%; +} + +.registration_wrap .errorlist, +.registration_wrap .errorlist li { + background: none; + color: red; + display: inline; + border: none; + margin-left: 0 !important; +} + +.registration_wrap .extra { + clear: both; + margin-top: 100px; + text-align: center; + margin-left: auto; + margin-right: auto; +} diff --git a/dr_botzo/templates/registration/activate.html b/dr_botzo/templates/registration/activate.html new file mode 100644 index 0000000..ac5fb37 --- /dev/null +++ b/dr_botzo/templates/registration/activate.html @@ -0,0 +1,16 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} + +{% block registration_content %} +
{% trans "Account activation failed." %}
+{% endblock %} + + +{% comment %} +**registration/activate.html** + +Used if account activation fails. With the default setup, has the following context: + +``activation_key`` + The activation key used during the activation attempt. +{% endcomment %} diff --git a/dr_botzo/templates/registration/activation_complete.html b/dr_botzo/templates/registration/activation_complete.html new file mode 100644 index 0000000..cf12988 --- /dev/null +++ b/dr_botzo/templates/registration/activation_complete.html @@ -0,0 +1,22 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} + +{% block title %}{% trans "Account Activated" %}{% endblock %} + +{% block registration_content %} ++ {% trans "Your account is now activated." %} + {% if not user.is_authenticated %} + {% trans "You can log in." %} + {% endif %} +
+{% endblock %} + + +{% comment %} +**registration/activation_complete.html** + +Used after successful account activation. This template has no context +variables of its own, and should simply inform the user that their +account is now active. +{% endcomment %} diff --git a/dr_botzo/templates/registration/activation_email.html b/dr_botzo/templates/registration/activation_email.html new file mode 100644 index 0000000..c15b89d --- /dev/null +++ b/dr_botzo/templates/registration/activation_email.html @@ -0,0 +1,77 @@ +{% load i18n %} +{% load url from future %} + + + + ++ {% blocktrans with site_name=site.name %} + You (or someone pretending to be you) have asked to register an account at + {{ site_name }}. If this wasn't you, please ignore this email + and your address will be removed from our records. + {% endblocktrans %} +
++ {% blocktrans %} + To activate this account, please click the following link within the next + {{ expiration_days }} days: + {% endblocktrans %} +
+ ++ + {{site.domain}}{% url 'registration_activate' activation_key %} + +
++ {% blocktrans with site_name=site.name %} + Sincerely, + {{ site_name }} Management + {% endblocktrans %} +
+ + + + + +{% comment %} +**registration/activation_email.html** + +Used to generate the html body of the activation email. Should display a +link the user can click to activate the account. This template has the +following context: + +``activation_key`` + The activation key for the new account. + +``expiration_days`` + The number of days remaining during which the account may be + activated. + +``site`` + An object representing the site on which the user registered; + depending on whether ``django.contrib.sites`` is installed, this + may be an instance of either ``django.contrib.sites.models.Site`` + (if the sites application is installed) or + ``django.contrib.sites.models.RequestSite`` (if not). Consult `the + documentation for the Django sites framework +{% trans "Forgot your password?" %} {% trans "Reset it" %}. + {% trans "Not a member?" %} {% trans "Register" %}.
+{% trans "Successfully logged out" %}.
+{% endblock %} diff --git a/dr_botzo/templates/registration/password_change_done.html b/dr_botzo/templates/registration/password_change_done.html new file mode 100644 index 0000000..55e60e4 --- /dev/null +++ b/dr_botzo/templates/registration/password_change_done.html @@ -0,0 +1,11 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} + +{% block title %}{% trans "Password changed" %}{% endblock %} + +{% block registration_content %} +{% trans "Password successfully changed!" %}
+{% endblock %} + + +{# This is used by django.contrib.auth #} diff --git a/dr_botzo/templates/registration/password_change_form.html b/dr_botzo/templates/registration/password_change_form.html new file mode 100644 index 0000000..fb96ab3 --- /dev/null +++ b/dr_botzo/templates/registration/password_change_form.html @@ -0,0 +1,17 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} +{% load bootstrap3 %} + +{% block title %}{% trans "Change password" %}{% endblock %} + +{% block registration_content %} + +{% endblock %} + + +{# This is used by django.contrib.auth #} diff --git a/dr_botzo/templates/registration/password_reset_complete.html b/dr_botzo/templates/registration/password_reset_complete.html new file mode 100644 index 0000000..1bd5d94 --- /dev/null +++ b/dr_botzo/templates/registration/password_reset_complete.html @@ -0,0 +1,14 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} + +{% block title %}{% trans "Password reset complete" %}{% endblock %} + +{% block registration_content %} ++ {% trans "Your password has been reset!" %} + {% trans "You may now" %} {% trans "log in" %}. +
+{% endblock %} + + +{# This is used by django.contrib.auth #} diff --git a/dr_botzo/templates/registration/password_reset_confirm.html b/dr_botzo/templates/registration/password_reset_confirm.html new file mode 100644 index 0000000..6b673f4 --- /dev/null +++ b/dr_botzo/templates/registration/password_reset_confirm.html @@ -0,0 +1,18 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} +{% load bootstrap3 %} + +{% block title %}{% trans "Confirm password reset" %}{% endblock %} + +{% block registration_content %} +{% trans "Enter your new password below to reset your password:" %}
+ +{% endblock %} + + +{# This is used by django.contrib.auth #} diff --git a/dr_botzo/templates/registration/password_reset_done.html b/dr_botzo/templates/registration/password_reset_done.html new file mode 100644 index 0000000..be4e209 --- /dev/null +++ b/dr_botzo/templates/registration/password_reset_done.html @@ -0,0 +1,16 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} + +{% block title %}{% trans "Password reset" %}{% endblock %} + +{% block registration_content %} ++ {% blocktrans %} + We have sent you an email with a link to reset your password. Please check + your email and click the link to continue. + {% endblocktrans %} +
+{% endblock %} + + +{# This is used by django.contrib.auth #} diff --git a/dr_botzo/templates/registration/password_reset_email.html b/dr_botzo/templates/registration/password_reset_email.html new file mode 100644 index 0000000..67b0253 --- /dev/null +++ b/dr_botzo/templates/registration/password_reset_email.html @@ -0,0 +1,26 @@ +{% load i18n %} +{% load url from future %} + +{% blocktrans %}Greetings{% endblocktrans %} {% if user.get_full_name %}{{ user.get_full_name }}{% else %}{{ user }}{% endif %}, + +{% blocktrans %} +You are receiving this email because you (or someone pretending to be you) +requested that your password be reset on the {{ domain }} site. If you do not +wish to reset your password, please ignore this message. +{% endblocktrans %} + +{% blocktrans %} +To reset your password, please click the following link, or copy and paste it +into your web browser: +{% endblocktrans %} + +{{ protocol }}://{{ domain }}{% url 'auth_password_reset_confirm' uid token %} + +{% blocktrans %}Your username, in case you've forgotten:{% endblocktrans %} {{ user.username }} + + +{% blocktrans %}Best regards{% endblocktrans %}, +{{ site_name }} {% blocktrans %}Management{% endblocktrans %} + + +{# This is used by django.contrib.auth #} diff --git a/dr_botzo/templates/registration/password_reset_form.html b/dr_botzo/templates/registration/password_reset_form.html new file mode 100644 index 0000000..5280b18 --- /dev/null +++ b/dr_botzo/templates/registration/password_reset_form.html @@ -0,0 +1,18 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} +{% load bootstrap3 %} + +{% block title %}{% trans "Reset password" %}{% endblock %} + +{% block registration_content %} +Forgot your password? Enter your email in the form below and we'll send you instructions for creating a new one.
+ +{% endblock %} + + +{# This is used by django.contrib.auth #} diff --git a/dr_botzo/templates/registration/registration_base.html b/dr_botzo/templates/registration/registration_base.html new file mode 100644 index 0000000..345a4c9 --- /dev/null +++ b/dr_botzo/templates/registration/registration_base.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% block extra_media %}{% load static %} + +{% endblock %} + +{% block navbarbrand %} +{{ site.domain }} +{% endblock %} + +{% block content %} +{% trans "Sorry, but registration is closed at this moment. Come back later." %}
+{% endblock %} diff --git a/dr_botzo/templates/registration/registration_complete.html b/dr_botzo/templates/registration/registration_complete.html new file mode 100644 index 0000000..ce35bb0 --- /dev/null +++ b/dr_botzo/templates/registration/registration_complete.html @@ -0,0 +1,18 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} + +{% block title %}{% trans "Activation email sent" %}{% endblock %} + +{% block registration_content %} +{% trans "Please check your email to complete the registration process." %}
+{% endblock %} + + +{% comment %} +**registration/registration_complete.html** + +Used after successful completion of the registration form. This +template has no context variables of its own, and should simply inform +the user that an email containing account-activation information has +been sent. +{% endcomment %} diff --git a/dr_botzo/templates/registration/registration_form.html b/dr_botzo/templates/registration/registration_form.html new file mode 100644 index 0000000..d8a9721 --- /dev/null +++ b/dr_botzo/templates/registration/registration_form.html @@ -0,0 +1,27 @@ +{% extends "registration/registration_base.html" %} +{% load i18n %} +{% load bootstrap3 %} + +{% block title %}{% trans "Register for an account" %}{% endblock %} + +{% block registration_content %} + +{% endblock %} + + +{% comment %} +**registration/registration_form.html** +Used to show the form users will fill out to register. By default, has +the following context: + +``form`` + The registration form. This will be an instance of some subclass + of ``django.forms.Form``; consult `Django's forms documentation +