Compare commits
8 Commits
abecc430a9
...
c79cb36f23
Author | SHA1 | Date | |
---|---|---|---|
c79cb36f23 | |||
cba4094e2b | |||
10ccab21eb | |||
53bb7c4d75 | |||
0cfb4eb697 | |||
6e700359ce | |||
8df4347932 | |||
1b8ee3d0f3 |
|
@ -4,7 +4,7 @@ By popular demand, I'm building a better anonkun. It doesn't do much right now t
|
||||||
## Requirements
|
## Requirements
|
||||||
Python 3.6+
|
Python 3.6+
|
||||||
PostgreSQL 10.4+
|
PostgreSQL 10.4+
|
||||||
Python packages: `django psycopg2 channels jinja2`
|
Python packages: `django psycopg2 channels jinja2 argon2-cffi`
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
/create_quest app views.
|
/create_quest app views.
|
||||||
"""
|
"""
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
|
@login_required(login_url='/login/')
|
||||||
def index(request):
|
def index(request):
|
||||||
"""
|
"""
|
||||||
The index page for creating new quests.
|
The index page for creating new quests.
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Quests 'n Shiet</h1>
|
<h1>Quests 'n Shiet</h1>
|
||||||
<a href="./quest/1">Unga Bunga Quest</a><br />
|
<a href="./quest/1">Unga Bunga Quest</a><br />
|
||||||
<a href="./create_quest">Create New Quest</a><br />
|
<a href="{{ url('create_quest:index') }}">Create New Quest</a><br />
|
||||||
<a href="./signup">Sign up</a><br />
|
<a href="{{ url('signup:index') }}">Sign up</a><br />
|
||||||
<a href="./login">Login</a><br />
|
<a href="{{ url('login:index') }}">Login</a><br />
|
||||||
|
<a href="{{ url('logout:index') }}">Logout</a><br />
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -36,6 +36,14 @@
|
||||||
<ul id="headerHidden" class="header" style="{% if request.session.get("hide_header") == True %}display:initial;{% else %}display:none;{% endif %}">
|
<ul id="headerHidden" class="header" style="{% if request.session.get("hide_header") == True %}display:initial;{% else %}display:none;{% endif %}">
|
||||||
<li><a onclick="toggleHeader();" href="javascript:void(0);">⤓</a></li>
|
<li><a onclick="toggleHeader();" href="javascript:void(0);">⤓</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<br /> <!-- TODO: make this more exact. -->
|
||||||
|
<div id="messages">
|
||||||
|
<ul class="messages">
|
||||||
|
{% for message in get_messages(request) %}
|
||||||
|
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
<div id="content">{% block content %}{% endblock %} </div>
|
<div id="content">{% block content %}{% endblock %} </div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
0
login/__init__.py
Normal file
0
login/__init__.py
Normal file
3
login/admin.py
Normal file
3
login/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
5
login/apps.py
Normal file
5
login/apps.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class LoginConfig(AppConfig):
|
||||||
|
name = 'login'
|
11
login/jinja2/login/index.html
Normal file
11
login/jinja2/login/index.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Login{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>Login</h1>
|
||||||
|
<form method="post" action="{{ url('login:index') }}">
|
||||||
|
{{ csrf_input }}
|
||||||
|
<input type="text" placeholder="Username" name="username" maxlength="20" required/><br />
|
||||||
|
<input type="password" placeholder="Password" name="password" maxlength="1024" required/><br />
|
||||||
|
<input type="submit" value="Log in" name="submit"/>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
0
login/migrations/__init__.py
Normal file
0
login/migrations/__init__.py
Normal file
3
login/models.py
Normal file
3
login/models.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
3
login/tests.py
Normal file
3
login/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
12
login/urls.py
Normal file
12
login/urls.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Login app URL configuration.
|
||||||
|
"""
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
app_name = 'login'
|
||||||
|
urlpatterns = [
|
||||||
|
path('', views.index, name='index'),
|
||||||
|
]
|
25
login/views.py
Normal file
25
login/views.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
/login app views.
|
||||||
|
"""
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.shortcuts import redirect, render
|
||||||
|
from django.contrib.auth import authenticate, login
|
||||||
|
|
||||||
|
def index(request):
|
||||||
|
"""
|
||||||
|
The login page.
|
||||||
|
"""
|
||||||
|
if request.method == "GET":
|
||||||
|
context = {}
|
||||||
|
return render(request, 'login/index.html', context)
|
||||||
|
username = request.POST['username']
|
||||||
|
password = request.POST['password']
|
||||||
|
user = authenticate(request, username=username, password=password)
|
||||||
|
if user is not None:
|
||||||
|
login(request, user)
|
||||||
|
messages.success(request, "Logged in")
|
||||||
|
return redirect('homepage:index')
|
||||||
|
else:
|
||||||
|
messages.error(request, "Invalid credentials")
|
||||||
|
return redirect('login:index')
|
0
logout/__init__.py
Normal file
0
logout/__init__.py
Normal file
3
logout/admin.py
Normal file
3
logout/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
5
logout/apps.py
Normal file
5
logout/apps.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class LogoutConfig(AppConfig):
|
||||||
|
name = 'logout'
|
0
logout/migrations/__init__.py
Normal file
0
logout/migrations/__init__.py
Normal file
3
logout/models.py
Normal file
3
logout/models.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
3
logout/tests.py
Normal file
3
logout/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
12
logout/urls.py
Normal file
12
logout/urls.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Logout app URL configuration.
|
||||||
|
"""
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
app_name = 'logout'
|
||||||
|
urlpatterns = [
|
||||||
|
path('', views.index, name='index'),
|
||||||
|
]
|
15
logout/views.py
Normal file
15
logout/views.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
/logout app views.
|
||||||
|
"""
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.contrib.auth import logout
|
||||||
|
|
||||||
|
def index(request):
|
||||||
|
"""
|
||||||
|
Logs the user out.
|
||||||
|
"""
|
||||||
|
logout(request)
|
||||||
|
messages.success(request, "Logged out")
|
||||||
|
return redirect('homepage:index')
|
0
signup/__init__.py
Normal file
0
signup/__init__.py
Normal file
3
signup/admin.py
Normal file
3
signup/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
5
signup/apps.py
Normal file
5
signup/apps.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class SignupConfig(AppConfig):
|
||||||
|
name = 'signup'
|
24
signup/jinja2/signup/index.html
Normal file
24
signup/jinja2/signup/index.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Sign up a new account{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>Sign up</h1>
|
||||||
|
<div id="namePassRules">
|
||||||
|
<p>Username rules:
|
||||||
|
<ul>
|
||||||
|
<li>Must be between 3 and 20 characters</li>
|
||||||
|
<li>Can only contain ASCII letters (case sensitive) and numbers</li>
|
||||||
|
</ul>
|
||||||
|
<p>Password rules:
|
||||||
|
<ul>
|
||||||
|
<li>Must be between 8 and 1024 characters</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<form method="post" action="{{ url('signup:index') }}">
|
||||||
|
{{ csrf_input }}
|
||||||
|
<input type="text" placeholder="Username" name="username" maxlength="20" required/><br />
|
||||||
|
<input type="text" placeholder="Email" name="email" maxlength="20" required/><br />
|
||||||
|
<input type="password" placeholder="Password" name="password" maxlength="1024" required/><br />
|
||||||
|
<input type="password" placeholder="Verify password" name="password_verify" maxlength="1024" required/><br />
|
||||||
|
<input type="submit" value="Sign up" name="submit"/>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
0
signup/migrations/__init__.py
Normal file
0
signup/migrations/__init__.py
Normal file
3
signup/models.py
Normal file
3
signup/models.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
3
signup/tests.py
Normal file
3
signup/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
12
signup/urls.py
Normal file
12
signup/urls.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
signup app URL configuration.
|
||||||
|
"""
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
app_name = 'signup'
|
||||||
|
urlpatterns = [
|
||||||
|
path('', views.index, name='index'),
|
||||||
|
]
|
13
signup/views.py
Normal file
13
signup/views.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
/signup app views.
|
||||||
|
"""
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
def index(request):
|
||||||
|
"""
|
||||||
|
The signup page.
|
||||||
|
"""
|
||||||
|
if request.method == "GET":
|
||||||
|
context = {}
|
||||||
|
return render(request, 'signup/index.html', context)
|
|
@ -3,8 +3,9 @@
|
||||||
Custom Jinja2 environment.
|
Custom Jinja2 environment.
|
||||||
"""
|
"""
|
||||||
import jinja2
|
import jinja2
|
||||||
from django.contrib.staticfiles.storage import staticfiles_storage
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.contrib.staticfiles.storage import staticfiles_storage
|
||||||
|
|
||||||
def environment(**options):
|
def environment(**options):
|
||||||
"""
|
"""
|
||||||
|
@ -12,11 +13,13 @@ def environment(**options):
|
||||||
"""
|
"""
|
||||||
env = jinja2.Environment(**options)
|
env = jinja2.Environment(**options)
|
||||||
env.globals.update({
|
env.globals.update({
|
||||||
'static': staticfiles_storage.url,
|
|
||||||
'url': reverse,
|
|
||||||
'undefined': jinja2.StrictUndefined,
|
'undefined': jinja2.StrictUndefined,
|
||||||
'autoescape': True,
|
'autoescape': True,
|
||||||
'trim_blocks': True,
|
'trim_blocks': True,
|
||||||
'lstrip_blocks': True,
|
'lstrip_blocks': True,
|
||||||
|
|
||||||
|
'url': reverse,
|
||||||
|
'static': staticfiles_storage.url,
|
||||||
|
'get_messages': messages.get_messages,
|
||||||
})
|
})
|
||||||
return env
|
return env
|
||||||
|
|
|
@ -31,9 +31,12 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'quest.apps.QuestConfig',
|
'users.apps.UsersConfig',
|
||||||
'homepage.apps.HomepageConfig',
|
'homepage.apps.HomepageConfig',
|
||||||
'create_quest.apps.CreateQuestConfig',
|
'create_quest.apps.CreateQuestConfig',
|
||||||
|
'quest.apps.QuestConfig',
|
||||||
|
'login.apps.LoginConfig',
|
||||||
|
'signup.apps.SignupConfig',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -58,6 +61,19 @@ TEMPLATES = [
|
||||||
'auto_reload': DEBUG,
|
'auto_reload': DEBUG,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
WSGI_APPLICATION = 'titivillus.wsgi.application'
|
WSGI_APPLICATION = 'titivillus.wsgi.application'
|
||||||
|
@ -87,6 +103,9 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
'OPTIONS': {
|
||||||
|
'min_length': 8,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
@ -119,3 +138,12 @@ STATIC_ROOT = '/usr/local/www/html/static/'
|
||||||
STATICFILES_DIRS = [
|
STATICFILES_DIRS = [
|
||||||
os.path.join(BASE_DIR, 'static'),
|
os.path.join(BASE_DIR, 'static'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
AUTH_USER_MODEL = 'users.User'
|
||||||
|
|
||||||
|
PASSWORD_HASHERS = [
|
||||||
|
'django.contrib.auth.hashers.Argon2PasswordHasher',
|
||||||
|
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
||||||
|
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
|
||||||
|
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
|
||||||
|
]
|
||||||
|
|
|
@ -11,4 +11,7 @@ urlpatterns = [
|
||||||
path('quest/', include('quest.urls')),
|
path('quest/', include('quest.urls')),
|
||||||
path('create_quest/', include('create_quest.urls')),
|
path('create_quest/', include('create_quest.urls')),
|
||||||
path('set_session/', include('set_session.urls')),
|
path('set_session/', include('set_session.urls')),
|
||||||
|
path('signup/', include('signup.urls')),
|
||||||
|
path('login/', include('login.urls')),
|
||||||
|
path('logout/', include('logout.urls')),
|
||||||
]
|
]
|
||||||
|
|
0
users/__init__.py
Normal file
0
users/__init__.py
Normal file
3
users/admin.py
Normal file
3
users/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
5
users/apps.py
Normal file
5
users/apps.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class UsersConfig(AppConfig):
|
||||||
|
name = 'users'
|
42
users/migrations/0001_initial.py
Normal file
42
users/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# Generated by Django 2.0.7 on 2018-08-10 20:30
|
||||||
|
|
||||||
|
import django.contrib.auth.models
|
||||||
|
import django.contrib.auth.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth', '0009_alter_user_last_name_max_length'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='User',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||||
|
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||||
|
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||||
|
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||||
|
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||||
|
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||||
|
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 20 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=20, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
|
||||||
|
('email', models.EmailField(max_length=254, verbose_name='email address')),
|
||||||
|
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
|
||||||
|
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'user',
|
||||||
|
'verbose_name_plural': 'users',
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
('objects', django.contrib.auth.models.UserManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
0
users/migrations/__init__.py
Normal file
0
users/migrations/__init__.py
Normal file
32
users/models.py
Normal file
32
users/models.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
A custom user model.
|
||||||
|
"""
|
||||||
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import AbstractUser
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.contrib.auth.validators import UnicodeUsernameValidator
|
||||||
|
|
||||||
|
class User(AbstractUser):
|
||||||
|
"""
|
||||||
|
A custom user model.
|
||||||
|
"""
|
||||||
|
username_validator = UnicodeUsernameValidator()
|
||||||
|
username = models.CharField(
|
||||||
|
_('username'),
|
||||||
|
max_length=20,
|
||||||
|
unique=True,
|
||||||
|
help_text=_("Required. 20 characters or fewer. "
|
||||||
|
+ "Letters, digits and @/./+/-/_ only."),
|
||||||
|
validators=[username_validator],
|
||||||
|
error_messages={
|
||||||
|
'unique': _("A user with that username already exists."),
|
||||||
|
},)
|
||||||
|
first_name = None
|
||||||
|
last_name = None
|
||||||
|
email = models.EmailField(_('email address'))
|
||||||
|
|
||||||
|
def get_full_name(self):
|
||||||
|
return None
|
||||||
|
def get_short_name(self):
|
||||||
|
return None
|
3
users/tests.py
Normal file
3
users/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
3
users/views.py
Normal file
3
users/views.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
Loading…
Reference in New Issue
Block a user