Browse Source

Initial commit

pull/7/head
Pēteris Caune 9 years ago
commit
00cdc313ec
29 changed files with 838 additions and 0 deletions
  1. +1
    -0
      .gitignore
  2. +0
    -0
      hc/__init__.py
  3. +0
    -0
      hc/accounts/__init__.py
  4. +3
    -0
      hc/accounts/admin.py
  5. +5
    -0
      hc/accounts/forms.py
  6. +0
    -0
      hc/accounts/migrations/__init__.py
  7. +3
    -0
      hc/accounts/models.py
  8. +3
    -0
      hc/accounts/tests.py
  9. +9
    -0
      hc/accounts/urls.py
  10. +49
    -0
      hc/accounts/views.py
  11. +0
    -0
      hc/checks/__init__.py
  12. +8
    -0
      hc/checks/admin.py
  13. +24
    -0
      hc/checks/migrations/0001_initial.py
  14. +23
    -0
      hc/checks/migrations/0002_auto_20150610_1852.py
  15. +0
    -0
      hc/checks/migrations/__init__.py
  16. +13
    -0
      hc/checks/models.py
  17. +3
    -0
      hc/checks/tests.py
  18. +7
    -0
      hc/checks/urls.py
  19. +16
    -0
      hc/checks/views.py
  20. +111
    -0
      hc/settings.py
  21. +8
    -0
      hc/urls.py
  22. +16
    -0
      hc/wsgi.py
  23. +10
    -0
      manage.py
  24. +3
    -0
      requirements.txt
  25. +5
    -0
      static/css/bootstrap.min.css
  26. +476
    -0
      static/css/creative.css
  27. +22
    -0
      templates/accounts/login.html
  28. +5
    -0
      templates/accounts/login_link_sent.html
  29. +15
    -0
      templates/base.html

+ 1
- 0
.gitignore View File

@ -0,0 +1 @@
__pycache__/

+ 0
- 0
hc/__init__.py View File


+ 0
- 0
hc/accounts/__init__.py View File


+ 3
- 0
hc/accounts/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 5
- 0
hc/accounts/forms.py View File

@ -0,0 +1,5 @@
from django import forms
class EmailForm(forms.Form):
email = forms.EmailField()

+ 0
- 0
hc/accounts/migrations/__init__.py View File


+ 3
- 0
hc/accounts/models.py View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

+ 3
- 0
hc/accounts/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 9
- 0
hc/accounts/urls.py View File

@ -0,0 +1,9 @@
from django.conf.urls import url
from hc.accounts import views
urlpatterns = [
url(r'^login/$', views.login, name="hc-login"),
url(r'^login_link_sent/$', views.login_link_sent, name="hc-login-link-sent"),
url(r'^check_token/([\w-]+)/$', views.check_token, name="hc-check-token"),
]

+ 49
- 0
hc/accounts/views.py View File

@ -0,0 +1,49 @@
import uuid
from django.conf import settings
from django.contrib.auth.models import User
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.shortcuts import redirect, render
from hc.accounts.forms import EmailForm
def login(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = EmailForm(request.POST)
# check whether it's valid:
if form.is_valid():
email = form.cleaned_data["email"]
user = User.objects.get(email=email)
token = str(uuid.uuid4())
user.set_password(token)
user.save()
login_link = reverse("hc-check-token", args=[token])
login_link = settings.SITE_ROOT + login_link
body = "login link: %s" % login_link
send_mail('Log In', body, '[email protected]', [email], fail_silently=False)
# FIXME send login token here
return redirect("hc-login-link-sent")
else:
form = EmailForm()
ctx = {
"form": form
}
return render(request, "accounts/login.html", ctx)
def login_link_sent(request):
return render(request, "accounts/login_link_sent.html")
def check_token(request):
return render(request, "accounts/login_link_sent.html")

+ 0
- 0
hc/checks/__init__.py View File


+ 8
- 0
hc/checks/admin.py View File

@ -0,0 +1,8 @@
from django.contrib import admin
from hc.checks.models import Canary
@admin.register(Canary)
class CanaryAdmin(admin.ModelAdmin):
list_display = ("id", "code", "user", "last_ping")

+ 24
- 0
hc/checks/migrations/0001_initial.py View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import uuid
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Canary',
fields=[
('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')),
('code', models.UUIDField(default=uuid.uuid4, editable=False)),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
],
),
]

+ 23
- 0
hc/checks/migrations/0002_auto_20150610_1852.py View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('checks', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='canary',
options={'verbose_name_plural': 'canaries'},
),
migrations.AddField(
model_name='canary',
name='last_ping',
field=models.DateTimeField(null=True, blank=True),
),
]

+ 0
- 0
hc/checks/migrations/__init__.py View File


+ 13
- 0
hc/checks/models.py View File

@ -0,0 +1,13 @@
import uuid
from django.contrib.auth.models import User
from django.db import models
class Canary(models.Model):
class Meta:
verbose_name_plural = "canaries"
code = models.UUIDField(default=uuid.uuid4, editable=False)
user = models.ForeignKey(User)
last_ping = models.DateTimeField(null=True, blank=True)

+ 3
- 0
hc/checks/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 7
- 0
hc/checks/urls.py View File

@ -0,0 +1,7 @@
from django.conf.urls import url
from hc.checks import views
urlpatterns = [
url(r'^ping/([\w-]+)/$', views.ping, name="hc-ping"),
]

+ 16
- 0
hc/checks/views.py View File

@ -0,0 +1,16 @@
from django.http import HttpResponse, HttpResponseBadRequest
from django.utils import timezone
from hc.checks.models import Canary
def ping(request, code):
try:
canary = Canary.objects.get(code=code)
except Canary.DoesNotExist:
return HttpResponseBadRequest()
canary.last_ping = timezone.now()
canary.save()
return HttpResponse()

+ 111
- 0
hc/settings.py View File

@ -0,0 +1,111 @@
"""
Django settings for hc project.
Generated by 'django-admin startproject' using Django 1.8.2.
For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '9)gjy!j50uvbcy#y9ifoh@9pf%3m5^-9h0jv@+3^ln$%az8e(7'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bootstrap3',
'hc.accounts',
'hc.checks'
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)
ROOT_URLCONF = 'hc.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'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 = 'hc.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'hc',
'USER': 'hc',
'PASSWORD': '',
'HOST': '192.168.1.111',
'PORT': 5432,
'TEST': {'CHARSET': 'UTF8'}
}
}
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
SITE_ROOT = "http://localhost:8000"
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]

+ 8
- 0
hc/urls.py View File

@ -0,0 +1,8 @@
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^accounts/', include('hc.accounts.urls')),
url(r'^', include('hc.checks.urls')),
]

+ 16
- 0
hc/wsgi.py View File

@ -0,0 +1,16 @@
"""
WSGI config for hc project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hc.settings")
application = get_wsgi_application()

+ 10
- 0
manage.py View File

@ -0,0 +1,10 @@
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hc.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)

+ 3
- 0
requirements.txt View File

@ -0,0 +1,3 @@
Django==1.8.2
django-bootstrap3
psycopg2==2.6

+ 5
- 0
static/css/bootstrap.min.css
File diff suppressed because it is too large
View File


+ 476
- 0
static/css/creative.css View File

@ -0,0 +1,476 @@
/*!
* Start Bootstrap - Creative Bootstrap Theme (http://startbootstrap.com)
* Code licensed under the Apache License v2.0.
* For details, see http://www.apache.org/licenses/LICENSE-2.0.
*/
html,
body {
width: 100%;
height: 100%;
}
body {
font-family: Merriweather,'Helvetica Neue',Arial,sans-serif;
}
hr {
max-width: 50px;
border-color: #f05f40;
border-width: 3px;
}
hr.light {
border-color: #fff;
}
a {
color: #f05f40;
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
a:hover,
a:focus {
color: #eb3812;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
}
p {
margin-bottom: 20px;
font-size: 16px;
line-height: 1.5;
}
.bg-primary {
background-color: #f05f40;
}
.bg-dark {
color: #fff;
background-color: #222;
}
.text-faded {
color: rgba(255,255,255,.7);
}
section {
padding: 100px 0;
}
aside {
padding: 50px 0;
}
.no-padding {
padding: 0;
}
.navbar-default {
border-color: rgba(34,34,34,.05);
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
background-color: #fff;
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
.navbar-default .navbar-header .navbar-brand {
text-transform: uppercase;
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
font-weight: 700;
color: #f05f40;
}
.navbar-default .navbar-header .navbar-brand:hover,
.navbar-default .navbar-header .navbar-brand:focus {
color: #eb3812;
}
.navbar-default .nav > li>a,
.navbar-default .nav>li>a:focus {
text-transform: uppercase;
font-size: 13px;
font-weight: 700;
color: #222;
}
.navbar-default .nav > li>a:hover,
.navbar-default .nav>li>a:focus:hover {
color: #f05f40;
}
.navbar-default .nav > li.active>a,
.navbar-default .nav>li.active>a:focus {
color: #f05f40!important;
background-color: transparent;
}
.navbar-default .nav > li.active>a:hover,
.navbar-default .nav>li.active>a:focus:hover {
background-color: transparent;
}
@media(min-width:768px) {
.navbar-default {
border-color: rgba(255,255,255,.3);
background-color: transparent;
}
.navbar-default .navbar-header .navbar-brand {
color: rgba(255,255,255,.7);
}
.navbar-default .navbar-header .navbar-brand:hover,
.navbar-default .navbar-header .navbar-brand:focus {
color: #fff;
}
.navbar-default .nav > li>a,
.navbar-default .nav>li>a:focus {
color: rgba(255,255,255,.7);
}
.navbar-default .nav > li>a:hover,
.navbar-default .nav>li>a:focus:hover {
color: #fff;
}
.navbar-default.affix {
border-color: rgba(34,34,34,.05);
background-color: #fff;
}
.navbar-default.affix .navbar-header .navbar-brand {
font-size: 14px;
color: #f05f40;
}
.navbar-default.affix .navbar-header .navbar-brand:hover,
.navbar-default.affix .navbar-header .navbar-brand:focus {
color: #eb3812;
}
.navbar-default.affix .nav > li>a,
.navbar-default.affix .nav>li>a:focus {
color: #222;
}
.navbar-default.affix .nav > li>a:hover,
.navbar-default.affix .nav>li>a:focus:hover {
color: #f05f40;
}
}
header {
position: relative;
width: 100%;
min-height: auto;
text-align: center;
color: #fff;
background-image: url(../img/header.jpg);
background-position: center;
-webkit-background-size: cover;
-moz-background-size: cover;
background-size: cover;
-o-background-size: cover;
}
header .header-content {
position: relative;
width: 100%;
padding: 100px 15px;
text-align: center;
}
header .header-content .header-content-inner h1 {
margin-top: 0;
margin-bottom: 0;
text-transform: uppercase;
font-weight: 700;
}
header .header-content .header-content-inner hr {
margin: 30px auto;
}
header .header-content .header-content-inner p {
margin-bottom: 50px;
font-size: 16px;
font-weight: 300;
color: rgba(255,255,255,.7);
}
@media(min-width:768px) {
header {
min-height: 100%;
}
header .header-content {
position: absolute;
top: 50%;
padding: 0 50px;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
header .header-content .header-content-inner {
margin-right: auto;
margin-left: auto;
max-width: 1000px;
}
header .header-content .header-content-inner p {
margin-right: auto;
margin-left: auto;
max-width: 80%;
font-size: 18px;
}
}
.section-heading {
margin-top: 0;
}
.service-box {
margin: 50px auto 0;
max-width: 400px;
}
@media(min-width:992px) {
.service-box {
margin: 20px auto 0;
}
}
.service-box p {
margin-bottom: 0;
}
.portfolio-box {
display: block;
position: relative;
margin: 0 auto;
max-width: 650px;
}
.portfolio-box .portfolio-box-caption {
display: block;
position: absolute;
bottom: 0;
width: 100%;
height: 100%;
text-align: center;
color: #fff;
opacity: 0;
background: rgba(240,95,64,.9);
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content {
position: absolute;
top: 50%;
width: 100%;
text-align: center;
transform: translateY(-50%);
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category,
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
padding: 0 15px;
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category {
text-transform: uppercase;
font-size: 14px;
font-weight: 600;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
font-size: 18px;
}
.portfolio-box:hover .portfolio-box-caption {
opacity: 1;
}
@media(min-width:768px) {
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category {
font-size: 16px;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
font-size: 22px;
}
}
.call-to-action h2 {
margin: 0 auto 20px;
}
.text-primary {
color: #f05f40;
}
.no-gutter > [class*=col-] {
padding-right: 0;
padding-left: 0;
}
.btn-default {
border-color: #fff;
color: #222;
background-color: #fff;
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
.btn-default:hover,
.btn-default:focus,
.btn-default.focus,
.btn-default:active,
.btn-default.active,
.open > .dropdown-toggle.btn-default {
border-color: #ededed;
color: #222;
background-color: #f2f2f2;
}
.btn-default:active,
.btn-default.active,
.open > .dropdown-toggle.btn-default {
background-image: none;
}
.btn-default.disabled,
.btn-default[disabled],
fieldset[disabled] .btn-default,
.btn-default.disabled:hover,
.btn-default[disabled]:hover,
fieldset[disabled] .btn-default:hover,
.btn-default.disabled:focus,
.btn-default[disabled]:focus,
fieldset[disabled] .btn-default:focus,
.btn-default.disabled.focus,
.btn-default[disabled].focus,
fieldset[disabled] .btn-default.focus,
.btn-default.disabled:active,
.btn-default[disabled]:active,
fieldset[disabled] .btn-default:active,
.btn-default.disabled.active,
.btn-default[disabled].active,
fieldset[disabled] .btn-default.active {
border-color: #fff;
background-color: #fff;
}
.btn-default .badge {
color: #fff;
background-color: #222;
}
.btn-primary {
border-color: #f05f40;
color: #fff;
background-color: #f05f40;
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary.focus,
.btn-primary:active,
.btn-primary.active,
.open > .dropdown-toggle.btn-primary {
border-color: #ed431f;
color: #fff;
background-color: #ee4b28;
}
.btn-primary:active,
.btn-primary.active,
.open > .dropdown-toggle.btn-primary {
background-image: none;
}
.btn-primary.disabled,
.btn-primary[disabled],
fieldset[disabled] .btn-primary,
.btn-primary.disabled:hover,
.btn-primary[disabled]:hover,
fieldset[disabled] .btn-primary:hover,
.btn-primary.disabled:focus,
.btn-primary[disabled]:focus,
fieldset[disabled] .btn-primary:focus,
.btn-primary.disabled.focus,
.btn-primary[disabled].focus,
fieldset[disabled] .btn-primary.focus,
.btn-primary.disabled:active,
.btn-primary[disabled]:active,
fieldset[disabled] .btn-primary:active,
.btn-primary.disabled.active,
.btn-primary[disabled].active,
fieldset[disabled] .btn-primary.active {
border-color: #f05f40;
background-color: #f05f40;
}
.btn-primary .badge {
color: #f05f40;
background-color: #fff;
}
.btn {
border: 0;
border-radius: 300px;
text-transform: uppercase;
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
font-weight: 700;
}
.btn-xl {
padding: 15px 30px;
}
::-moz-selection {
text-shadow: none;
color: #fff;
background: #222;
}
::selection {
text-shadow: none;
color: #fff;
background: #222;
}
img::selection {
color: #fff;
background: 0 0;
}
img::-moz-selection {
color: #fff;
background: 0 0;
}
body {
webkit-tap-highlight-color: #222;
}

+ 22
- 0
templates/accounts/login.html View File

@ -0,0 +1,22 @@
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h1>Log In</h1>
<p>
Please enter your email address.
Next, we'll send you an email with log-in instructions!
</p>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">
Submit
</button>
{% endbuttons %}
</form>
{% endblock %}

+ 5
- 0
templates/accounts/login_link_sent.html View File

@ -0,0 +1,5 @@
{% extends "base.html" %}
{% block content %}
<h1>Login link sent, check your inbox!</h1>
{% endblock %}

+ 15
- 0
templates/base.html View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Waka Waka</title>
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css">
</head>
<body>
<div class="container">
{% block content %}{% endblock %}
</div>
</body>
</html>

Loading…
Cancel
Save