contact form, newer styles and various other tweaks
60
Dockerfile
|
@ -1,34 +1,52 @@
|
|||
# fabricad
|
||||
#
|
||||
# VERSION 0.0.1
|
||||
FROM olymk2/uwsgi
|
||||
|
||||
FROM ubuntu:16.04
|
||||
MAINTAINER Oliver Marks "olymk2@gmail.com"
|
||||
ENV SERVER_ENVIRONMENT DEVELOPMENT
|
||||
ENV SITE_FOLDER /etc/sites/mysite/
|
||||
|
||||
ENV SERVER_ENVIRONMENT DOCKER
|
||||
#COPY website/config/nginx/maidstone-hackspace.org.uk.ini /etc/sites/nginx/maidstone-hackspace.org.uk.ini
|
||||
#COPY website/config/uwsgi/maidstone-hackspace.org.uk.ini /etc/sites/uwsgi/maidstone-hackspace.org.uk.ini
|
||||
|
||||
RUN apk add --update --no-cache libssl1.0 libxml2 libxslt ca-certificates
|
||||
RUN apk add --update --no-cache py-psycopg2 py-lxml py-flask py-pillow py-openssl py-cffi
|
||||
|
||||
RUN apk add --update --no-cache build-base make bzr python3-dev libffi-dev openssl-dev libxml2-dev libxslt-dev && \
|
||||
pip3 install lxml && \
|
||||
pip3 install --no-cache-dir lxml dateutils requests requests-oauthlib mailer gocardless paypalrestsdk pytz nose2 oauthlib flask flask-login pymysql misaka && \
|
||||
pip3 install --no-cache-dir bzr+lp:scaffold/trunk#egg=scaffold && \
|
||||
apk del build-base make bzr python3-dev libffi-dev openssl-dev libxml2-dev libxslt-dev
|
||||
|
||||
# RUN pip3 install --no-cache-dir dateutils requests requests-oauthlib gocardless paypalrestsdk pytz nose2 oauthlib flask flask-login pymysql misaka
|
||||
# RUN pip3 install --no-cache-dir bzr+lp:scaffold/trunk#egg=scaffold
|
||||
|
||||
#CMD ["setup.sh"]
|
||||
#ENTRYPOINT ["setup.sh"]
|
||||
|
||||
# make sure the package repository is up to date
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get upgrade -y && \
|
||||
apt-get install -y libssl-dev libffi-dev nano && \
|
||||
apt-get install -y software-properties-common python-software-properties && \
|
||||
apt-get install -y software-properties-common python-pip python-dev python-nose2 && \
|
||||
apt-get install -y python-mysqldb python-psycopg2 python-requests-oauthlib python-dateutil python-requests python-lxml python-flask python-flask-login python-pillow && \
|
||||
apt-get install -y cssmin slimit && \
|
||||
add-apt-repository -y ppa:oly/ppa && \
|
||||
apt-get update && \
|
||||
apt-get install -y python-scaffold
|
||||
#RUN \
|
||||
# apt-get update && \
|
||||
# apt-get upgrade -y && \
|
||||
# apt-get install -y libssl-dev libffi-dev nano && \
|
||||
# apt-get install -y software-properties-common python-software-properties && \
|
||||
# apt-get install -y software-properties-common python-pip python-dev python-nose2 && \
|
||||
# apt-get install -y python-mysqldb python-psycopg2 python-requests-oauthlib python-dateutil python-requests python-lxml python-flask python-flask-login python-pillow && \
|
||||
# apt-get install -y cssmin slimit && \
|
||||
# add-apt-repository -y ppa:oly/ppa && \
|
||||
# apt-get update && \
|
||||
# apt-get install -y python-scaffold
|
||||
|
||||
|
||||
RUN pip install gocardless paypalrestsdk pytz
|
||||
|
||||
#allow access to flask
|
||||
EXPOSE 5000 5002
|
||||
WORKDIR /var/www/website/
|
||||
#EXPOSE 5000 5002
|
||||
#WORKDIR /var/www/website/
|
||||
|
||||
|
||||
#RUN /bin/sh -c 'cd /var/www/site; python index.py'
|
||||
ENTRYPOINT /bin/sh -c 'python index.py'
|
||||
#ENTRYPOINT /bin/sh -c 'scaffold import && python index.py'
|
||||
|
||||
#docker build -t mhackspace .
|
||||
#docker run -d --name=mhackspace_container --restart=always mhackspace
|
||||
#docker run -it -v /etc/uwsgi/apps-enabled/:/etc/uwsgi/apps-enabled/ -v sockets:/data/sockets --entrypoint sh --name mhackspace olymk2/mhackspace
|
||||
#docker run -it -v /etc/uwsgi/apps-enabled/:/etc/uwsgi/apps-enabled/ -v sockets:/data/sockets -v /var/www/test.maidstone-hackspace.org.uk/site:/var/www --name mhackspace olymk2/mhackspace
|
||||
#accesss on dockerip 172.17.0.?:5000
|
||||
#https://hub.docker.com/r/olymk2/mhackspace/
|
||||
|
|
|
@ -14,6 +14,9 @@ The simplest way to setup this site is to use docker-compose so please install t
|
|||
and make sure the quick start guide works https://docs.docker.com/machine/get-started/ then you can use the commands below to test and make changes.
|
||||
|
||||
docker-compose up
|
||||
|
||||
docker volume create --name sockets
|
||||
docker run -it -v /etc/uwsgi/apps-enabled/:/etc/uwsgi/apps-enabled/ -v /var/www:/var/www -v sockets:/data/sockets --name mhackspace olymk2/mhackspace
|
||||
|
||||
If you plan on making large changes consider discussing it first so you dont waste your own time.
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
PATH=/usr/local/sbin:/usr/local/bin
|
||||
MAILTO=contact@maidstone-hackspace.org.uk
|
||||
0 2 * * * python /var/www/maidstone-hackspace.org.uk/site/generate.py
|
|
@ -0,0 +1,2 @@
|
|||
./letsencrypt-auto certonly -d maidstone-hackspace.org.uk -d live.maidstone-hackspace.org.uk
|
||||
./letsencrypt-auto certonly -d test.maidstone-hackspace.org.uk
|
|
@ -0,0 +1,28 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name maidstone-hackspace.org.uk live.maidstone-hackspace.org.uk www.maidstone-hackspace.org.uk;
|
||||
root /var/www/static/html;
|
||||
|
||||
error_page 404 = /404.htm;
|
||||
|
||||
location = / {
|
||||
# match uri equalling / only for index, if anything is after / go to next location
|
||||
try_files $uri $uri/index.htm;
|
||||
}
|
||||
|
||||
location / {
|
||||
# if the first root location fails try this one instead and fallback to uwsgi
|
||||
try_files $uri $uri.htm $uri/ @uwsgi_fallback;
|
||||
#error_page 404 = @fallback;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
alias /var/www/static/;
|
||||
log_not_found on;
|
||||
}
|
||||
|
||||
location @uwsgi_fallback {
|
||||
include uwsgi_params;
|
||||
uwsgi_pass unix:///data/sockets/maidstone_hackspace.sock;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name maidstone-hackspace.org.uk live.maidstone-hackspace.org.uk www.maidstone-hackspace.org.uk;
|
||||
root /var/www/live-maidstone-hackspace.org.uk/site/html;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/live.maidstone-hackspace.org.uk/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/live.maidstone-hackspace.org.uk/privkey.pem;
|
||||
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_protocols TLSv1.2;
|
||||
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_session_tickets on;
|
||||
ssl_dhparam /etc/ssl/certs/dhparam.pem;
|
||||
|
||||
resolver 8.8.8.8;
|
||||
|
||||
server_tokens off;
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header Strict-Transport-Security max-age=15768000;
|
||||
|
||||
error_page 404 = /404.htm;
|
||||
|
||||
location = / {
|
||||
# match uri equalling / only for index, if anything is after / go to next location
|
||||
try_files $uri $uri/index.htm;
|
||||
}
|
||||
|
||||
|
||||
location / {
|
||||
try_files $uri $uri.htm $uri/ @uwsgi_fallback;
|
||||
#error_page 404 = @fallback;
|
||||
}
|
||||
|
||||
location /static {
|
||||
alias /var/www/live-maidstone-hackspace.org.uk/site/static;
|
||||
#expires 1d;
|
||||
#add_header Pragma public;
|
||||
#add_header Cache-Control "public";
|
||||
}
|
||||
|
||||
location @uwsgi_fallback {
|
||||
include uwsgi_params;
|
||||
uwsgi_pass unix:///data/sockets/live-maidstone_hackspace.sock;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name test.maidstone-hackspace.org.uk;
|
||||
root /var/www/test-maidstone-hackspace.org.uk/site/html;
|
||||
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/test.maidstone-hackspace.org.uk/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/test.maidstone-hackspace.org.uk/privkey.pem;
|
||||
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_protocols TLSv1.2;
|
||||
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_session_tickets off;
|
||||
ssl_dhparam /etc/ssl/certs/dhparam.pem;
|
||||
|
||||
resolver 8.8.8.8;
|
||||
|
||||
server_tokens off;
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header Strict-Transport-Security max-age=15768000;
|
||||
|
||||
error_page 404 = /404.htm;
|
||||
|
||||
location = / {
|
||||
# match uri equalling / only for index, if anything is after / go to next location
|
||||
try_files $uri $uri/index.htm;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri.htm $uri/ @uwsgi_fallback;
|
||||
#error_page 404 = @fallback;
|
||||
}
|
||||
|
||||
location /static {
|
||||
alias /var/www/test-maidstone-hackspace.org.uk/site/static;
|
||||
expires 1d;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
|
||||
|
||||
location @uwsgi_fallback {
|
||||
include uwsgi_params;
|
||||
uwsgi_pass unix:///data/sockets/test-maidstone_hackspace.sock;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
[uwsgi]
|
||||
module = wsgi
|
||||
chdir = /var/www/
|
||||
base = /var/www/
|
||||
touch-reload = /etc/uwsgi/apps-enabled/maidstone-hackspace.org.uk.ini
|
||||
master = true
|
||||
processes = 3
|
||||
logto = /tmp/maidstone_hackspace.log
|
||||
plugin = python3
|
||||
socket = /data/sockets/maidstone_hackspace.sock
|
||||
chmod-socket = 660
|
||||
vacuum = true
|
||||
die-on-term = true
|
||||
|
||||
# only for development
|
||||
python-autoreload = 3
|
|
@ -1,25 +1,50 @@
|
|||
version: '2'
|
||||
|
||||
nginx:
|
||||
image: olymk2/mhackspace
|
||||
#name: mhackspace
|
||||
links:
|
||||
- db:database
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
- 8.8.4.4
|
||||
ports:
|
||||
- "5000:5000"
|
||||
volumes:
|
||||
- .:/var/www
|
||||
restart: always
|
||||
services:
|
||||
mhackspace_uwsgi:
|
||||
image: olymk2/mhackspace
|
||||
restart: unless-stopped
|
||||
network_mode: bridge
|
||||
links:
|
||||
- mariadb:mariadb
|
||||
- mhackspace_web:nginx
|
||||
- mhackspace_mail:mail_server
|
||||
volumes:
|
||||
- sockets:/data/sockets
|
||||
- ./website/:/var/www
|
||||
- ./config/uwsgi/maidstone-hackspace.org.uk.ini:/etc/uwsgi/apps-enabled/maidstone-hackspace.org.uk.ini
|
||||
|
||||
db:
|
||||
image: mariadb
|
||||
ports:
|
||||
- "3300:3306"
|
||||
environment:
|
||||
MYSQL_DATABASE: maidstone_hackspace
|
||||
MYSQL_USER: mhackspace
|
||||
MYSQL_PASSWORD: mhackspace
|
||||
MYSQL_ROOT_PASSWORD: mhackspace
|
||||
restart: always
|
||||
mhackspace_web:
|
||||
image: olymk2/nginx
|
||||
restart: unless-stopped
|
||||
network_mode: bridge
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
- 8.8.4.4
|
||||
volumes:
|
||||
- ./website/:/var/www
|
||||
- sockets:/data/sockets
|
||||
- /etc/ssl/certs/:/etc/ssl/certs/
|
||||
- ./config/nginx/docker-maidstone-hackspace.org.uk:/etc/nginx/sites-enabled/docker-maidstone-hackspace.org.uk
|
||||
restart: always
|
||||
|
||||
mariadb:
|
||||
image: mariadb
|
||||
network_mode: bridge
|
||||
ports:
|
||||
- "3300:3306"
|
||||
environment:
|
||||
MYSQL_DATABASE: maidstone_hackspace
|
||||
MYSQL_USER: mhackspace
|
||||
MYSQL_PASSWORD: mhackspace
|
||||
MYSQL_ROOT_PASSWORD: mhackspace
|
||||
restart: unless-stopped
|
||||
|
||||
mhackspace_mail:
|
||||
image: mailhog/mailhog
|
||||
network_mode: bridge
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
sockets:
|
||||
driver: local
|
||||
|
|
|
@ -1,409 +0,0 @@
|
|||
import os
|
||||
import uuid
|
||||
import hashlib
|
||||
import datetime
|
||||
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
from flask import session, flash
|
||||
from flask import redirect, abort
|
||||
from flask import make_response
|
||||
from flask import request
|
||||
from flask import Blueprint
|
||||
from flask.ext.login import current_user, LoginManager, login_required, UserMixin, login_user, logout_user, make_secure_token
|
||||
from requests_oauthlib import OAuth2Session
|
||||
from requests_oauthlib.compliance_fixes import facebook_compliance_fix
|
||||
|
||||
from scaffold import web
|
||||
from libs.mail import sendmail
|
||||
from pages import header, footer
|
||||
from data import site_user
|
||||
from config.settings import *
|
||||
from constants import *
|
||||
|
||||
web.load_widgets('widgets')
|
||||
|
||||
authorize_pages = Blueprint('authorize_pages', __name__, template_folder='templates')
|
||||
|
||||
login_manager = LoginManager()
|
||||
login_manager.login_view = '/login'
|
||||
|
||||
oauth_lookup = {'google':1, 'github':2, 'facebook':3}
|
||||
|
||||
|
||||
def is_weak_password(password1, password2):
|
||||
if password1 != password2:
|
||||
password1 = password2 = None
|
||||
return True
|
||||
|
||||
# TODO check length and chars
|
||||
|
||||
password1 = password2 = None
|
||||
return False
|
||||
|
||||
|
||||
def todict(data):
|
||||
new_dict = {}
|
||||
for key, value in data.items():
|
||||
new_dict[key] = value
|
||||
return new_dict
|
||||
|
||||
|
||||
class User(UserMixin):
|
||||
def __init__(self, user_id, active=True):
|
||||
print user_id
|
||||
self.id = None
|
||||
user_details = site_user.get_user_details({'id': user_id}).get()
|
||||
self.active = False
|
||||
print 'user'
|
||||
print user_details
|
||||
if user_details:
|
||||
#~ self.check_password(user_details.get('password'))
|
||||
self.id = user_id
|
||||
self.name = user_details.get('username')
|
||||
print self.name
|
||||
self.active = active
|
||||
|
||||
def get_id(self):
|
||||
return self.id
|
||||
|
||||
def is_active(self):
|
||||
return self.active
|
||||
|
||||
def is_authenticated(self):
|
||||
return self.active
|
||||
|
||||
def get_auth_token(self):
|
||||
return make_secure_token(self.name, key='deterministic')
|
||||
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(userid):
|
||||
"""Flask user loader hook, internal to flask login"""
|
||||
return User(userid)
|
||||
|
||||
|
||||
@login_manager.token_loader
|
||||
def load_token(request):
|
||||
token = request.headers.get('Authorization')
|
||||
if token is None:
|
||||
token = request.args.get('token')
|
||||
|
||||
if token is not None:
|
||||
username, password = token.split(":") # naive token
|
||||
print username
|
||||
print password
|
||||
user_entry = User.get(username)
|
||||
if (user_entry is not None):
|
||||
user = User(user_entry[0], user_entry[1])
|
||||
|
||||
if (user.password == password):
|
||||
return user
|
||||
return None
|
||||
|
||||
#~ def auth_required():
|
||||
#~ if not session.get('user_id'):
|
||||
#~ redirect(domain + '/login', 301)
|
||||
|
||||
@authorize_pages.route("/register", methods=['GET'])
|
||||
def register_form():
|
||||
header('Register for access')
|
||||
web.page.create('Register for access')
|
||||
#~ web.page.section(web.register_form.create().render())
|
||||
|
||||
web.form.create('Register new user account', '/register')
|
||||
web.form.append(name='name', label='Your full name', placeholder='Ralf Green', value='')
|
||||
web.form.append(name='email', label='Valid Email', placeholder='ralf@maidstone-hackspace.org.uk', value='')
|
||||
web.form.append(input_type='password', name='password', label='Password', placeholder='quick brown fox jumped over', value='')
|
||||
web.form.append(input_type='password', name='password_confirm', label='Password Confirm', placeholder='quick brown fox jumped over', value='')
|
||||
|
||||
web.page.section(web.form.render())
|
||||
web.template.body.append(web.page.render())
|
||||
|
||||
return make_response(footer())
|
||||
|
||||
@authorize_pages.route("/register", methods=['POST'])
|
||||
def register_submit():
|
||||
data = {}
|
||||
data['email'] = request.form.get('email')
|
||||
data['username'] = request.form.get('email')
|
||||
data['first_name'] = request.form.get('name').strip().split()[0]
|
||||
data['last_name'] = request.form.get('name').strip().split()[-1]
|
||||
|
||||
data['password'] = request.form.get('password')
|
||||
data['password_confirm'] = request.form.get('password')
|
||||
|
||||
data['password'] = generate_password_hash(request.form.get('password'))
|
||||
#TODO password strength tests
|
||||
if is_weak_password(request.form.get('password'), request.form.get('password_confirm')):
|
||||
redirect('/register')
|
||||
|
||||
header('Your account has been registered')
|
||||
web.page.create('Your account has been registered')
|
||||
|
||||
new_user = site_user.create()
|
||||
new_user.execute(data)
|
||||
flash('Your account has now been created')
|
||||
|
||||
web.template.body.append(web.page.render())
|
||||
return make_response(footer())
|
||||
|
||||
@authorize_pages.route("/oauth/<provider>/<start_oauth_login>/", methods=['GET'])
|
||||
@authorize_pages.route("/oauth/<provider>/<start_oauth_login>", methods=['GET'])
|
||||
@authorize_pages.route("/oauth/<provider>/", methods=['GET'])
|
||||
@authorize_pages.route("/oauth/<provider>", methods=['GET'])
|
||||
def oauth(provider, start_oauth_login=False):
|
||||
oauth_verify = True
|
||||
oauth_provider = oauth_conf.get(provider)
|
||||
oauth_access_type = ''
|
||||
oauth_approval_prompt = ''
|
||||
if oauth_live is False:
|
||||
oauth_verify = False
|
||||
oauth_access_type = 'offline'
|
||||
oauth_approval_prompt = "force"
|
||||
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
|
||||
|
||||
if start_oauth_login:
|
||||
print oauth_provider.get('redirect_uri')
|
||||
oauth_session = OAuth2Session(
|
||||
oauth_provider.get('client_id'),
|
||||
scope=oauth_provider.get('scope'),
|
||||
redirect_uri=oauth_provider.get('redirect_uri'))
|
||||
|
||||
if provider == 'facebook':
|
||||
oauth_session = facebook_compliance_fix(oauth_session)
|
||||
|
||||
authorization_url, state = oauth_session.authorization_url(
|
||||
oauth_provider.get('auth_uri'),
|
||||
access_type=oauth_access_type,
|
||||
approval_prompt=oauth_approval_prompt)
|
||||
|
||||
# State is used to prevent CSRF, keep this for later, make sure oauth returns to the same url.
|
||||
# if testing and oauth_state errors make sure you logged in with localhost and not 127.0.0.1
|
||||
session['oauth_state'] = state
|
||||
session.modified = True
|
||||
return redirect(authorization_url)
|
||||
|
||||
# allready authorised so lets handle the callback
|
||||
oauth_session = OAuth2Session(
|
||||
oauth_provider.get('client_id'),
|
||||
state=session['oauth_state'],
|
||||
redirect_uri=oauth_provider.get('redirect_uri'))
|
||||
|
||||
print '----------'
|
||||
print oauth_provider.get('redirect_uri')
|
||||
print request.url
|
||||
|
||||
if provider == 'facebook':
|
||||
oauth_session = facebook_compliance_fix(oauth_session)
|
||||
|
||||
|
||||
# code error is todo with authorisation response
|
||||
oauth_session.fetch_token(
|
||||
oauth_provider.get('token_uri'),
|
||||
client_secret=oauth_provider.get('client_secret'),
|
||||
authorization_response=request.url,
|
||||
verify=oauth_verify)
|
||||
|
||||
# Fetch a protected resource, i.e. user profile
|
||||
response = oauth_session.get(oauth_provider.get('user_uri'))
|
||||
oauth_response = response.json()
|
||||
|
||||
print 'oauth response'
|
||||
print oauth_response
|
||||
|
||||
oauth_id = oauth_response.get('login') or oauth_response.get('id')
|
||||
provider_id = oauth_lookup.get(provider)
|
||||
oauth_user = site_user.fetch_oauth_login({
|
||||
'username': oauth_id or '',
|
||||
'provider': provider_id
|
||||
}).get()
|
||||
|
||||
if oauth_user:
|
||||
user_details = site_user.get_user_details({
|
||||
'id': oauth_user.get('user_id')
|
||||
}).get()
|
||||
|
||||
# we have matched a user so login and redirect
|
||||
if user_details:
|
||||
login_user(User(user_details.get('user_id')))
|
||||
# no E-Mail so lets ask the user to set there email before allowing login
|
||||
if not user_details.get('email'):
|
||||
return redirect('/profile/change_email')
|
||||
return redirect('/profile')
|
||||
|
||||
flash('Your new profile has been created, and your now logged in')
|
||||
|
||||
print 'current user'
|
||||
print current_user.get_id()
|
||||
if current_user.get_id():
|
||||
# link oauth to users account
|
||||
site_user.create_oauth_login().execute({
|
||||
'user_id': current_user.get_id(),
|
||||
'username': oauth_id or '',
|
||||
'provider': provider_id})
|
||||
return redirect('/profile')
|
||||
|
||||
print oauth_response
|
||||
print '-----'
|
||||
print oauth_response.get('email') or ''
|
||||
# create new user from oauth information
|
||||
|
||||
new_user_details = {
|
||||
'password': 'oauth',
|
||||
'profile_image': oauth_response.get('picture'),
|
||||
'username': oauth_id,
|
||||
'first_name': oauth_response.get('given_name') or '',
|
||||
'last_name': oauth_response.get('family_name') or ''}
|
||||
|
||||
if oauth_response.get('email'):
|
||||
new_user_details['email']= oauth_response.get('email')
|
||||
|
||||
user_id = site_user.create().execute(new_user_details)
|
||||
|
||||
# register oauth login creation
|
||||
site_user.create_oauth_login().execute({
|
||||
'user_id': user_id,
|
||||
'username': oauth_id or '',
|
||||
'provider': provider_id})
|
||||
|
||||
login_user(User(user_id))
|
||||
site_user.update_last_login().execute({'id': user_id})
|
||||
if not user_id:
|
||||
flash('Failed to create user')
|
||||
return redirect('/login')
|
||||
return redirect('/profile')
|
||||
|
||||
|
||||
@authorize_pages.route("/change-password/<code>", methods=['GET'])
|
||||
@authorize_pages.route("/change-password", methods=['GET'])
|
||||
def change_password(code=None):
|
||||
#if we have a code this is a password reset, so try and login the user first
|
||||
print code
|
||||
site_user.delete_password_reset().execute({})
|
||||
if code:
|
||||
|
||||
user_details = site_user.get_user_by_reset_code({'reset_code': code}).get()
|
||||
|
||||
print user_details
|
||||
if not user_details:
|
||||
#invalid code so pretend the page does not even exist
|
||||
return abort(404)
|
||||
#check the code has not expired
|
||||
#datetime.datetime.now() + datetime.timedelta(minutes=15)
|
||||
has_date_expired = user_details.get('created') + datetime.timedelta(minutes=60)
|
||||
if has_date_expired < datetime.datetime.now():
|
||||
print 'date expired'
|
||||
#date expired so clean up and pretend the page does not exist
|
||||
return abort(404)
|
||||
#challenge passed so login the user so they can change there password
|
||||
login_user(
|
||||
User(user_details.get('user_id'))
|
||||
)
|
||||
session['user_id'] = str(user_details.get('user_id'))
|
||||
|
||||
web.template.create('Maidstone Hackspace - Profile')
|
||||
header('User profile')
|
||||
web.page.create('Change password')
|
||||
web.page.section(
|
||||
web.change_password_box.create().render()
|
||||
)
|
||||
web.template.body.append(web.page.render())
|
||||
return make_response(footer())
|
||||
|
||||
@login_required
|
||||
@authorize_pages.route("/change-password", methods=['POST'])
|
||||
def change_password_submit(code=None):
|
||||
if not session.get('user_id'):
|
||||
abort(404)
|
||||
user_details = site_user.authorize({
|
||||
'id': session.get('user_id')}).get()
|
||||
|
||||
if is_weak_password(request.form.get('password'), request.form.get('password_confirm')):
|
||||
print 'password not strong enough'
|
||||
redirect('/login')
|
||||
|
||||
pw_hash = generate_password_hash(request.form.get('password'))
|
||||
|
||||
site_user.change_password().execute({'id': user_details.get('user_id'), 'password': pw_hash})
|
||||
|
||||
web.template.create('Maidstone Hackspace - Profile')
|
||||
header('User Profile')
|
||||
web.page.create('Password change complete')
|
||||
web.page.section(
|
||||
'Your password has successfull been changed'
|
||||
)
|
||||
web.template.body.append(web.page.render())
|
||||
return make_response(footer())
|
||||
|
||||
|
||||
@authorize_pages.route("/reset-password", methods=['GET'])
|
||||
def reset_password():
|
||||
web.template.create('Maidstone Hackspace - Login')
|
||||
header('Members Login')
|
||||
web.page.create('Forgot password reset')
|
||||
web.page.section(
|
||||
web.password_box.create('Please enter your E-Mail account', reset=True).render()
|
||||
)
|
||||
web.template.body.append(web.page.render())
|
||||
return make_response(footer())
|
||||
|
||||
@authorize_pages.route("/reset-password", methods=['POST'])
|
||||
def reset_password_submit():
|
||||
user_details = site_user.get_by_username({
|
||||
'email': request.form.get('email')}).get()
|
||||
|
||||
reset_code = hashlib.sha256(str(uuid.uuid4())).hexdigest()
|
||||
|
||||
if user_details:
|
||||
site_user.create_password_reset() \
|
||||
.on_duplicate() \
|
||||
.execute({
|
||||
'user_id': str(user_details.get('user_id')),
|
||||
'reset_code': reset_code})
|
||||
|
||||
l=web.link.create(title='Change password', content='Click to change password',link="{domain}change-password/{resetcode}".format(**{'domain':app_domain, 'resetcode': reset_code})).render()
|
||||
|
||||
body = "Please follow the link below to change your password.\n" + l
|
||||
body += "{domain}change-password/{resetcode}".format(**{'domain':app_domain, 'resetcode': reset_code})
|
||||
sendmail().send(
|
||||
from_address='no-reply@maidstone-hackspace.org.uk',
|
||||
to_address='oly@leela',
|
||||
subject="Reset password request",
|
||||
body=body)
|
||||
|
||||
# display success page, dont give away anything about if the email is actually registered
|
||||
web.template.create('Maidstone Hackspace - Password reset')
|
||||
header('Password reset')
|
||||
web.page.create('Password reset sent')
|
||||
web.page.section(
|
||||
web.paragraph.create('If this E-Mail is registered you will shortly be reciving an E-Mail with reset details').render()
|
||||
)
|
||||
web.template.body.append(web.page.render())
|
||||
return make_response(footer())
|
||||
|
||||
#~ @authorize_pages.route("/login", methods=['GET'])
|
||||
#~ def login_screen():
|
||||
#~ web.template.create('Maidstone Hackspace - Login')
|
||||
#~ header('Members Login')
|
||||
#~ web.page.create('Member Login')
|
||||
#~ web.page.section(
|
||||
#~ web.login_box.create().enable_oauth('google').enable_oauth('facebook').enable_oauth('github').render()
|
||||
#~ )
|
||||
#~ web.template.body.append(web.page.render())
|
||||
#~ return make_response(footer())
|
||||
|
||||
|
||||
@authorize_pages.route("/login/failure", methods=['GET'])
|
||||
def login_Failure():
|
||||
web.template.create('%s - Login' % site_name)
|
||||
header('Login Failure')
|
||||
web.page.create('Login Failure')
|
||||
#~ web.template.body.append(web.messages.render())
|
||||
web.template.body.append(web.page.render())
|
||||
return make_response(footer())
|
||||
|
||||
|
||||
@authorize_pages.route("/logout")
|
||||
def logout():
|
||||
logout_user()
|
||||
return redirect('/')
|
|
@ -0,0 +1,10 @@
|
|||
import os
|
||||
import logging
|
||||
|
||||
log = logging.getLogger('Maidstone Hackspace')
|
||||
log.setLevel(logging.DEBUG)
|
||||
#~ log.propagate = False
|
||||
if os.path.exists('/tmp/maidstone_hackspace.log'):
|
||||
ch = logging.FileHandler('/tmp/maidstone_hackspace.log')
|
||||
ch.setLevel(logging.DEBUG)
|
||||
log.addHandler(ch)
|
|
@ -1,6 +1,10 @@
|
|||
import os
|
||||
import constants
|
||||
import socket
|
||||
from scaffold.core.data.database import db
|
||||
from scaffold import web
|
||||
from libs import mail
|
||||
|
||||
|
||||
schema = 'https:'
|
||||
domain = '127.0.0.1'
|
||||
|
@ -35,27 +39,27 @@ google_calendar_api_key = ''
|
|||
|
||||
if os.environ.get('SERVER_ENVIRONMENT') =='DOCKER':
|
||||
if os.path.exists('config/settings_docker.py'):
|
||||
print 'Using settings for docker enviroment'
|
||||
from settings_docker import *
|
||||
print('Using settings for docker enviroment')
|
||||
from config.settings_docker import *
|
||||
else:
|
||||
if os.path.exists('config/settings_dev.py'):
|
||||
print 'Using settings for dev enviroment'
|
||||
from settings_dev import *
|
||||
print('Using settings for dev enviroment')
|
||||
from config.settings_dev import *
|
||||
|
||||
if os.path.exists('config/settings_testing.py'):
|
||||
print('Using settings for test enviroment')
|
||||
from settings_testing import *
|
||||
from config.settings_testing import *
|
||||
|
||||
if os.path.exists('config/settings_live.py'):
|
||||
print('Using settings for live enviroment')
|
||||
from settings_live import *
|
||||
from config.settings_live import *
|
||||
|
||||
|
||||
|
||||
with web.template as setup:
|
||||
#css for jquery, material sprite sheet and custom css
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />')
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/materialize.css" media="" type="text/css" />')
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />')
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />')
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-navigation-white.css" media="" type="text/css" />')
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-action-white.css" media="" type="text/css" />')
|
||||
|
@ -65,6 +69,7 @@ with web.template as setup:
|
|||
setup.persistent_header('<script type="text/javascript" src="/static/js/jquery-2.2.3.min.js"></script>')
|
||||
setup.persistent_header('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>')
|
||||
setup.persistent_header('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js"></script>')
|
||||
setup.persistent_header('<script type="text/javascript" src="/static/js/materialize.js"></script>')
|
||||
setup.persistent_header('<script type="text/javascript" src="/static/js/default.js"></script>')
|
||||
|
||||
#other favicon etc
|
||||
|
@ -75,5 +80,5 @@ with web.template as setup:
|
|||
domain=domain,
|
||||
port=port)
|
||||
|
||||
|
||||
db.config(database)
|
||||
mail.sendmail.set_server(email_server)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import os
|
||||
import socket
|
||||
|
||||
database = {
|
||||
'charset': 'utf8',
|
||||
|
@ -43,8 +45,28 @@ payment_providers = {
|
|||
google_calendar_id = 'contact@maidstone-hackspace.org.uk'
|
||||
google_calendar_api_key = 'AIzaSyA98JvRDmplA9lVLZeKwrs1f2k17resLy0'
|
||||
|
||||
app_domain = 'http://localhost:5000'
|
||||
|
||||
google_captcha = {
|
||||
'secret': '',
|
||||
'site': ''
|
||||
}
|
||||
|
||||
# TODO in scaffold remove when commited
|
||||
def get_ip_from_hostname(hostname, schema='http'):
|
||||
try:
|
||||
'%s://%s' % (schema, socket.gethostbyname('nginx'))
|
||||
except socket.gaierror:
|
||||
return '%s://%s' % (schema, '127.0.0.1')
|
||||
|
||||
app_domain = 'http://%s' % socket.gethostbyname('nginx')
|
||||
app_email_template_path = 'templates/email/'
|
||||
schema = 'https:'
|
||||
domain = get_ip_from_hostname('nginx')
|
||||
port = ''
|
||||
rel_uri = '//' + domain
|
||||
app_domain = 'http:%s' % rel_uri
|
||||
app_email_template_path = 'templates/email/'
|
||||
site_name = 'Maidstone Hackspace'
|
||||
|
||||
flask_secret_key = '4466ae96-849f-4fbe-a469-3295bf1a13f5'
|
||||
|
||||
|
@ -81,3 +103,11 @@ oauth_conf = {
|
|||
}
|
||||
}
|
||||
|
||||
email_server = {
|
||||
'username': '',
|
||||
'password': '',
|
||||
'host': 'mail_server',
|
||||
'port': 1025,
|
||||
'use_tls': False,
|
||||
'from': 'support@maidstone-hackspace.org.uk',
|
||||
'to': 'support@maidstone-hackspace.org.uk'}
|
||||
|
|
|
@ -3,7 +3,7 @@ page_menu = [
|
|||
('Home', '/'),
|
||||
('Chat', '/chat'),
|
||||
('Donate', '/donate'),
|
||||
('Contact', '#mailing-list-signup')]
|
||||
('Contact', '/contact-us')]
|
||||
|
||||
nav_for_authenticated_user = (
|
||||
('Profile', '/profile'),
|
||||
|
@ -14,7 +14,8 @@ nav_for_authenticated_user = (
|
|||
)
|
||||
|
||||
banner_images = [
|
||||
('/static/images/banners/hackspace-banner.png', '', '', ''),
|
||||
('/static/images/banners/hackspace-banner.png', 'Maidstone Hackspace', 'Maidstone Hackspace', ''),
|
||||
('/static/images/banners/emf_2016_sign.jpg', 'EMF CAMP 2016', 'EMF CAMP 2016', ''),
|
||||
('/static/images/banners/audio_board.jpg', 'Audio board', 'Audio board', ''),
|
||||
('/static/images/banners/microscope.jpg', '', 'Microscope', ''),
|
||||
('/static/images/banners/object_avoiding_robot.jpg', '', 'Object avoiding robot', ''),
|
||||
|
@ -42,6 +43,9 @@ rss_feeds = [{
|
|||
}, {
|
||||
'author':'Mike McRoberts',
|
||||
'url': 'http://thearduinoguy.org/?feed=rss2'
|
||||
}, {
|
||||
'author': 'James',
|
||||
'url': 'https://feeds.feedburner.com/projects-jl'
|
||||
}]
|
||||
|
||||
kent_hackspace = [
|
||||
|
@ -58,14 +62,6 @@ maker_events = [
|
|||
|
||||
email = 'support@maidstone-hackspace.org.uk'
|
||||
|
||||
email_server = {
|
||||
'user': '',
|
||||
'password': '',
|
||||
'host': 'email-smtp.us-east-1.amazonaws.com',
|
||||
'port': 465,
|
||||
'from': 'support@maidstone-hackspace.org.uk',
|
||||
'to': 'support@maidstone-hackspace.org.uk'}
|
||||
|
||||
badge_lookup = {
|
||||
1: 'member',
|
||||
2: 'backer',
|
||||
|
|
|
@ -23,7 +23,6 @@ class assign_badge(insert_data):
|
|||
class fetch_badges(select_data):
|
||||
#~ debug = True
|
||||
table = 'badges'
|
||||
required = {}
|
||||
columns = {'id', 'name'}
|
||||
|
||||
class fetch_badge(select_data):
|
||||
|
|
|
@ -28,7 +28,6 @@ class get_requests(select_data):
|
|||
debug = True
|
||||
#~ limit_rows = False
|
||||
pagination_rows = 100
|
||||
required = {}
|
||||
#~ query_str = 'select id, user_id, name, description, url, price, count(user_id) as quantity from maidstone_hackspace.requests group by name'
|
||||
query_str = 'select id, user_id, name, description, url, price as quantity from maidstone_hackspace.requests order by name'
|
||||
columns = {}
|
||||
|
|
|
@ -9,7 +9,6 @@ query_builder.query_path = os.path.abspath('./data/sql/')
|
|||
|
||||
|
||||
class get_members(select_data):
|
||||
required = {}
|
||||
query_file = 'member_list.sql'
|
||||
columns = {}
|
||||
|
||||
|
|
|
@ -76,7 +76,6 @@ class delete_password_reset(delete_data):
|
|||
"""clean up expired password resets"""
|
||||
table = 'user_password_reset'
|
||||
sql_where = 'where DATE_ADD(created, INTERVAL 1 HOUR) < now()'
|
||||
required = {}
|
||||
|
||||
|
||||
class create_password_reset(insert_data):
|
||||
|
@ -89,14 +88,15 @@ class get_user_by_reset_code(select_data):
|
|||
columns_where = ['reset_code']
|
||||
|
||||
class change_password(update_data):
|
||||
debug=True
|
||||
table = 'users'
|
||||
required = {'id', 'password'}
|
||||
columns_where = ['password']
|
||||
columns = ['password']
|
||||
#~ columns_where = ['password']
|
||||
sql_where = 'id=%(id)s'
|
||||
|
||||
|
||||
class get_users(select_data):
|
||||
required = {}
|
||||
query_file = 'get_users.sql'
|
||||
|
||||
|
||||
|
@ -119,9 +119,9 @@ class get_by_email(select_data):
|
|||
|
||||
|
||||
class get_by_username(select_data):
|
||||
required = {'email'}
|
||||
required = {'username'}
|
||||
query_file = 'get_user_credentials.sql'
|
||||
columns_where = {'email'}
|
||||
columns_where = {'username'}
|
||||
|
||||
class authorize(select_data):
|
||||
required = {'id'}
|
||||
|
@ -138,6 +138,18 @@ class create_oauth_login(insert_data):
|
|||
def calculated_data(self):
|
||||
return {'registered': time.strftime('%Y-%m-%d %H:%M:%S')}
|
||||
|
||||
class get_registered_oauth_providers(select_data):
|
||||
table = 'user_oauth'
|
||||
columns = {'username', 'provider', 'last_login'}
|
||||
required = {'user_id'}
|
||||
query_file = 'get_user_by_oauth_username.sql'
|
||||
columns_where = {'user_id',}
|
||||
|
||||
def calculated_data(self):
|
||||
return {
|
||||
'last_login': time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
class update_oauth_login(update_data):
|
||||
table = 'user_oauth'
|
||||
columns = {'username', 'provider', 'last_login'}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import os
|
||||
import time
|
||||
from collections import defaultdict
|
||||
from scaffold.core.data.select import select_data
|
||||
from scaffold.core.data.insert import insert_data
|
||||
from scaffold.core.data.update import update_data
|
||||
from scaffold.core.data.delete import delete_data
|
||||
from scaffold.core.data.sql import query_builder
|
||||
|
||||
query_builder.query_path = os.path.abspath('./data/sql/')
|
||||
|
||||
|
||||
class create_badge(insert_data):
|
||||
table = 'badges'
|
||||
required = {'name'}
|
||||
columns = {'name'}
|
||||
|
||||
class assign_badge(insert_data):
|
||||
table = 'user_badges'
|
||||
required = {'user_id', 'badge_id'}
|
||||
columns = {'user_id', 'badge_id'}
|
||||
|
||||
class fetch_badges(select_data):
|
||||
#~ debug = True
|
||||
table = 'badges'
|
||||
columns = {'id', 'name'}
|
||||
|
||||
class fetch_badge(select_data):
|
||||
#~ debug = True
|
||||
table = 'user_badges'
|
||||
required = {'user_id'}
|
||||
columns = {'user_id', 'badge_id'}
|
||||
columns_where = {'user_id', 'badge_id'}
|
||||
columns_optional_where = {'user_id', 'badge_id'}
|
||||
columns_optional = {'user_id', 'badge_id'}
|
||||
|
||||
class fetch_user_badges(select_data):
|
||||
#~ debug = True
|
||||
table = 'user_badges'
|
||||
columns = {'user_id', 'badge_id'}
|
||||
#~ columns_where = {'user_id'}
|
||||
columns_optional_where = {'user_id', 'badge_id'}
|
||||
#~ columns_optional = {'user_id', 'badge_id'}
|
||||
|
||||
def fetch_user_badges_grouped():
|
||||
badge_lookup = defaultdict(list)
|
||||
for badge in fetch_user_badges():
|
||||
badge_lookup[badge.get('user_id')].append(badge.get('badge_id'))
|
||||
return badge_lookup
|
||||
|
||||
class remove_badge(delete_data):
|
||||
table = 'user_badges'
|
||||
required = {'id'}
|
||||
columns = {'id'}
|
|
@ -0,0 +1,37 @@
|
|||
import os
|
||||
|
||||
from scaffold.core.data.select import select_data
|
||||
from scaffold.core.data.insert import insert_data
|
||||
#~ from scaffold.core.data.update import update_data
|
||||
#~ from scaffold.core.data.delete import delete_data
|
||||
from scaffold.core.data.sql import query_builder
|
||||
|
||||
query_builder.query_path = os.path.abspath('./data/sql/')
|
||||
|
||||
class get_pledge(select_data):
|
||||
debug = True
|
||||
table = 'pledges'
|
||||
columns = {'id', 'name', 'total'}
|
||||
required = {'name'}
|
||||
|
||||
class get_pledges(select_data):
|
||||
debug = True
|
||||
#~ table = 'pledges'
|
||||
query_file = 'pledge_totals.sql'
|
||||
required = {'environment'}
|
||||
columns_where = {'expired', 'environment'}
|
||||
grouping = {'name'}
|
||||
|
||||
class add_pledge(insert_data):
|
||||
debug = True
|
||||
table = 'pledges'
|
||||
required = {'name'}
|
||||
columns = {'name'}
|
||||
|
||||
class add_payment(insert_data):
|
||||
debug = True
|
||||
table = 'pledge_amounts'
|
||||
required = {'provider_id', 'pledge_id', 'reference', 'amount', 'environment'}
|
||||
columns = {'provider_id', 'pledge_id', 'reference', 'amount', 'environment'}
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import os
|
||||
import sys
|
||||
sys.path.append(os.path.abspath('../../../../scaffold/'))
|
||||
sys.path.insert(0,os.path.abspath('../../../../scaffold/'))
|
||||
from scaffold.core.data.select import select_data
|
||||
from scaffold.core.data.insert import insert_data
|
||||
from scaffold.core.data.update import update_data
|
||||
#~ from scaffold.core.data.delete import delete_data
|
||||
from scaffold.core.data.sql import query_builder
|
||||
|
||||
query_builder.query_path = os.path.abspath('./data/sql/')
|
||||
|
||||
class create(insert_data):
|
||||
table = 'requests'
|
||||
required = {'user_id', 'name'}
|
||||
columns = {'user_id', 'name'}
|
||||
columns_optional = {'price', 'description', 'url'}
|
||||
|
||||
class update(update_data):
|
||||
#~ debug = True
|
||||
table = 'requests'
|
||||
required = {'id', 'user_id'}
|
||||
columns = {'user_id', 'name'}
|
||||
columns_where = {'id'}
|
||||
columns_optional = {'price', 'description', 'url'}
|
||||
|
||||
class get_requests(select_data):
|
||||
debug = True
|
||||
#~ limit_rows = False
|
||||
pagination_rows = 100
|
||||
#~ query_str = 'select id, user_id, name, description, url, price, count(user_id) as quantity from maidstone_hackspace.requests group by name'
|
||||
query_str = 'select id, user_id, name, description, url, price as quantity from maidstone_hackspace.requests order by name'
|
||||
columns = {}
|
||||
|
||||
|
||||
class get_request(select_data):
|
||||
table = 'requests'
|
||||
required = {'id'}
|
||||
columns = {'*'}
|
||||
#query_str = 'select id, user_id, name, description, url, price, count(user_id) as quantity from maidstone_hackspace.requests group by name'
|
||||
columns_where = {'id'}
|
||||
#columns = {}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import os
|
||||
from scaffold.core.data.select import select_data
|
||||
#~ from scaffold.core.data.insert import insert_data
|
||||
from scaffold.core.data.update import update_data
|
||||
#~ from scaffold.core.data.delete import delete_data
|
||||
from scaffold.core.data.sql import query_builder
|
||||
|
||||
query_builder.query_path = os.path.abspath('./data/sql/')
|
||||
|
||||
|
||||
class get_members(select_data):
|
||||
query_file = 'member_list.sql'
|
||||
columns = {}
|
||||
|
||||
class get_member_profile(select_data):
|
||||
required = {'id'}
|
||||
query_file = 'get_users.sql'
|
||||
columns_where = {'id'}
|
||||
|
||||
class fetch_member_badges(select_data):
|
||||
required = {'id'}
|
||||
query_file = 'fetch_user_badges.sql'
|
||||
columns_where = {'id'}
|
||||
|
||||
class update_membership_status(update_data):
|
||||
debug = True
|
||||
query_str = "update `users` set `status`=%(status)s where id=%(user_id)s"
|
||||
required = {'user_id', 'status'}
|
||||
columns_where = {}
|
||||
|
||||
class fetch_member_subscription(select_data):
|
||||
debug = True
|
||||
required = {'user_id'}
|
||||
query_str = 'select provider_id, subscription_reference from user_membership'
|
||||
columns_where = {'user_id'}
|
|
@ -0,0 +1,28 @@
|
|||
import os
|
||||
|
||||
from scaffold.core.data.select import select_data
|
||||
from scaffold.core.data.insert import insert_data
|
||||
from scaffold.core.data.update import update_data
|
||||
#~ from scaffold.core.data.delete import delete_data
|
||||
from scaffold.core.data.sql import query_builder
|
||||
|
||||
query_builder.query_path = os.path.abspath('./data/sql/')
|
||||
|
||||
class fetch_users(select_data):
|
||||
query_file = 'get_users.sql'
|
||||
|
||||
class update_description(update_data):
|
||||
#~ debug = True
|
||||
table = 'user_detail'
|
||||
required = {'user_id', 'description', 'skills'}
|
||||
columns = {'user_id', 'description', 'skills'}
|
||||
columns_optional = {'description', 'skills'}
|
||||
columns_where = {'user_id'}
|
||||
|
||||
class create_description(insert_data):
|
||||
#~ debug = True
|
||||
table = 'user_detail'
|
||||
required = {'user_id'}
|
||||
columns = {'user_id'}
|
||||
columns_optional = {'description', 'skills'}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
import os
|
||||
import time
|
||||
from scaffold.core.data.select import select_data
|
||||
from scaffold.core.data.insert import insert_data
|
||||
from scaffold.core.data.update import update_data
|
||||
from scaffold.core.data.delete import delete_data
|
||||
from scaffold.core.data.sql import query_builder
|
||||
|
||||
query_builder.query_path = os.path.abspath('./data/sql/')
|
||||
|
||||
|
||||
class create_basic_user(insert_data):
|
||||
"""not able to actually log in but registered on the system"""
|
||||
table = 'users'
|
||||
required = {'first_name', 'last_name'}
|
||||
columns = {'first_name', 'last_name'}
|
||||
|
||||
def calculated_data(self):
|
||||
return {'created': time.strftime('%Y-%m-%d %H:%M:%S')}
|
||||
|
||||
def set(self, data):
|
||||
data['created'] = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
super(create_basic_user, self).set(data)
|
||||
|
||||
class create(insert_data):
|
||||
table = 'users'
|
||||
required = {'password', 'username', 'first_name', 'last_name', 'created'}
|
||||
columns = {'password', 'username', 'first_name', 'last_name', 'created'}
|
||||
columns_optional = {'profile_image'}
|
||||
|
||||
def calculated_data(self):
|
||||
return {'created': time.strftime('%Y-%m-%d %H:%M:%S')}
|
||||
|
||||
def set(self, data):
|
||||
data['created'] = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
super(create, self).set(data)
|
||||
|
||||
class update_last_login(update_data):
|
||||
#~ debug = True
|
||||
query_str = "update `users` set `last_login`=now()"
|
||||
required = {'id'}
|
||||
columns_where = {'id'}
|
||||
|
||||
class update_user_email(update_data):
|
||||
#~ debug = True
|
||||
query_str = "update `users` set `email`=%(email)s"
|
||||
required = {'id', 'email'}
|
||||
columns_where = {'id'}
|
||||
|
||||
class update_membership_status(update_data):
|
||||
#~ debug = True
|
||||
query_str = "update `users` set `status`=%(status)s where id=%(user_id)s"
|
||||
required = {'user_id', 'status'}
|
||||
columns_where = {}
|
||||
|
||||
class create_membership(insert_data):
|
||||
#~ debug = True
|
||||
table = 'user_membership'
|
||||
required = {'user_id', 'subscription_reference', 'status', 'amount', 'join_date'}
|
||||
columns = {'user_id', 'subscription_reference', 'status', 'amount', 'join_date'}
|
||||
columns_where = {}
|
||||
|
||||
class update_membership(update_data):
|
||||
#~ debug = True
|
||||
query_str = u"""
|
||||
update user_membership set
|
||||
status=%(status)s,
|
||||
subscription_reference=%(subscription_reference)s,
|
||||
amount=%(amount)s,
|
||||
join_date=%(join_date)s
|
||||
where id=%(user_id)s"""
|
||||
required = {'subscription_reference', 'status', 'amount', 'join_date'}
|
||||
columns_where = {}
|
||||
|
||||
class delete_password_reset(delete_data):
|
||||
"""clean up expired password resets"""
|
||||
table = 'user_password_reset'
|
||||
sql_where = 'where DATE_ADD(created, INTERVAL 1 HOUR) < now()'
|
||||
|
||||
|
||||
class create_password_reset(insert_data):
|
||||
table = 'user_password_reset'
|
||||
required = {'user_id', 'reset_code'}
|
||||
|
||||
class get_user_by_reset_code(select_data):
|
||||
required = {'reset_code'}
|
||||
query_file = 'get_user_password_reset.sql'
|
||||
columns_where = ['reset_code']
|
||||
|
||||
class change_password(update_data):
|
||||
table = 'users'
|
||||
required = {'id', 'password'}
|
||||
columns_where = ['password']
|
||||
sql_where = 'id=%(id)s'
|
||||
|
||||
|
||||
class get_users(select_data):
|
||||
query_file = 'get_users.sql'
|
||||
|
||||
|
||||
class get_user_bio(select_data):
|
||||
#~ debug = True
|
||||
required = {'id'}
|
||||
query_file = 'get_user_bio.sql'
|
||||
columns_where = {'user_id'}
|
||||
|
||||
class get_user_details(select_data):
|
||||
#~ debug = True
|
||||
required = {'id'}
|
||||
query_file = 'get_user_detail.sql'
|
||||
columns_where = {'users.id'}
|
||||
|
||||
class get_by_email(select_data):
|
||||
required = {'email'}
|
||||
query_file = 'get_users.sql'
|
||||
columns_where = {'email'}
|
||||
|
||||
|
||||
class get_by_username(select_data):
|
||||
required = {'email'}
|
||||
query_file = 'get_user_credentials.sql'
|
||||
columns_where = {'email'}
|
||||
|
||||
class authorize(select_data):
|
||||
required = {'id'}
|
||||
query_file = 'get_user_credentials.sql'
|
||||
columns_where = {'id'}
|
||||
|
||||
|
||||
class create_oauth_login(insert_data):
|
||||
#~ debug = True
|
||||
table = 'user_oauth'
|
||||
required = {'username', 'provider', 'user_id'}
|
||||
columns = {'username', 'provider', 'user_id', 'registered'}
|
||||
|
||||
def calculated_data(self):
|
||||
return {'registered': time.strftime('%Y-%m-%d %H:%M:%S')}
|
||||
|
||||
class update_oauth_login(update_data):
|
||||
table = 'user_oauth'
|
||||
columns = {'username', 'provider', 'last_login'}
|
||||
required = {'username', 'provider'}
|
||||
query_file = 'get_user_by_oauth_username.sql'
|
||||
columns_where = {'username', 'provider'}
|
||||
|
||||
def calculated_data(self):
|
||||
return {
|
||||
'last_login': time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
class fetch_oauth_login(select_data):
|
||||
required = {'username', 'provider'}
|
||||
query_file = 'get_user_by_oauth_username.sql'
|
||||
columns_where = {'username', 'provider'}
|
|
@ -3,9 +3,6 @@ import sys
|
|||
import codecs
|
||||
import argparse
|
||||
|
||||
sys.path.append(os.path.abspath('../../../scaffold/'))
|
||||
sys.path.insert(0,os.path.abspath('../../../scaffold/'))
|
||||
|
||||
from scaffold import web
|
||||
web.load_widgets('widgets')
|
||||
|
||||
|
@ -33,7 +30,7 @@ def generate_rss():
|
|||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Generate static pages')
|
||||
parser.add_argument('--folder', dest='folder', default='./html/' ,nargs='?', help='output folder')
|
||||
parser.add_argument('--folder', dest='folder', default='./static/html/' ,nargs='?', help='output folder')
|
||||
|
||||
#module, function, output file
|
||||
pages_list = (
|
||||
|
@ -44,7 +41,6 @@ if __name__ == "__main__":
|
|||
('pages.competition', 'index', 'competition.htm'))
|
||||
|
||||
args = parser.parse_args()
|
||||
print args.folder
|
||||
|
||||
for module, page, filename in pages_list:
|
||||
page_module = __import__(module, globals(), locals(), page)
|
||||
|
@ -56,5 +52,5 @@ if __name__ == "__main__":
|
|||
print('Failed to Generate %s%s' % (args.folder, filename))
|
||||
import traceback
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
traceback.print_tb(exc_traceback, limit=5, file=sys.stdout)
|
||||
traceback.print_tb(exc_traceback, limit=10, file=sys.stdout)
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ from pages import homepage
|
|||
from pages import chat
|
||||
from pages import blog
|
||||
from pages import members
|
||||
from pages.contact import contact_page, submit_contact_page
|
||||
|
||||
from pages.core.login_pages import login_pages
|
||||
from pages.core.authorize import authorize_pages, login_manager
|
||||
|
@ -21,7 +22,6 @@ from pages.equipment import equipment_pages
|
|||
from pages.profile import profile_pages
|
||||
|
||||
|
||||
|
||||
web_app = Flask(__name__, static_folder='static')
|
||||
web_app.config['PROPAGATE_EXCEPTIONS'] = True
|
||||
web_app.secret_key = settings.flask_secret_key
|
||||
|
@ -73,5 +73,15 @@ def chat_index():
|
|||
"""competition page"""
|
||||
return make_response(chat.index())
|
||||
|
||||
@web_app.route("/contact-us/", methods=['GET'])
|
||||
def contact_us():
|
||||
"""Contact page"""
|
||||
return make_response(contact_page())
|
||||
|
||||
@web_app.route("/contact-us/", methods=['POST'])
|
||||
def submit_contact_us():
|
||||
"""Contact page"""
|
||||
return make_response(submit_contact_page())
|
||||
|
||||
if __name__ == '__main__':
|
||||
web_app.run(host='0.0.0.0', port=5000, debug=True)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
from uuid import uuid4
|
||||
import os
|
||||
import hashlib
|
||||
import requests
|
||||
|
||||
|
||||
def save_remote_image(url, path='', domain='', skip_exists=True):
|
||||
filename = '%s.%s' % (hashlib.md5(url.encode()).hexdigest(), url[-3:])
|
||||
filepath = os.path.abspath('./static/images/blogs/%s' %(filename))
|
||||
urlpath = 'static/images/blogs/' + filename
|
||||
|
||||
if not url:
|
||||
return None
|
||||
|
||||
if url[-3:] not in ('jpg', 'png'):
|
||||
return None
|
||||
print(domain + urlpath)
|
||||
if skip_exists is True and os.path.exists(filepath):
|
||||
return domain + urlpath
|
||||
|
||||
r = requests.get(url, stream=True)
|
||||
if r.status_code != 200:
|
||||
return None
|
||||
|
||||
with open(filepath, 'wb') as f:
|
||||
for chunk in r.iter_content(1024):
|
||||
f.write(chunk)
|
||||
return domain + urlpath
|
|
@ -1,15 +1,15 @@
|
|||
from mailer import Mailer
|
||||
from mailer import Message
|
||||
|
||||
from config.logger import log
|
||||
|
||||
class sendmail:
|
||||
host = 'localhost'
|
||||
config = 'localhost'
|
||||
charset = 'utf-8'
|
||||
subject_prefix = ''
|
||||
|
||||
@classmethod
|
||||
def set_server(cls, host='localhost', charset='utf-8'):
|
||||
cls.host = host
|
||||
def set_server(cls, config, charset='utf-8'):
|
||||
cls.config = config
|
||||
|
||||
def __call__(self, **args):
|
||||
return self
|
||||
|
@ -19,20 +19,35 @@ class sendmail:
|
|||
self.body = fp.read()
|
||||
self.body.format(**params)
|
||||
|
||||
|
||||
def send(self, from_address, to_address, subject, body=None, html=True):
|
||||
message = Message(
|
||||
From=from_address,
|
||||
To=to_address,
|
||||
charset=self.charset
|
||||
)
|
||||
try:
|
||||
message = Message(
|
||||
From=from_address,
|
||||
To=to_address,
|
||||
charset=self.charset
|
||||
)
|
||||
|
||||
if body:
|
||||
if body is None:
|
||||
body = ''
|
||||
self.body = body
|
||||
|
||||
message.Subject = "%sAn HTML Email" % self.subject_prefix
|
||||
message.Html = self.body
|
||||
message.Body = self.body
|
||||
message.Subject = "%s - %s" % (self.subject_prefix, subject)
|
||||
message.Html = self.body
|
||||
message.Body = self.body
|
||||
except Exception as e:
|
||||
log.exception('[scaffold_mailer] - Failed to create message object for mailer')
|
||||
return False
|
||||
|
||||
sender = Mailer(self.host)
|
||||
sender.send(message)
|
||||
try:
|
||||
sender = Mailer(
|
||||
host=self.config.get('host'),
|
||||
port=self.config.get('port'),
|
||||
use_tls=self.config.get('use_tls', False),
|
||||
use_ssl=True,
|
||||
usr=self.config.get('username'),
|
||||
pwd=self.config.get('password'))
|
||||
sender.send(message)
|
||||
except Exception as e:
|
||||
log.exception('[scaffold_mailer] - Failed to connect to smtp sever and send message with subject: %s' % message.Subject)
|
||||
return False
|
||||
return True
|
||||
|
|
|
@ -24,8 +24,8 @@ class payment:
|
|||
self.provider_id = PROVIDER_ID.get(provider)
|
||||
|
||||
if provider == 'paypal':
|
||||
print settings.payment_providers[provider]['credentials']
|
||||
paypal.configure(**settings.payment_providers[provider]['credentials'])
|
||||
print(settings.payment_providers[provider]['credentials'])
|
||||
return
|
||||
|
||||
#~ environment = int('production' = settings.payment_providers[provider]['environment'])
|
||||
|
@ -52,13 +52,13 @@ class payment:
|
|||
"description": reference}]})
|
||||
|
||||
payment_response = payment.create()
|
||||
print 'payment create'
|
||||
print('payment create')
|
||||
if payment_response:
|
||||
print payment_response
|
||||
print(payment_response)
|
||||
for link in payment.links:
|
||||
if link.method == "REDIRECT":
|
||||
redirect_url = str(link.href)
|
||||
print redirect_url
|
||||
print(redirect_url)
|
||||
return str(redirect_url)
|
||||
else:
|
||||
print("Error while creating payment:")
|
||||
|
@ -84,17 +84,18 @@ class payment:
|
|||
'amount': paying_member.amount}
|
||||
|
||||
if self.provider == 'paypal':
|
||||
#~ I-S39170DK26AF
|
||||
#~ start_date, end_date = "2014-07-01", "2014-07-20"
|
||||
billing_agreement = paypal.BillingAgreement.find('')
|
||||
print billing_agreement
|
||||
print dir(billing_agreement)
|
||||
print(billing_agreement)
|
||||
print(dir(billing_agreement))
|
||||
#~ print billing_agreement.search_transactions(start_date, end_date)
|
||||
#~ transactions = billing_agreement.search_transactions(start_date, end_date)
|
||||
payment_history = paypal.Payment.all({"count": 2})
|
||||
|
||||
# List Payments
|
||||
print("List Payment:")
|
||||
print payment_history
|
||||
print(payment_history)
|
||||
for payment in payment_history.payments:
|
||||
print(" -> Payment[%s]" % (payment.id))
|
||||
#~ print paypal.BillingAgreement.all()
|
||||
|
@ -104,8 +105,8 @@ class payment:
|
|||
|
||||
print("List BillingPlan:")
|
||||
for plan in history.plans:
|
||||
print dir(plan)
|
||||
print plan.to_dict()
|
||||
print(dir(plan))
|
||||
print(plan.to_dict())
|
||||
print(" -> BillingPlan[%s]" % (plan.id))
|
||||
|
||||
#~ merchant = gocardless.client.merchant()
|
||||
|
@ -128,12 +129,12 @@ class payment:
|
|||
}
|
||||
|
||||
if self.provider == 'paypal':
|
||||
print 'subscribe_confirm'
|
||||
print('subscribe_confirm')
|
||||
payment_token = args.get('token', '')
|
||||
billing_agreement_response = paypal.BillingAgreement.execute(payment_token)
|
||||
amount = 0
|
||||
print billing_agreement_response
|
||||
print billing_agreement_response.id
|
||||
print(billing_agreement_response)
|
||||
print(billing_agreement_response.id)
|
||||
for row in billing_agreement_response.plan.payment_definitions:
|
||||
amount = row.amount.value
|
||||
|
||||
|
@ -147,16 +148,16 @@ class payment:
|
|||
|
||||
def unsubscribe(self, reference):
|
||||
if self.provider == 'gocardless':
|
||||
print 'unsubscribe gocardless'
|
||||
print('unsubscribe gocardless')
|
||||
subscription = gocardless.client.subscription(reference)
|
||||
print subscription.cancel()
|
||||
print(subscription.cancel())
|
||||
|
||||
if self.provider == 'paypal':
|
||||
# this may be wrong
|
||||
# ManageRecurringPaymentsProfileStatus
|
||||
print reference
|
||||
print(reference)
|
||||
billing_plan = paypal.BillingAgreement.find(reference)
|
||||
print billing_plan
|
||||
print(billing_plan)
|
||||
print(billing_plan.error)
|
||||
#~ billing_plan.replace([{"op": "replace","path": "/","value": {"state":"DELETED"}}])
|
||||
print(billing_plan.error)
|
||||
|
@ -212,7 +213,7 @@ class payment:
|
|||
],
|
||||
"type": "INFINITE"
|
||||
})
|
||||
print 'create bill'
|
||||
print('create bill')
|
||||
|
||||
response = billing_plan.create()
|
||||
|
||||
|
@ -229,8 +230,8 @@ class payment:
|
|||
})
|
||||
|
||||
if billing_agreement.create():
|
||||
print 'billing agreement id'
|
||||
print billing_agreement.id
|
||||
print('billing agreement id')
|
||||
print(billing_agreement.id)
|
||||
|
||||
for link in billing_agreement.links:
|
||||
if link.rel == "approval_url":
|
||||
|
@ -238,24 +239,24 @@ class payment:
|
|||
return approval_url
|
||||
else:
|
||||
print(billing_agreement.error)
|
||||
print 'failed'
|
||||
print('failed')
|
||||
|
||||
def confirm(self, args):
|
||||
confirm_details = {}
|
||||
confirm_details['successfull'] = False
|
||||
print '---------------------'
|
||||
print args
|
||||
print('---------------------')
|
||||
print(args)
|
||||
|
||||
|
||||
|
||||
from pprint import pprint
|
||||
if self.provider == 'paypal':
|
||||
print args.get('paymentId')
|
||||
print args.get('PayerID')
|
||||
print(args.get('paymentId'))
|
||||
print(args.get('PayerID'))
|
||||
payment = paypal.Payment.find(args.get('paymentId'))
|
||||
pprint(payment)
|
||||
print pprint(payment)
|
||||
print payment
|
||||
print(pprint(payment))
|
||||
print(payment)
|
||||
|
||||
confirm_details['name'] = payment['payer']['payer_info'].first_name + ' ' + payment['payer']['payer_info'].last_name
|
||||
confirm_details['user'] = payment['payer']['payer_info'].email
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
"""https://developers.google.com/recaptcha/docs/verify"""
|
||||
|
||||
from requests import post
|
||||
from config.logger import log
|
||||
|
||||
def verify_captcha(secret, response, remoteip=''):
|
||||
try:
|
||||
response = post(
|
||||
'https://www.google.com/recaptcha/api/siteverify',
|
||||
{'secret': secret,
|
||||
'response': response,
|
||||
'remoteip': remoteip})
|
||||
json = response.json()
|
||||
except:
|
||||
log.error('Failed to get capture json response from google')
|
||||
return False
|
||||
return json.get('success')
|
||||
|
|
@ -7,8 +7,8 @@ from scaffold.core.data.database import db
|
|||
db.config(settings.database)
|
||||
from scaffold.core.data.migrations import export_schema, import_schema
|
||||
|
||||
export_schema(os.path.abspath('./data/migrate/'))
|
||||
#~ import_schema(os.path.abspath('./data/migrate/'))
|
||||
#export_schema(os.path.abspath('./data/migrate/'))
|
||||
import_schema(os.path.abspath('./data/migrate/'))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -15,15 +15,15 @@ web.template.append('<link rel="icon" type="image/png" href="/static/images/icon
|
|||
|
||||
#paths
|
||||
web.document_root = os.path.abspath('./')
|
||||
web.template.domain = 'http://maidstone-hackspace.org.uk/'
|
||||
web.template.domain = 'https://maidstone-hackspace.org.uk/'
|
||||
web.template.theme_full_path = os.path.abspath('./static') + os.sep
|
||||
domain = 'http://192.168.21.41:5000/'
|
||||
image_path = domain + os.sep + 'images' + os.sep
|
||||
#~ domain = 'http://192.168.21.41:5000/'
|
||||
#~ image_path = domain + os.sep + 'images' + os.sep
|
||||
|
||||
|
||||
with web.template as setup:
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />')
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/materialize.css" media="" type="text/css" />')
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />')
|
||||
#~ setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />')
|
||||
#setup.persistent_header('<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.9.4/angular-material.min.css">')
|
||||
#setup.persistent_header('<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=RobotoDraft:300,400,500,700,400italic">')
|
||||
|
@ -31,10 +31,10 @@ with web.template as setup:
|
|||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-action-white.css" media="" type="text/css" />')
|
||||
setup.persistent_header('<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-content-white.css" media="" type="text/css" />')
|
||||
|
||||
|
||||
setup.persistent_header('<script type="text/javascript" src="/static/js/jquery-2.2.3.min.js"></script>')
|
||||
setup.persistent_header('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>')
|
||||
setup.persistent_header('<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js"></script>')
|
||||
setup.persistent_header('<script type="text/javascript" src="/static/js/materialize.js"></script>')
|
||||
setup.persistent_header('<script type="text/javascript" src="/static/js/default.js"></script>')
|
||||
|
||||
#setup.persistent_header('<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.min.js"></script>')
|
||||
|
@ -50,18 +50,19 @@ def header(title, description='Maidstone Hackspace is a shared space where artis
|
|||
web.template.body.append(web.header_strip.render())
|
||||
|
||||
# top menu bar navigation
|
||||
web.menu.create('/' + url).set_id('leftNav')
|
||||
|
||||
web.menu.create('/' + url).set_classes('col s10 offset-s1')
|
||||
web.menu * site.page_menu
|
||||
web.menu.append('Group', '/mailing-list')
|
||||
|
||||
if current_user and current_user.is_authenticated():
|
||||
if current_user and current_user.is_authenticated:
|
||||
web.menu.append('Logout', '/logout')
|
||||
web.navigation_bar.create(hide=(False if url=='/profile' else True))
|
||||
web.navigation_bar * site.nav_for_authenticated_user
|
||||
web.template.body.append(web.navigation_bar.render())
|
||||
else:
|
||||
web.menu.append('Login', '/login')
|
||||
web.template.body.append(web.menu.render())
|
||||
web.template.body.append(web.container.create(web.menu.render()).set_id('menubar').set_classes('row').render())
|
||||
|
||||
# lets create the footer
|
||||
web.footer_content.create().append(
|
||||
|
|
|
@ -12,5 +12,5 @@ def index():
|
|||
web.page.create(web.title.create('IRC Chat Room').render())
|
||||
web.page.create(web.paragraph.create('Pop in and say hi, please be patient users tend to idle and will respond when they get a chance.').render())
|
||||
web.page.section(web.chat.create('maidstone-hackspace').render())
|
||||
web.template.body.append(web.page.render())
|
||||
web.template.body.append(web.page.set_classes('page col s10 offset-s1').render())
|
||||
return footer()
|
||||
|
|
|
@ -8,5 +8,5 @@ def index():
|
|||
web.page.create(web.title.create('IRC Chat Room').render())
|
||||
web.page.create(web.paragraph.create('Pop in and say hi, please be patient users tend to idle, but will likely respond given a chance.').render())
|
||||
web.page.section(web.chat.create('maidstone-hackspace').render())
|
||||
web.template.body.append(web.page.render())
|
||||
web.template.body.append(web.page.set_classes('page col s10 offset-s1').render())
|
||||
return footer()
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
from pages import web
|
||||
from pages import header, footer
|
||||
from config.settings import google_captcha, email_server
|
||||
from libs.mail import sendmail
|
||||
from flask import get_flashed_messages, flash, request
|
||||
from libs.recapture import verify_captcha
|
||||
|
||||
def contact_page():
|
||||
web.template.create('Maidstone Hackspace - Chat room')
|
||||
header('Maidstone Hackspace Chat')
|
||||
|
||||
web.contact_form.capture_settings = google_captcha
|
||||
web.contact_form.create('Contact Us')
|
||||
web.contact_form.enable_capture()
|
||||
web.contact_form.render()
|
||||
|
||||
web.simple_form.create()
|
||||
web.simple_form.append(input_type='text', input_name='test', label='my label')
|
||||
|
||||
web.page.create(web.title.create('Contact Form').render())
|
||||
web.page.section(web.contact_form.render())
|
||||
web.template.body.append(web.page.set_classes('page col s10 offset-s1').render())
|
||||
return footer()
|
||||
|
||||
def submit_contact_page():
|
||||
subject = '[%s] - %s' % (
|
||||
request.form.get('form_query', 'MHS'),
|
||||
request.form.get('form_subject', 'No Subject ?')
|
||||
)
|
||||
|
||||
# Check user password the robot check
|
||||
print(request.form.get('g-recaptcha-response', ''))
|
||||
print(google_captcha.get('secret'))
|
||||
print(request.remote_addr)
|
||||
success = verify_captcha(
|
||||
secret=google_captcha.get('secret'),
|
||||
response=request.form.get('g-recaptcha-response', ''),
|
||||
remoteip=request.remote_addr)
|
||||
|
||||
if success is False:
|
||||
flash('Message failed to send, capture failed to validate are you a robot ?')
|
||||
return contact_page()
|
||||
|
||||
# Send Email and let user know if it worked or not
|
||||
success = sendmail().send(
|
||||
from_address=request.form.get('email'),
|
||||
to_address='contact@maidstone-hackspace.org.uk',
|
||||
subject=subject,
|
||||
body=request.form.get('form_message'))
|
||||
|
||||
if success is False:
|
||||
flash('Sorry system was unable to send your message, someone has been notified.')
|
||||
return contact_page()
|
||||
|
||||
flash('Your message has been sent, we will get back to you shortly.')
|
||||
return contact_page()
|
|
@ -27,7 +27,8 @@ authorize_pages = Blueprint('authorize_pages', __name__, template_folder='templa
|
|||
login_manager = LoginManager()
|
||||
login_manager.login_view = '/login'
|
||||
|
||||
oauth_lookup = {'google':1, 'github':2, 'facebook':3}
|
||||
oauth_lookup_id = {'google':1, 'github':2, 'facebook':3}
|
||||
oauth_lookup_name = dict((v, k) for k, v in oauth_lookup_id.items())
|
||||
|
||||
|
||||
def is_weak_password(password1, password2):
|
||||
|
@ -36,32 +37,28 @@ def is_weak_password(password1, password2):
|
|||
return True
|
||||
|
||||
# TODO check length and chars
|
||||
|
||||
password1 = password2 = None
|
||||
return False
|
||||
|
||||
|
||||
def todict(data):
|
||||
new_dict = {}
|
||||
for key, value in data.items():
|
||||
new_dict[key] = value
|
||||
return new_dict
|
||||
#~ def todict(data):
|
||||
#~ new_dict = {}
|
||||
#~ for key, value in data.items():
|
||||
#~ new_dict[key] = value
|
||||
#~ return new_dict
|
||||
|
||||
|
||||
class User(UserMixin):
|
||||
def __init__(self, user_id, active=True):
|
||||
print user_id
|
||||
self.id = None
|
||||
user_details = site_user.get_user_details({'id': user_id}).get()
|
||||
self.active = False
|
||||
print 'user'
|
||||
print user_details
|
||||
if user_details:
|
||||
self.active = True
|
||||
#~ self.check_password(user_details.get('password'))
|
||||
self.id = user_id
|
||||
self.name = user_details.get('username')
|
||||
print self.name
|
||||
self.active = active
|
||||
#~ self.is_authenticated = self.active
|
||||
|
||||
def get_id(self):
|
||||
return self.id
|
||||
|
@ -90,8 +87,6 @@ def load_token(request):
|
|||
|
||||
if token is not None:
|
||||
username, password = token.split(":") # naive token
|
||||
print username
|
||||
print password
|
||||
user_entry = User.get(username)
|
||||
if (user_entry is not None):
|
||||
user = User(user_entry[0], user_entry[1])
|
||||
|
@ -144,7 +139,7 @@ def register_submit():
|
|||
new_user.execute(data)
|
||||
flash('Your account has now been created')
|
||||
|
||||
web.template.body.append(web.page.render())
|
||||
web.template.body.append(web.page.set_classes('page col s10 offset-s1').render())
|
||||
return make_response(footer())
|
||||
|
||||
@authorize_pages.route("/oauth/<provider>/<start_oauth_login>/", methods=['GET'])
|
||||
|
@ -157,17 +152,17 @@ def oauth(provider, start_oauth_login=False):
|
|||
oauth_access_type = ''
|
||||
oauth_approval_prompt = ''
|
||||
if oauth_live is False:
|
||||
print('offline testing')
|
||||
oauth_verify = False
|
||||
oauth_access_type = 'offline'
|
||||
oauth_approval_prompt = "force"
|
||||
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
|
||||
|
||||
if start_oauth_login:
|
||||
print oauth_provider.get('redirect_uri')
|
||||
oauth_session = OAuth2Session(
|
||||
oauth_provider.get('client_id'),
|
||||
scope=oauth_provider.get('scope'),
|
||||
redirect_uri=oauth_provider.get('redirect_uri'))
|
||||
redirect_uri=request.url_root + oauth_provider.get('redirect_uri'))
|
||||
|
||||
if provider == 'facebook':
|
||||
oauth_session = facebook_compliance_fix(oauth_session)
|
||||
|
@ -183,15 +178,15 @@ def oauth(provider, start_oauth_login=False):
|
|||
session.modified = True
|
||||
return redirect(authorization_url)
|
||||
|
||||
if session.get('oauth_state', None) is None:
|
||||
flash('Something went wrong, oauth session not started')
|
||||
return redirect('/login')
|
||||
|
||||
# allready authorised so lets handle the callback
|
||||
oauth_session = OAuth2Session(
|
||||
oauth_provider.get('client_id'),
|
||||
state=session['oauth_state'],
|
||||
redirect_uri=oauth_provider.get('redirect_uri'))
|
||||
|
||||
print '----------'
|
||||
print oauth_provider.get('redirect_uri')
|
||||
print request.url
|
||||
redirect_uri=request.url_root + oauth_provider.get('redirect_uri'))
|
||||
|
||||
if provider == 'facebook':
|
||||
oauth_session = facebook_compliance_fix(oauth_session)
|
||||
|
@ -208,11 +203,8 @@ def oauth(provider, start_oauth_login=False):
|
|||
response = oauth_session.get(oauth_provider.get('user_uri'))
|
||||
oauth_response = response.json()
|
||||
|
||||
print 'oauth response'
|
||||
print oauth_response
|
||||
|
||||
oauth_id = oauth_response.get('login') or oauth_response.get('id')
|
||||
provider_id = oauth_lookup.get(provider)
|
||||
provider_id = oauth_lookup_id.get(provider)
|
||||
oauth_user = site_user.fetch_oauth_login({
|
||||
'username': oauth_id or '',
|
||||
'provider': provider_id
|
||||
|
@ -233,8 +225,6 @@ def oauth(provider, start_oauth_login=False):
|
|||
|
||||
flash('Your new profile has been created, and your now logged in')
|
||||
|
||||
print 'current user'
|
||||
print current_user.get_id()
|
||||
if current_user.get_id():
|
||||
# link oauth to users account
|
||||
site_user.create_oauth_login().execute({
|
||||
|
@ -243,9 +233,6 @@ def oauth(provider, start_oauth_login=False):
|
|||
'provider': provider_id})
|
||||
return redirect('/profile')
|
||||
|
||||
print oauth_response
|
||||
print '-----'
|
||||
print oauth_response.get('email') or ''
|
||||
# create new user from oauth information
|
||||
|
||||
new_user_details = {
|
||||
|
@ -278,13 +265,11 @@ def oauth(provider, start_oauth_login=False):
|
|||
@authorize_pages.route("/change-password", methods=['GET'])
|
||||
def change_password(code=None):
|
||||
#if we have a code this is a password reset, so try and login the user first
|
||||
print code
|
||||
site_user.delete_password_reset().execute({})
|
||||
if code:
|
||||
|
||||
user_details = site_user.get_user_by_reset_code({'reset_code': code}).get()
|
||||
|
||||
print user_details
|
||||
if not user_details:
|
||||
#invalid code so pretend the page does not even exist
|
||||
return abort(404)
|
||||
|
@ -292,7 +277,6 @@ def change_password(code=None):
|
|||
#datetime.datetime.now() + datetime.timedelta(minutes=15)
|
||||
has_date_expired = user_details.get('created') + datetime.timedelta(minutes=60)
|
||||
if has_date_expired < datetime.datetime.now():
|
||||
print 'date expired'
|
||||
#date expired so clean up and pretend the page does not exist
|
||||
return abort(404)
|
||||
#challenge passed so login the user so they can change there password
|
||||
|
@ -307,7 +291,7 @@ def change_password(code=None):
|
|||
web.page.section(
|
||||
web.change_password_box.create().render()
|
||||
)
|
||||
web.template.body.append(web.page.render())
|
||||
web.template.body.append(web.page.set_classes('page col s10 offset-s1').render())
|
||||
return make_response(footer())
|
||||
|
||||
@login_required
|
||||
|
@ -315,16 +299,16 @@ def change_password(code=None):
|
|||
def change_password_submit(code=None):
|
||||
if not session.get('user_id'):
|
||||
abort(404)
|
||||
user_details = site_user.authorize({
|
||||
'id': session.get('user_id')}).get()
|
||||
|
||||
if is_weak_password(request.form.get('password'), request.form.get('password_confirm')):
|
||||
print 'password not strong enough'
|
||||
redirect('/login')
|
||||
|
||||
|
||||
pw_hash = generate_password_hash(request.form.get('password'))
|
||||
|
||||
site_user.change_password().execute({'id': user_details.get('user_id'), 'password': pw_hash})
|
||||
user_details = site_user.authorize({
|
||||
'id': session.get('user_id')}).get()
|
||||
site_user.change_password().execute({
|
||||
'id': user_details.get('user_id'),
|
||||
'password': pw_hash})
|
||||
|
||||
web.template.create('Maidstone Hackspace - Profile')
|
||||
header('User Profile')
|
||||
|
@ -381,18 +365,6 @@ def reset_password_submit():
|
|||
web.template.body.append(web.page.render())
|
||||
return make_response(footer())
|
||||
|
||||
#~ @authorize_pages.route("/login", methods=['GET'])
|
||||
#~ def login_screen():
|
||||
#~ web.template.create('Maidstone Hackspace - Login')
|
||||
#~ header('Members Login')
|
||||
#~ web.page.create('Member Login')
|
||||
#~ web.page.section(
|
||||
#~ web.login_box.create().enable_oauth('google').enable_oauth('facebook').enable_oauth('github').render()
|
||||
#~ )
|
||||
#~ web.template.body.append(web.page.render())
|
||||
#~ return make_response(footer())
|
||||
|
||||
|
||||
@authorize_pages.route("/login/failure", methods=['GET'])
|
||||
def login_Failure():
|
||||
web.template.create('%s - Login' % site_name)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
from flask import session, flash
|
||||
from flask import redirect, abort
|
||||
from flask import make_response
|
||||
|
@ -12,6 +13,7 @@ from requests_oauthlib.compliance_fixes import facebook_compliance_fix
|
|||
from scaffold import web
|
||||
from libs.mail import sendmail
|
||||
from pages import header, footer
|
||||
from pages.core.authorize import User
|
||||
from data import site_user
|
||||
from config.settings import *
|
||||
from constants import *
|
||||
|
@ -26,9 +28,9 @@ def login_screen():
|
|||
header('Members Login')
|
||||
web.page.create('Member Login')
|
||||
web.page.section(
|
||||
web.login_box.create().enable_oauth('google').enable_oauth('facebook').enable_oauth('github').render()
|
||||
web.loginBox.create().enable_oauth('google').enable_oauth('facebook').enable_oauth('github').render()
|
||||
)
|
||||
web.template.body.append(web.page.render())
|
||||
web.template.body.append(web.page.set_classes('page col s10 offset-s1').render())
|
||||
return make_response(footer())
|
||||
|
||||
|
||||
|
@ -37,7 +39,7 @@ def login_screen_submit():
|
|||
"""handle the login form submit"""
|
||||
# try to find user by username
|
||||
user_details = site_user.get_by_username({
|
||||
'email': request.form.get('username')}).get()
|
||||
'username': request.form.get('username')}).get()
|
||||
|
||||
# not found so lets bail to the login screen
|
||||
if not user_details:
|
||||
|
@ -56,7 +58,7 @@ def login_screen_submit():
|
|||
)
|
||||
|
||||
flash('You have successfully logged in !')
|
||||
site_user.update_last_login().execute(user_details)
|
||||
site_user.update_last_login().execute({'id': user_details.get('user_id')})
|
||||
|
||||
# logged in but no E-Mail so lets ask the user for there email.
|
||||
if not user_details.get('email'):
|
||||
|
|
|
@ -40,7 +40,7 @@ def index():
|
|||
web.form.append(name='amount', label='Donation Amount', placeholder='50.00', value='50.00')
|
||||
web.page.append(web.form.render())
|
||||
|
||||
web.template.body.append(web.page.render())
|
||||
web.template.body.append(web.page.set_classes('page col s10 offset-s1').render())
|
||||
return web.render()
|
||||
|
||||
|
||||
|
@ -67,10 +67,8 @@ def populate_by_name():
|
|||
web.template.body.append('Populating users')
|
||||
user_list = {}
|
||||
#make sure we have all users in the system
|
||||
print '--------------'
|
||||
#~ users_emails = []
|
||||
for user in merchant.users():
|
||||
#~ print dir(user)
|
||||
user_list[user.id] = user.email
|
||||
#~ users_emails.append(user.email)
|
||||
site_user.create_basic_user().execute({
|
||||
|
|
|
@ -11,3 +11,29 @@ def twitter():
|
|||
web.twitter_feed.render())
|
||||
web.template.body.append(web.page.render())
|
||||
return footer()
|
||||
|
||||
# normally you will abstract the html into the widgets folder so its reusable
|
||||
# to keep things as simple as possibler for everyone you can bypass and render you html direct
|
||||
# either to tha page web.page.section or to web.template.body
|
||||
# This is the simplest way to make a page
|
||||
def simple_page():
|
||||
web.template.create('Maidstone Hackspace')
|
||||
header('Maidstone Hackspace Homepage')
|
||||
|
||||
# render to a page in this way
|
||||
web.page.create('Page title ')
|
||||
web.page.section('<p>Page Body<p>')
|
||||
web.template.body.append(web.page.render())
|
||||
|
||||
# render direct to the template body in this way
|
||||
data = {
|
||||
'first_value': 'value from where ever',
|
||||
'second_value': 'value from where ever'}
|
||||
|
||||
web.template.body.append("""
|
||||
<div>some content here</div>
|
||||
<p>paragrph or any other html you want to place in here</p>
|
||||
<span>{first_value}</span>
|
||||
<span>{second_value}</span>
|
||||
""".format(*data))
|
||||
return footer()
|
||||
|
|
|
@ -19,6 +19,6 @@ def index(request_id=None):
|
|||
web.container.create(web.google_groups.render()).set_classes('margin_default')
|
||||
web.page.append(web.container.render())
|
||||
|
||||
web.template.body.append(web.page.render())
|
||||
web.template.body.append(web.page.set_classes('page col s10 offset-s1').render())
|
||||
return footer()
|
||||
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
import constants as site
|
||||
|
||||
#~ from config.settings import *
|
||||
from config.settings import google_calendar_id, google_calendar_api_key
|
||||
from libs.image_fetcher import save_remote_image
|
||||
from config.settings import google_calendar_id, google_calendar_api_key, app_domain
|
||||
|
||||
from scaffold.readers.rss_reader import feed_reader
|
||||
#~ from libs.rss_fetcher import feed_reader
|
||||
from scaffold import web
|
||||
#~ from pages import web
|
||||
from pages import header, footer
|
||||
|
||||
|
||||
def index():
|
||||
web.template.create('Maidstone Hackspace')
|
||||
header('Maidstone Hackspace Homepage')
|
||||
web.page.create('')
|
||||
web.page.create('').set_classes('page col s10 offset-s1')
|
||||
web.page.section(
|
||||
web.div.create(
|
||||
web.google_calendar.create(
|
||||
|
@ -53,18 +50,22 @@ def index():
|
|||
# fetch the rss feeds from the various blogs for the homepage
|
||||
web.columns.create()
|
||||
feed = feed_reader(site.rss_feeds)
|
||||
|
||||
|
||||
web.tiles.create()
|
||||
for row in feed:
|
||||
web.tiles.create()
|
||||
web.columns.append(
|
||||
web.tiles.append(
|
||||
row['image'] = save_remote_image(row.get('image'), domain=app_domain + '/')
|
||||
|
||||
web.tiles.append(
|
||||
title = row.get('title'),
|
||||
author = row.get('author'),
|
||||
link = row.get('url'),
|
||||
image = row.get('image'),
|
||||
date = row.get('date'),
|
||||
description = row.get('description')).render())
|
||||
web.page.append(web.columns.render())
|
||||
|
||||
description = row.get('description')).render()
|
||||
#~ web.columns.append(
|
||||
#~ )
|
||||
web.page.append(web.div.create(web.tiles.render()).set_classes('row').render())
|
||||
web.template.body.append(web.page.render())
|
||||
|
||||
return footer()
|
||||
|
|
|
@ -35,9 +35,9 @@ def index():
|
|||
if item.get('status') is 1:
|
||||
count_members += 1
|
||||
|
||||
web.info_box.create('Current Users')
|
||||
web.info_box.append('Members %d<br />' % count_members)
|
||||
web.info_box.append('Users %d<br />' % count_users)
|
||||
web.info_box.create('<div class="col s4 dark-blue">Current Users</div>').set_classes('row')
|
||||
web.info_box.append('<div class="col s4 dark-blue">Members %d</div>' % count_members)
|
||||
web.info_box.append('<div class="col s4 dark-blue">Users %d</div>' % count_users)
|
||||
web.page.section(web.info_box.render())
|
||||
|
||||
web.container.create(web.member_tiles.render()).set_classes('members')
|
||||
|
|
|
@ -5,9 +5,10 @@ from flask.ext.login import current_user, login_required
|
|||
|
||||
from constants import badge_lookup
|
||||
|
||||
from pages.core.authorize import oauth_lookup_name
|
||||
from pages import web
|
||||
from pages import header, footer
|
||||
from data.site_user import get_user_details, update_membership, update_membership_status, get_user_bio, create_membership
|
||||
from data.site_user import get_user_details, get_registered_oauth_providers, update_membership, update_membership_status, get_user_bio, create_membership
|
||||
from data.profile import update_description, create_description, fetch_users
|
||||
from data import badges
|
||||
from data import members
|
||||
|
@ -23,32 +24,24 @@ profile_pages = Blueprint('profile_pages', __name__, template_folder='templates'
|
|||
def index():
|
||||
web.template.create('Maidstone Hackspace - User profile')
|
||||
header('User Profile', url='/profile')
|
||||
print current_user
|
||||
user = get_user_details({'id': current_user.get_id()}).get()
|
||||
user_oauth_providers = [provider for provider in get_registered_oauth_providers({'user_id': current_user.get_id()})]
|
||||
|
||||
name = '%s %s' % (user.get('first_name', '').capitalize(), user.get('last_name', '').capitalize())
|
||||
name = '%s %s' % (
|
||||
user.get('first_name', '').capitalize(),
|
||||
user.get('last_name', '').capitalize())
|
||||
web.page.create('%s - Profile' % name)
|
||||
web.columns.create()
|
||||
|
||||
|
||||
web.paragraph.create(
|
||||
web.images.create(user.get('profile_image', '/static/images/hackspace.png'), name).add_attributes('width', '200').render()
|
||||
)
|
||||
web.paragraph.add(name)
|
||||
web.paragraph.add('%s' % (user.get('email')))
|
||||
web.paragraph.add('%s' % (user.get('email', '') if user.get('email', '') else ''))
|
||||
web.paragraph.add('Last Login %s' % (user.get('last_login', '')))
|
||||
web.paragraph.add('Member since %s' % (user.get('created', '')))
|
||||
web.paragraph.add('Description %s' % (user.get('description', '')))
|
||||
web.paragraph.add('Skills %s' % (user.get('skills', '')))
|
||||
web.columns.append(web.paragraph.render())
|
||||
|
||||
# membership form
|
||||
web.columns.append(
|
||||
web.member_card.create(
|
||||
reference=str(user.get('user_id')).zfill(5),
|
||||
name=name,
|
||||
active=user.get('status')==1
|
||||
).render()
|
||||
)
|
||||
web.div.create(web.paragraph.render())
|
||||
|
||||
web.paragraph.create(
|
||||
web.link.create(
|
||||
|
@ -63,11 +56,33 @@ def index():
|
|||
'Link login provider',
|
||||
'/login'
|
||||
).render())
|
||||
|
||||
web.table.create('', ('Login providers', 'Last login'))
|
||||
for provider in user_oauth_providers:
|
||||
web.table.append((
|
||||
str(oauth_lookup_name.get(int(provider.get('provider')))),
|
||||
provider.get('last_login') if provider.get('last_login') else 'Unknown'))
|
||||
|
||||
web.paragraph.append(
|
||||
web.table.render())
|
||||
|
||||
|
||||
web.columns.append(web.paragraph.render())
|
||||
web.page.section(
|
||||
web.div.append(
|
||||
web.paragraph.render()
|
||||
).set_classes('col s6').render()
|
||||
)
|
||||
# membership form
|
||||
web.page.append(
|
||||
web.div.create(
|
||||
web.member_card.create(
|
||||
reference=str(user.get('user_id')).zfill(5),
|
||||
name=name,
|
||||
active=user.get('status')==1
|
||||
).render()
|
||||
).set_classes('col s6').render()
|
||||
)
|
||||
|
||||
|
||||
web.page.section(web.columns.render())
|
||||
web.template.body.append(web.page.render())
|
||||
web.template.body.append(web.popup.create('').render())
|
||||
|
||||
|
@ -83,26 +98,24 @@ def setup():
|
|||
badges.create_badge().execute({'id': badge_id, 'name': badge_name})
|
||||
|
||||
user_lookup = {}
|
||||
for member in fetch_users():
|
||||
for member in fetch_users():
|
||||
user_lookup[member.get('email')] = member.get('user_id')
|
||||
|
||||
provider = payment(provider='paypal', style='payment')
|
||||
for item in provider.fetch_subscriptions():
|
||||
print item
|
||||
print(item)
|
||||
|
||||
print user_lookup
|
||||
merchant = gocardless.client.merchant()
|
||||
#https://jsfiddle.net/api/post/library/pure/
|
||||
for paying_member in merchant.subscriptions():
|
||||
print dir(paying_member)
|
||||
print paying_member.user()
|
||||
print paying_member.amount
|
||||
print(dir(paying_member))
|
||||
print(paying_member.user())
|
||||
print(paying_member.amount)
|
||||
user=paying_member.user()
|
||||
|
||||
print '---------------'
|
||||
print user.email
|
||||
print(user.email)
|
||||
user_id = user_lookup.get(user.email)
|
||||
print user_id
|
||||
print(user_id)
|
||||
update_membership_status().execute({'user_id': user_id, 'status': '1'})
|
||||
create_membership().execute({'user_id': user_id, 'status': '1', 'join_date': paying_member.created_at, 'amount': paying_member.amount, 'subscription_id': paying_member.id})
|
||||
|
||||
|
@ -138,8 +151,8 @@ def cancel_membership():
|
|||
user_code = str(user.get('user_id')).zfill(5)
|
||||
|
||||
subscription = members.fetch_member_subscription({'user_id': current_user.get_id()}).get()
|
||||
print subscription.get('provider_id')
|
||||
print subscription.get('subscription_reference')
|
||||
print(subscription.get('provider_id'))
|
||||
print(subscription.get('subscription_reference'))
|
||||
|
||||
|
||||
provider = payment(provider='paypal', style='payment')
|
||||
|
@ -194,10 +207,10 @@ def membership_signup(provider):
|
|||
def update_profiles():
|
||||
"""this is used to sync up older accounts"""
|
||||
for user in get_users():
|
||||
print user
|
||||
print(user)
|
||||
|
||||
for payment in get_users():
|
||||
print user
|
||||
print(user)
|
||||
|
||||
return web.form.render()
|
||||
|
||||
|
@ -205,9 +218,8 @@ def update_profiles():
|
|||
@login_required
|
||||
def edit_profile():
|
||||
user_details = get_user_details({'id': current_user.get_id()}).get() or {}
|
||||
print user_details
|
||||
if not user_details:
|
||||
print 'create'
|
||||
print('create')
|
||||
create_description().execute({'user_id': current_user.get_id()})
|
||||
web.form.create('Update your details', '/profile/update')
|
||||
web.form.append(name='description', label='Description', placeholder='This is me i am great', value=user_details.get('description') or '')
|
||||
|
|
|
@ -2,45 +2,47 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:sa="/">
|
||||
<head>
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/materialize.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-navigation-white.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-action-white.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-content-white.css" media="" type="text/css" />
|
||||
<script type="text/javascript" src="/static/js/jquery-2.1.4.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery-2.2.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js"></script>
|
||||
<script type="text/javascript" src="/static/js/materialize.js"></script>
|
||||
<script type="text/javascript" src="/static/js/default.js"></script>
|
||||
<link rel="icon" type="image/png" href="/static/images/favicon.png">
|
||||
<title>Maidstone Hackspace - Chat room</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="headerstrip"><nav class="navstrip"><div class="left"><a id="mini_logo" href="/login"><img src="//127.0.0.1:5000/static/images/hackspace.png" class="mini-logo"></a><span class="mini-logo-text">Maidstone Hackspace</span></div><div class="social"><div class="btn"><a href="https://twitter.com/share" class="twitter-share-button" data-via="http://maidstone-hackspace.org.uk/">Tweet</a></div><div class="btn"><div class="fb-share-button" data-href="http://maidstone-hackspace.org.uk/" data-layout="button_count"></div></div><div class="btn"><script type="IN/Share" data-url="http://maidstone-hackspace.org.uk/" data-counter="right"></script></div><div class="btn"><div size="standard" class="g-plusone" data-href="http://maidstone-hackspace.org.uk/" data-size="medium" data-annotation="bubble" count="true"></div></div></div></nav></div>
|
||||
<nav id="leftNav" class="menu" >
|
||||
<div id="headerstrip" class="row"><nav class="navstrip"><div class="navstripleft col s6"><a id="mini_logo" href="/login"><img src="//http://127.0.0.1/static/images/hackspace.png" class="mini-logo"></a><span class="mini-logo-text">Maidstone Hackspace</span></div><div class="col s6 offset-s8 social"><div class="socbtn"><a href="https://twitter.com/share" class="twitter-share-button" data-via="https://maidstone-hackspace.org.uk/" data-hashtags="mhackspace">Tweet</a></div><div class="socbtn"><div class="fb-share-button" data-href="https://maidstone-hackspace.org.uk/" data-layout="button_count"></div></div><div class="socbtn"><script type="IN/Share" data-url="https://maidstone-hackspace.org.uk/" data-counter="right"></script></div><div class="socbtn"><div size="standard" class="g-plusone" data-href="https://maidstone-hackspace.org.uk/" data-size="medium" data-annotation="bubble" count="true"></div></div></div></nav></div>
|
||||
<div id="menubar" class="row" ><nav class="col s10 offset-s1" >
|
||||
<ul>
|
||||
<li class="active mi0"><a href="/" >Home</a></li>
|
||||
<li class="mi1"><a href="/chat" >Chat</a></li>
|
||||
<li class="mi2"><a href="/donate" >Donate</a></li>
|
||||
<li class="mi3"><a href="#mailing-list-signup" >Contact</a></li>
|
||||
<li class="mi4"><a href="/login" >login</a></li>
|
||||
<li class="mi3"><a href="/contact-us" >Contact</a></li>
|
||||
<li class="mi4"><a href="/mailing-list" >Group</a></li>
|
||||
<li class="mi5"><a href="/login" >Login</a></li>
|
||||
</ul>
|
||||
<div style="clear:both;"></div>
|
||||
</nav>
|
||||
<div class="page" >
|
||||
</nav></div>
|
||||
<div class="row"><div class="page col s10 offset-s1" >
|
||||
<header class="pageHeader">
|
||||
<p>Pop in and say hi, please be patient users tend to idle, but will likely respond given a chance.</p></header>
|
||||
<section class="pageSection">
|
||||
<section class="pageSection col s12">
|
||||
<div class="social-chat"><div class="contain"><iframe src="https://webchat.freenode.net?channels=%23maidstone-hackspace&uio=MTE9MjU207"></iframe></div></div></section>
|
||||
<footer class="pageFooter">
|
||||
<footer class="pageFooter col s12">
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<div id="footer"><div id="footertop"></div><div id="footerbottom"><div class="container"><div class="copyright">©2016 Maidstone Hackspace</div><div mailing-list-signup class="google-groups-signup"><h3>Signup and make yourself known</h3><form class="block" name="signup" method="get" action="http://groups.google.com/group/maidstone-hackspace/boxsubscribe"><label for="groups-email">Email Address</label><input id="groups-email" name="email" class="required"/><button type="submit" />Subscribe</button><a href="http://groups.google.com/group/maidstone-hackspace">Browse Archives</a></form><div style="clear:both;"></div><div></div></div><div>
|
||||
</div></div>
|
||||
<div id="footer"><div id="footertop"></div><div id="footerbottom"><div class="container"><div class="copyright">©2016 Maidstone Hackspace</div><div mailing-list-signup class="google-groups-signup"><h3>Signup and make yourself known</h3><form class="block" name="signup" method="get" action="https://groups.google.com/group/maidstone-hackspace/boxsubscribe"><label for="groups-email">Email Address</label><input id="groups-email" name="email" class="required"/><button type="submit" />Subscribe</button><a href="http://groups.google.com/group/maidstone-hackspace">View Group</a></form><div style="clear:both;"></div><div></div></div><div>
|
||||
<!--google analytics-->
|
||||
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
|
||||
|
||||
<script><!--//--><![CDATA[//><!--!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'http://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
|
||||
//]]></script>
|
||||
|
||||
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
|
||||
|
||||
<script src="//platform.linkedin.com/in.js" type="text/javascript"> lang: en_US</script>
|
||||
|
||||
|
@ -48,29 +50,6 @@
|
|||
//facebook share
|
||||
(function(d, s, id) {var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) return;js = d.createElement(s); js.id = id;js.src = "//connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v2.3";fjs.parentNode.insertBefore(js, fjs);}(document, 'script', 'facebook-jssdk'));
|
||||
//]]></script><script type="text/javascript" ><!--//--><![CDATA[//><!--
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#mini_logo').on("click", function(e){
|
||||
e.preventDefault();
|
||||
$('#member_navigation').toggle();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
|
||||
ga('create', 'UA-63373181-1', 'maidstone-hackspace.org.uk');
|
||||
|
||||
ga('send', 'pageview');
|
||||
|
||||
var app = angular.module('myApp', ['ngAnimate']);
|
||||
|
||||
app.controller('sliderController', function($scope, $interval) {
|
||||
|
@ -113,6 +92,29 @@ app.controller('sliderController', function($scope, $interval) {
|
|||
|
||||
});
|
||||
|
||||
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#mini_logo').on("click", function(e){
|
||||
e.preventDefault();
|
||||
$('#member_navigation').toggle();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
|
||||
ga('create', 'UA-63373181-1', 'maidstone-hackspace.org.uk');
|
||||
|
||||
ga('send', 'pageview');
|
||||
//]]>
|
||||
</script>
|
||||
|
|
@ -2,49 +2,52 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:sa="/">
|
||||
<head>
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/materialize.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-navigation-white.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-action-white.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-content-white.css" media="" type="text/css" />
|
||||
<script type="text/javascript" src="/static/js/jquery-2.1.4.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery-2.2.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js"></script>
|
||||
<script type="text/javascript" src="/static/js/materialize.js"></script>
|
||||
<script type="text/javascript" src="/static/js/default.js"></script>
|
||||
<link rel="icon" type="image/png" href="/static/images/favicon.png">
|
||||
<title>Maidstone Hackspace - Screw sorting competition</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="headerstrip"><nav class="navstrip"><div class="left"><a id="mini_logo" href="/login"><img src="//127.0.0.1:5000/static/images/hackspace.png" class="mini-logo"></a><span class="mini-logo-text">Maidstone Hackspace</span></div><div class="social"><div class="btn"><a href="https://twitter.com/share" class="twitter-share-button" data-via="http://maidstone-hackspace.org.uk/">Tweet</a></div><div class="btn"><div class="fb-share-button" data-href="http://maidstone-hackspace.org.uk/" data-layout="button_count"></div></div><div class="btn"><script type="IN/Share" data-url="http://maidstone-hackspace.org.uk/" data-counter="right"></script></div><div class="btn"><div size="standard" class="g-plusone" data-href="http://maidstone-hackspace.org.uk/" data-size="medium" data-annotation="bubble" count="true"></div></div></div></nav></div>
|
||||
<nav id="leftNav" class="menu" >
|
||||
<div id="headerstrip" class="row"><nav class="navstrip"><div class="navstripleft col s6"><a id="mini_logo" href="/login"><img src="//http://127.0.0.1/static/images/hackspace.png" class="mini-logo"></a><span class="mini-logo-text">Maidstone Hackspace</span></div><div class="col s6 offset-s8 social"><div class="socbtn"><a href="https://twitter.com/share" class="twitter-share-button" data-via="https://maidstone-hackspace.org.uk/" data-hashtags="mhackspace">Tweet</a></div><div class="socbtn"><div class="fb-share-button" data-href="https://maidstone-hackspace.org.uk/" data-layout="button_count"></div></div><div class="socbtn"><script type="IN/Share" data-url="https://maidstone-hackspace.org.uk/" data-counter="right"></script></div><div class="socbtn"><div size="standard" class="g-plusone" data-href="https://maidstone-hackspace.org.uk/" data-size="medium" data-annotation="bubble" count="true"></div></div></div></nav></div>
|
||||
<div id="menubar" class="row" ><nav class="col s10 offset-s1" >
|
||||
<ul>
|
||||
<li class="active mi0"><a href="/" >Home</a></li>
|
||||
<li class="mi1"><a href="/chat" >Chat</a></li>
|
||||
<li class="mi2"><a href="/donate" >Donate</a></li>
|
||||
<li class="mi3"><a href="#mailing-list-signup" >Contact</a></li>
|
||||
<li class="mi4"><a href="/login" >login</a></li>
|
||||
<li class="mi3"><a href="/contact-us" >Contact</a></li>
|
||||
<li class="mi4"><a href="/mailing-list" >Group</a></li>
|
||||
<li class="mi5"><a href="/login" >Login</a></li>
|
||||
</ul>
|
||||
<div style="clear:both;"></div>
|
||||
</nav>
|
||||
<div class="page" >
|
||||
</nav></div>
|
||||
<div class="row"><div class="page col s10 offset-s1" >
|
||||
<header class="pageHeader">
|
||||
<img src="/static/images/competitions/screw_sorting_competition_banner.jpg" alt="Screw sorting competition banner" align="middle" style="margin:auto;display:block;width:500px;" />
|
||||
</header>
|
||||
<section class="pageSection">
|
||||
<section class="pageSection col s12">
|
||||
<p>Welcome to the first Maidstone Hackspace challenge! A great opportunity for all to show off their creative flair and to join our community of makers, tinkerers, artists and more.</p><h2>The Challenge:</h2></section>
|
||||
<section class="pageSection">
|
||||
<section class="pageSection col s12">
|
||||
<p>Design a device which can sort a jar of screws by size, the winning entry will be built by Maidstone Hackspace.</p></section>
|
||||
<section class="pageSection">
|
||||
<section class="pageSection col s12">
|
||||
<p>Concepts can be designed in any software as long as the finished product is viewable without any specialist software e.g.JPG images. If you prefer to paint or draw we accept that too.</p></section>
|
||||
<section class="pageSection">
|
||||
<section class="pageSection col s12">
|
||||
<p>Submissions must be via our mailing list. The closing date is the 31st of July, submissions after this date will not be entered.</p></section>
|
||||
<section class="pageSection">
|
||||
<section class="pageSection col s12">
|
||||
<p><a title="Submit your image here." href="https://groups.google.com/forum/#!forum/maidstone-hackspace" >Submit your image here.</a>
|
||||
</p></section>
|
||||
<section class="pageSection">
|
||||
<section class="pageSection col s12">
|
||||
<h2>Win a UNO Basic Starter Kit</h2></section>
|
||||
<section class="pageSection">
|
||||
<section class="pageSection col s12">
|
||||
<p><img src="http://imgapp.banggood.com/thumb/large/2014/xiemeijuan/03/SKU208787/SKU208787a.jpg" alt="Arduino starter kit" align="middle" style="margin:auto;display:block;width:500px;" />
|
||||
This kit comes with an arduino board and various sensors and components, list below of every thing in the kit.<ul class="bullet-list" >
|
||||
<li>1 x Arduino UNO R3 development board</li>
|
||||
|
@ -85,15 +88,14 @@ This kit comes with an arduino board and various sensors and components, list be
|
|||
<li>1 x 9V battery</li>
|
||||
<li>1 x 2.54mm 40pin pin header</li>
|
||||
</ul></p></section>
|
||||
<footer class="pageFooter">
|
||||
<footer class="pageFooter col s12">
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<div id="footer"><div id="footertop"></div><div id="footerbottom"><div class="container"><div class="copyright">©2016 Maidstone Hackspace</div><div mailing-list-signup class="google-groups-signup"><h3>Signup and make yourself known</h3><form class="block" name="signup" method="get" action="http://groups.google.com/group/maidstone-hackspace/boxsubscribe"><label for="groups-email">Email Address</label><input id="groups-email" name="email" class="required"/><button type="submit" />Subscribe</button><a href="http://groups.google.com/group/maidstone-hackspace">Browse Archives</a></form><div style="clear:both;"></div><div></div></div><div>
|
||||
</div></div>
|
||||
<div id="footer"><div id="footertop"></div><div id="footerbottom"><div class="container"><div class="copyright">©2016 Maidstone Hackspace</div><div mailing-list-signup class="google-groups-signup"><h3>Signup and make yourself known</h3><form class="block" name="signup" method="get" action="https://groups.google.com/group/maidstone-hackspace/boxsubscribe"><label for="groups-email">Email Address</label><input id="groups-email" name="email" class="required"/><button type="submit" />Subscribe</button><a href="http://groups.google.com/group/maidstone-hackspace">View Group</a></form><div style="clear:both;"></div><div></div></div><div>
|
||||
<!--google analytics-->
|
||||
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
|
||||
|
||||
<script><!--//--><![CDATA[//><!--!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'http://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
|
||||
//]]></script>
|
||||
|
||||
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
|
||||
|
||||
<script src="//platform.linkedin.com/in.js" type="text/javascript"> lang: en_US</script>
|
||||
|
||||
|
@ -101,29 +103,6 @@ This kit comes with an arduino board and various sensors and components, list be
|
|||
//facebook share
|
||||
(function(d, s, id) {var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) return;js = d.createElement(s); js.id = id;js.src = "//connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v2.3";fjs.parentNode.insertBefore(js, fjs);}(document, 'script', 'facebook-jssdk'));
|
||||
//]]></script><script type="text/javascript" ><!--//--><![CDATA[//><!--
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#mini_logo').on("click", function(e){
|
||||
e.preventDefault();
|
||||
$('#member_navigation').toggle();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
|
||||
ga('create', 'UA-63373181-1', 'maidstone-hackspace.org.uk');
|
||||
|
||||
ga('send', 'pageview');
|
||||
|
||||
var app = angular.module('myApp', ['ngAnimate']);
|
||||
|
||||
app.controller('sliderController', function($scope, $interval) {
|
||||
|
@ -166,6 +145,29 @@ app.controller('sliderController', function($scope, $interval) {
|
|||
|
||||
});
|
||||
|
||||
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#mini_logo').on("click", function(e){
|
||||
e.preventDefault();
|
||||
$('#member_navigation').toggle();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
|
||||
ga('create', 'UA-63373181-1', 'maidstone-hackspace.org.uk');
|
||||
|
||||
ga('send', 'pageview');
|
||||
//]]>
|
||||
</script>
|
||||
|
|
@ -2,48 +2,48 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:sa="/">
|
||||
<head>
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/materialize.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/default.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/js/jquery-ui/themes/base/jquery-ui.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-navigation-white.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-action-white.css" media="" type="text/css" />
|
||||
<link rel="stylesheet" id="navigationCss" href="/static/css/sprite-content-white.css" media="" type="text/css" />
|
||||
<script type="text/javascript" src="/static/js/jquery-2.1.4.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery-2.2.3.min.js"></script>
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.js"></script>
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js"></script>
|
||||
<script type="text/javascript" src="/static/js/materialize.js"></script>
|
||||
<script type="text/javascript" src="/static/js/default.js"></script>
|
||||
<link rel="icon" type="image/png" href="/static/images/favicon.png">
|
||||
<title>Maidstone Hackspace</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="headerstrip"><nav class="navstrip"><div class="left"><a id="mini_logo" href="/login"><img src="//127.0.0.1:5000/static/images/hackspace.png" class="mini-logo"></a><span class="mini-logo-text">Maidstone Hackspace</span></div><div class="social"><div class="btn"><a href="https://twitter.com/share" class="twitter-share-button" data-via="http://maidstone-hackspace.org.uk/">Tweet</a></div><div class="btn"><div class="fb-share-button" data-href="http://maidstone-hackspace.org.uk/" data-layout="button_count"></div></div><div class="btn"><script type="IN/Share" data-url="http://maidstone-hackspace.org.uk/" data-counter="right"></script></div><div class="btn"><div size="standard" class="g-plusone" data-href="http://maidstone-hackspace.org.uk/" data-size="medium" data-annotation="bubble" count="true"></div></div></div></nav></div>
|
||||
<nav id="leftNav" class="menu" >
|
||||
<div id="headerstrip" class="row"><nav class="navstrip"><div class="navstripleft col s6"><a id="mini_logo" href="/login"><img src="//http://127.0.0.1/static/images/hackspace.png" class="mini-logo"></a><span class="mini-logo-text">Maidstone Hackspace</span></div><div class="col s6 offset-s8 social"><div class="socbtn"><a href="https://twitter.com/share" class="twitter-share-button" data-via="https://maidstone-hackspace.org.uk/" data-hashtags="mhackspace">Tweet</a></div><div class="socbtn"><div class="fb-share-button" data-href="https://maidstone-hackspace.org.uk/" data-layout="button_count"></div></div><div class="socbtn"><script type="IN/Share" data-url="https://maidstone-hackspace.org.uk/" data-counter="right"></script></div><div class="socbtn"><div size="standard" class="g-plusone" data-href="https://maidstone-hackspace.org.uk/" data-size="medium" data-annotation="bubble" count="true"></div></div></div></nav></div>
|
||||
<div id="menubar" class="row" ><nav class="col s10 offset-s1" >
|
||||
<ul>
|
||||
<li class="active mi0"><a href="/" >Home</a></li>
|
||||
<li class="mi1"><a href="/chat" >Chat</a></li>
|
||||
<li class="mi2"><a href="/donate" >Donate</a></li>
|
||||
<li class="mi3"><a href="#mailing-list-signup" >Contact</a></li>
|
||||
<li class="mi4"><a href="/login" >login</a></li>
|
||||
<li class="mi3"><a href="/contact-us" >Contact</a></li>
|
||||
<li class="mi4"><a href="/mailing-list" >Group</a></li>
|
||||
<li class="mi5"><a href="/login" >Login</a></li>
|
||||
</ul>
|
||||
<div style="clear:both;"></div>
|
||||
</nav>
|
||||
<div class="page" >
|
||||
</nav></div>
|
||||
<div class="row"><div class="page col s10 offset-s1" >
|
||||
<header class="pageHeader">
|
||||
Make a donation</header>
|
||||
<section class="pageSection">
|
||||
<section class="pageSection col s12">
|
||||
<p>If you would like to donate to the space please type an amount and use the reference code for what ever your donating for, for example use #lair to donate to getting a space.
|
||||
We may run pledges in the future for equipment in which case use the reference for the equipment your pledging towards.</p></section>
|
||||
<section class="pageSection">
|
||||
<p>Currently raised £5.00 towards #lair target is £1000.00.</p><form action="/donate/submit" method="post" ><fieldset><legend>Donate to Maidstone Hackspace</legend><p><label for="reference">Reference<select name="reference"><option value="#lair" selected="selected">#lair</option></select></label></p><p><label for="amount">Donation Amount<input type="text" name="amount" placeholder="50.00" value="50.00"></label></p><p class="bottom full_width"><button type="submit">submit</button></p></fieldset></form></section>
|
||||
<footer class="pageFooter">
|
||||
We may run pledges in the future for equipment in which case use the reference for the equipment your pledging towards.</p><form action="/donate/submit" method="post" ><fieldset><legend>Donate to Maidstone Hackspace</legend><p><label for="provider">GoCardless<input type="radio" name="provider" placeholder="gocardless" value="gocardless" checked="checked"></label></p><p><label for="provider">PayPal<input type="radio" name="provider" placeholder="" value="paypal"></label></p><p><label for="reference">Reference<select name="reference"><option value="#lair" selected="selected">#lair</option></select></label></p><p><label for="amount">Donation Amount<input type="text" name="amount" placeholder="50.00" value="50.00"></label></p><p class="bottom full_width"><button type="submit">submit</button></p></fieldset></form></section>
|
||||
<footer class="pageFooter col s12">
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<div id="footer"><div id="footertop"></div><div id="footerbottom"><div class="container"><div class="copyright">©2016 Maidstone Hackspace</div><div mailing-list-signup class="google-groups-signup"><h3>Signup and make yourself known</h3><form class="block" name="signup" method="get" action="http://groups.google.com/group/maidstone-hackspace/boxsubscribe"><label for="groups-email">Email Address</label><input id="groups-email" name="email" class="required"/><button type="submit" />Subscribe</button><a href="http://groups.google.com/group/maidstone-hackspace">Browse Archives</a></form><div style="clear:both;"></div><div></div></div><div>
|
||||
</div></div>
|
||||
<div id="footer"><div id="footertop"></div><div id="footerbottom"><div class="container"><div class="copyright">©2016 Maidstone Hackspace</div><div mailing-list-signup class="google-groups-signup"><h3>Signup and make yourself known</h3><form class="block" name="signup" method="get" action="https://groups.google.com/group/maidstone-hackspace/boxsubscribe"><label for="groups-email">Email Address</label><input id="groups-email" name="email" class="required"/><button type="submit" />Subscribe</button><a href="http://groups.google.com/group/maidstone-hackspace">View Group</a></form><div style="clear:both;"></div><div></div></div><div>
|
||||
<!--google analytics-->
|
||||
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
|
||||
|
||||
<script><!--//--><![CDATA[//><!--!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'http://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
|
||||
//]]></script>
|
||||
|
||||
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
|
||||
|
||||
<script src="//platform.linkedin.com/in.js" type="text/javascript"> lang: en_US</script>
|
||||
|
||||
|
@ -51,29 +51,6 @@
|
|||
//facebook share
|
||||
(function(d, s, id) {var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) return;js = d.createElement(s); js.id = id;js.src = "//connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v2.3";fjs.parentNode.insertBefore(js, fjs);}(document, 'script', 'facebook-jssdk'));
|
||||
//]]></script><script type="text/javascript" ><!--//--><![CDATA[//><!--
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#mini_logo').on("click", function(e){
|
||||
e.preventDefault();
|
||||
$('#member_navigation').toggle();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
|
||||
ga('create', 'UA-63373181-1', 'maidstone-hackspace.org.uk');
|
||||
|
||||
ga('send', 'pageview');
|
||||
|
||||
var app = angular.module('myApp', ['ngAnimate']);
|
||||
|
||||
app.controller('sliderController', function($scope, $interval) {
|
||||
|
@ -116,6 +93,29 @@ app.controller('sliderController', function($scope, $interval) {
|
|||
|
||||
});
|
||||
|
||||
|
||||
|
||||
$(document).ready(function(){
|
||||
$('#mini_logo').on("click", function(e){
|
||||
e.preventDefault();
|
||||
$('#member_navigation').toggle();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
|
||||
ga('create', 'UA-63373181-1', 'maidstone-hackspace.org.uk');
|
||||
|
||||
ga('send', 'pageview');
|
||||
//]]>
|
||||
</script>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 945 B After Width: | Height: | Size: 945 B |
Before Width: | Height: | Size: 1003 B After Width: | Height: | Size: 1003 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 983 B |
Before Width: | Height: | Size: 983 B After Width: | Height: | Size: 983 B |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 236 KiB |
After Width: | Height: | Size: 559 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
0
website/static/images/competitions/screw_sorting_competition_banner.jpg
Normal file → Executable file
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 256 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |