#5: Started work on roles switching

This commit is contained in:
simon 2017-04-01 15:11:50 +01:00
parent 68bb22bd31
commit e425c56ec2
14 changed files with 661 additions and 19 deletions

View file

@ -0,0 +1,218 @@
# Database Specification
Note that this is a work in progress. Read it in concert with the Entity-Relationship Diagram.
Tables are listed in alphabetical order.
## Address
The postal address of a dwelling at which electors are registered.
CREATE TABLE IF NOT EXISTS addresses (
id integer NOT NULL,
address character varying(256) NOT NULL,
postcode character varying(16),
phone character varying(16),
district_id integer,
latitude real,
longitude real
);
## Authority
An *oauth* authority which authenticates canvassers. *Note that* there will need to be substantially more in this table but I don't yet know what.
CREATE TABLE IF NOT EXISTS authorities (
id character varying(32) NOT NULL
);
## Canvasser
A user of the system.
CREATE TABLE IF NOT EXISTS canvassers (
id serial,
username character varying(32) NOT NULL,
fullname character varying(64) NOT NULL,
elector_id integer,
address_id integer NOT NULL,
phone character varying(16),
email character varying(128),
authority_id character varying(32) NOT NULL,
authorised boolean
);
## District
An electoral district.
CREATE TABLE IF NOT EXISTS districts (
id integer NOT NULL,
name character varying(64) NOT NULL
);
## Elector
Someone entitled to cast a vote in the referendum.
CREATE TABLE IF NOT EXISTS electors (
id integer NOT NULL,
name character varying(64) NOT NULL,
address_id integer NOT NULL,
phone character varying(16),
email character varying(128)
);
## Followup Action
An action performed by an issue expert in response to a followup request.
CREATE TABLE IF NOT EXISTS followupactions (
id integer NOT NULL,
request_id integer NOT NULL,
actor integer NOT NULL,
date timestamp with time zone DEFAULT now() NOT NULL,
notes text,
closed boolean
);
## Followup Method
A method for responding to a followup request; reference data.
CREATE TABLE IF NOT EXISTS followupmethods (
id character varying(32) NOT NULL
);
insert into followupmethods values ('Telephone');
insert into followupmethods values ('eMail');
insert into followupmethods values ('Post');
## Followup Request
A request recorded by a canvasser for an issue expert to contact an elector with regard to a particular issue.
CREATE TABLE IF NOT EXISTS followuprequests (
id integer NOT NULL,
elector_id integer NOT NULL,
visit_id integer NOT NULL,
issue_id character varying(32) NOT NULL,
method_id character varying(32) NOT NULL
);
## Intention
An intention, by an elector, to vote for an option; captured by a canvasser during a visit.
CREATE TABLE IF NOT EXISTS intentions (
id serial not null,
elector integer not null references elector(id),
option varchar(32) not null references option(id),
visit integer not null references visit(id),
date timestamp with time zone DEFAULT now() NOT NULL
);
## Issue
An issue which might affect electors' decisions regarding their intention.
CREATE TABLE IF NOT EXISTS issues (
id character varying(32) NOT NULL,
url character varying(256),
content varchar(1024),
current default false
);
## Issue expertise
Expertise of a canvasser able to use a method, in an issue.
CREATE TABLE IF NOT EXISTS issueexpertise (
canvasser_id integer NOT NULL,
issue_id character varying(32) NOT NULL,
method_id character varying(32) NOT NULL
);
## Option
An option for which an elector may have an intention to vote.
CREATE TABLE IF NOT EXISTS options (
id character varying(32) NOT NULL
);
## Role
A role (other than basic *Canvasser*) that a user may have in the system. Reference data.
create table if not exists roles (
id serial primary key,
name varchar(64) not null
);
## Role Member
Membership of a user (*Canvasser*) of an additional role; link table.
create table if not exists rolememberships (
role_id integer not null references roles(id),
canvasser_id integer not null references canvassers(id)
);
## Team
A team of canvassers in a locality who are known to one another and frequently
canvas together.
create table if not exists teams (
id serial primary key,
name varchar(64) not null,
district_id integer not null references districts(id),
latitude real,
longitude real
);
## Team Member
Membership of a user (*Canvasser*) of a particular team. Canvassers may join multiple teams. Link table.
create table if not exists teammemberships (
team_id integer not null references teams(id),
canvasser_id integer not null references canvassers(id)
);
## Team Organiser
A relationship which defines a user (*Canvasser*) as an organiser of a team. A team may
have more than one organiser. An organiser (if they also have the role 'Recruiter', which
they often will have) may recruit additional Canvassers as members of their team, or
accept applications by canvassers to join their team. An organiser may promote a member of
the team to organiser of the team, and may also exclude a member from the team.
create table if not exists teamorganiserships (
team_id integer not null references teams(id),
canvasser_id integer not null references canvassers(id)
);
## Visit
A visit by a canvasser to an address on a date to solicit intentions from electors.
CREATE TABLE IF NOT EXISTS visits (
id integer NOT NULL,
address_id integer NOT NULL,
canvasser_id integer NOT NULL,
date timestamp with time zone DEFAULT now() NOT NULL
);

View file

@ -25,9 +25,9 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1.979899" inkscape:zoom="2.8"
inkscape:cx="833.70674" inkscape:cx="764.16287"
inkscape:cy="324.89697" inkscape:cy="256.90499"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
@ -58,12 +58,13 @@
id="layer1" id="layer1"
transform="translate(0,-308.26772)"> transform="translate(0,-308.26772)">
<rect <rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#060000;stroke-width:1.324;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.51906158" style="display:none;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#060000;stroke-width:1.324;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.51906158"
id="rect4428" id="matte"
width="1030" width="1030"
height="730" height="730"
x="232.23355" x="8.484766"
y="376.0018" /> y="312.36221"
sodipodi:insensitive="true" />
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:20px;line-height:125%;font-family:Arial;-inkscape-font-specification:'Arial Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:20px;line-height:125%;font-family:Arial;-inkscape-font-specification:'Arial Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
@ -124,7 +125,7 @@
y="563.88513" y="563.88513"
x="230.18532" x="230.18532"
id="tspan4156" id="tspan4156"
sodipodi:role="line">Addresss</tspan></text> sodipodi:role="line">Address</tspan></text>
<rect <rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.4000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.4000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4158" id="rect4158"
@ -566,7 +567,7 @@
sodipodi:nodetypes="ccc" /> sodipodi:nodetypes="ccc" />
<path <path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 222.5,781.65662 -10,10 10,10 0,0" d="m 219.72208,781.65662 -10,10 10,10 0,0"
id="path4347" id="path4347"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /> sodipodi:nodetypes="cccc" />
@ -613,14 +614,14 @@
y="394.48404" y="394.48404"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;font-family:Arial;-inkscape-font-specification:Arial"><tspan style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;font-family:Arial;-inkscape-font-specification:Arial"><tspan
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Arial;-inkscape-font-specification:'Arial Bold'" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Arial;-inkscape-font-specification:'Arial Bold'"
id="tspan4371">Version: </tspan>0.2</tspan><tspan id="tspan4371">Version: </tspan>0.3</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="472.0152" x="472.0152"
y="413.23404" y="413.23404"
id="tspan4365" id="tspan4365"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;font-family:Arial;-inkscape-font-specification:Arial"><tspan style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;font-family:Arial;-inkscape-font-specification:Arial"><tspan
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Arial;-inkscape-font-specification:'Arial Bold'" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Arial;-inkscape-font-specification:'Arial Bold'"
id="tspan4373">Date: </tspan>20170315</tspan><tspan id="tspan4373">Date: </tspan>20170401</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="472.0152" x="472.0152"
y="431.98404" y="431.98404"
@ -1159,5 +1160,49 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
</g> </g>
</g> </g>
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.4000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4338"
width="100"
height="60"
x="42.398472"
y="896.52991" />
<text
sodipodi:linespacing="125%"
id="text4341"
y="926.52985"
x="54.166237"
style="font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:20px;line-height:125%;font-family:'URW Chancery L';-inkscape-font-specification:'URW Chancery L Bold Italic';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;font-family:Arial;-inkscape-font-specification:Arial"
y="926.52985"
x="54.166237"
id="tspan4343"
sodipodi:role="line">Followup</tspan><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;font-family:Arial;-inkscape-font-specification:Arial"
y="945.27985"
x="54.166237"
sodipodi:role="line"
id="tspan4345">Method</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 120,897.36221 0,-80 100,0"
id="path4348"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 220,807.36221 -10,10 10,10"
id="path4350"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 110,887.36221 20,0"
id="path4352"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path4354"
d="m 900,792.1255 -10,10 10,10"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View file

@ -0,0 +1,58 @@
-- We don't explicitly instantiate the 'Canvasser' role since every user is
-- deemed to be a canvasser.
-- an 'Expert' is someone with expertise in one or more issues, who is
-- trusted to discuss those issues in detail with electors.
insert into roles (name) values ('Expert');
-- an 'Administrator' is someone entitled to broadly alter reference data
-- throughout the system.
insert into roles (name) values ('Administrator');
-- a 'Recruiter' is someone entitled to invite other people to become users
-- ('Canvassers'). A Recruiter is entitled to lock the account of anyone they
-- have recruited, recursively.
insert into roles (name) values ('Recruiter');
-- an 'Organiser' is someone who organises one or more local teams. An Organiser
-- is entitled to exclude any Canvasser from any team they organise.
insert into roles (name) values ('Organiser');
-- an 'Editor' is someone entitled to add and edit issues.
insert into roles (name) values ('Editor');
-- issue text is local; there may still in addition be a further link to more
-- information, but the basic issue text should be part of the issue record.
-- The text should fit on a phone screen without scrolling, so is reasonably
-- short.
alter table issues add column content varchar(1024);
-- an issue may be current or not current; when not current it is not deleted
-- from the system but kept because it may become current again later. Only
-- current issues are shown in the app. Typically not fewer than three and not
-- more than about seven issues should be current at any time.
alter table issues add column current default false;
insert into issues (id, content, current) values ('Currency',
'Scotland could keep the Pound, or use the Euro. But we could also set up a new currency of our own.',
true);
insert into issues (id, content, current) values ('Monarchy',
'Scotland could keep the Queen. This is an issue to be decided after independence.',
true);
insert into issues (id, content, current) values ('Defence',
'Scotland will not have nuclear weapons, and will probably not choose to engage in far-off wars. But we could remain members of NATO.',
true);
insert into options (id) values ('Yes');
insert into options (id) values ('No');

View file

@ -19,3 +19,4 @@ WHERE id = :id
-- :doc delete a user given the id -- :doc delete a user given the id
DELETE FROM users DELETE FROM users
WHERE id = :id WHERE id = :id

View file

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/yyy-static.css" />
<link rel="stylesheet" type="text/css" href="css/spinner.css" />
<link href="https://fonts.googleapis.com/css?family=Archivo+Black|Archivo+Narrow" rel="stylesheet"/>
<title>{% block title %}{% endblock %}{{title}}</title>
</head>
<body>
<header>
<div id="canvasser">
You are logged in as {{username}}
</div>
<div id="nav">
<img id="nav-icon" src="img/threelines.png" alt="Menu"/>
<menu id="nav-menu" class="nav">
<li class=""><a href="index.html">Home</a></li>
<li class=""><a href="library.html">Library</a></li>
<li class=""><a href="register.html">Register</a></li>
<li class=""><a href="login.html">Login</a></li>
<li class=""><a href="about.html">About</a></li>
</menu>
</div>
<h1>
{% block title %}
{% endblock %}
{{title}}
</h1>
</header>
<div id="main-container" class="container">
<div id="big-links">
{% block big-links %}
{% endblock %}
</div>
<div if="#content">
{{content}}
</div>
<div id="back-link-container">
<a href="javascript:history.back()" id="back-link">Back</a>
</div>
<div id="logout-link-container">
<a href="logout" id="back-link">Logout</a>
</div>
</div>
<footer>
<div id="credits">
<div>
<img src="img/ric-logo.png" width="24" height="24"/>
A project of the
<a href="https://radical.scot/">Radical Independence Campaign</a> ||
Version {{version}}
</div>
<div>
<img height="16" width="16" alt="Clojure" src="img/luminus-logo.png"/>Built with <a href="http://www.luminusweb.net/">LuminusWeb</a> ||
<img height="16" width="16" alt="Clojure" src="img/clojure-icon.gif"/> Powered by <a href="http://clojure.org">Clojure</a> ||
<img height="16" width="16" alt="GitHub" src="img/github-logo-transparent.png"/>Find me/fork me on <a href="https://github.com/simon-brooke/smeagol">Github</a> ||
<img height="16" width="16" alt="Free Software Foundation" src="img/gnu.small.png"/>Licensed under the <a href="http://www.gnu.org/licenses/gpl-2.0.html">GNU General Public License version 2.0</a>
</div>
</div>
</footer>
<script type="text/javascript">
var context = "{{servlet-context}}";
var csrfToken = "{{csrf-token}}";
</script>
</body>
</html>

View file

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/yyy-common.css" />
<link rel="stylesheet" type="text/css" href="css/yyy-site.css" />
<link href="https://fonts.googleapis.com/css?family=Archivo+Black|Archivo+Narrow" rel="stylesheet"/>
<title>{% block title %}{% endblock %}{{title}}</title>
</head>
<body>
<header>
<div id="nav">
<img id="nav-icon" src="img/threelines.png" alt="Menu"/>
<menu id="nav-menu" class="nav">
<li class=""><a href="home">Home</a></li>
<li class=""><a href="auth">Login</a></li>
<li class=""><a href="about">About</a></li>
</menu>
</div>
<h1>
{{title}}
</h1>
</header>
<div id="main-container" class="container">
<div id="big-links">
{% block big-links %}
{% endblock %}
</div>
<div if="#content">
{% block content %}
{% endblock %}
</div>
</div>
<footer>
<div id="credits">
<div>
<img src="img/ric-logo.png" width="24" height="24"/>
A project of the
<a href="https://radical.scot/">Radical Independence Campaign</a> ||
Version {{version}}
</div>
<div>
<img height="16" width="16" alt="Clojure" src="img/luminus-logo.png"/>Built with <a href="http://www.luminusweb.net/">LuminusWeb</a> ||
<img height="16" width="16" alt="Clojure" src="img/clojure-icon.gif"/> Powered by <a href="http://clojure.org">Clojure</a> ||
<img height="16" width="16" alt="GitHub" src="img/github-logo-transparent.png"/>Find me/fork me on <a href="https://github.com/simon-brooke/smeagol">Github</a> ||
<img height="16" width="16" alt="Free Software Foundation" src="img/gnu.small.png"/>Licensed under the <a href="http://www.gnu.org/licenses/gpl-2.0.html">GNU General Public License version 2.0</a>
</div>
</div>
</footer>
<script type="text/javascript">
var context = "{{servlet-context}}";
var csrfToken = "{{csrf-token}}";
</script>
</body>
</html>

View file

@ -0,0 +1,13 @@
{% extends "base-authenticated.html" %}
{% block title %}
{% endblock %}
{% block big-links %}
<div class="big-link-container">
<a href="app" class="big-link" id="big-link">Canvasser</a>
</div>
{% for role in roles %}
<div class="big-link-container">
<a href="{{role}}" class="big-link" id="big-link">{{role}}</a>
</div>
{% endfor %}
{% endblock %}

View file

@ -15,8 +15,12 @@
Timestamp Timestamp
PreparedStatement])) PreparedStatement]))
;; TODO: I am CERTANLY misunderstanding something here. We ought to be getting
;; the database connection string and credentials fomr profiles.clj
;; (def ^:dynamic *db* {:name "java:comp/env/jdbc/EmployeeDB"})
(defstate ^:dynamic *db* (defstate ^:dynamic *db*
:start (conman/connect! {:jdbc-url (env :database-url)}) :start (conman/connect! {:jdbc-url (env :database-url)
:driver-class-name "org.postgresql.Driver"})
:stop (conman/disconnect! *db*)) :stop (conman/disconnect! *db*))
(conman/bind-connection *db* "sql/queries.sql") (conman/bind-connection *db* "sql/queries.sql")

View file

@ -10,6 +10,29 @@
[clojure.tools.logging :as log] [clojure.tools.logging :as log]
[youyesyet.config :refer [env]])) [youyesyet.config :refer [env]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.handler: handlers for starting and stopping the webapp.
;;;;
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License
;;;; as published by the Free Software Foundation; either version 2
;;;; of the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;;;; USA.
;;;;
;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(mount/defstate init-app (mount/defstate init-app
:start ((or (:init defaults) identity)) :start ((or (:init defaults) identity))
:stop ((or (:stop defaults) identity))) :stop ((or (:stop defaults) identity)))

View file

@ -0,0 +1,35 @@
(ns youyesyet.routes.authenticated
(:require [clojure.walk :refer [keywordize-keys]]
[noir.response :as nresponse]
[noir.util.route :as route]
[youyesyet.layout :as layout]
[youyesyet.db.core :as db-core]
[compojure.core :refer [defroutes GET POST]]
[ring.util.http-response :as response]
[clojure.java.io :as io]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.routes.authenticated: routes and pages for authenticated users.
;;;;
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License
;;;; as published by the Free Software Foundation; either version 2
;;;; of the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;;;; USA.
;;;;
;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (defn roles-page [request]
;; (if

View file

@ -1,15 +1,81 @@
(ns youyesyet.routes.home (ns youyesyet.routes.home
(:require [youyesyet.layout :as layout] (:require [clojure.walk :refer [keywordize-keys]]
[noir.response :as nresponse]
[noir.util.route :as route]
[youyesyet.layout :as layout]
[youyesyet.db.core :as db-core] [youyesyet.db.core :as db-core]
[compojure.core :refer [defroutes GET]] [compojure.core :refer [defroutes GET POST]]
[ring.util.http-response :as response] [ring.util.http-response :as response]
[clojure.java.io :as io])) [clojure.java.io :as io]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.routes.home: routes and pages for unauthenticated users.
;;;;
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License
;;;; as published by the Free Software Foundation; either version 2
;;;; of the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;;;; USA.
;;;;
;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn app-page []
(layout/render "app.html"))
(defn about-page []
(layout/render "about.html"))
(defn call-me-page [request]
(if
request
(do
;; do something to store it in the database
(layout/render "call-me-accepted.html" (:params request)))
(layout/render "call-me.html"
{:title "Please call me!"
;; TODO: Issues need to be fetched from the database
:concerns nil})))
(defn home-page [] (defn home-page []
(layout/render "home.html")) (layout/render "home.html" {:title "You Yes Yet?"}))
(defn login-page
"This is very temporary. We're going to do authentication by oauth."
[request]
(let [params (keywordize-keys (:form-params request))
session (:session request)
username (:username params)
password (:password params)
redirect-to (or (:redirect-to params) "app")]
(if
(and (= username "test") (= password "test"))
(do
(assoc (response/found redirect-to) :session (assoc session :user username)))
(layout/render "login.html" {:title "Please log in" :redirect-to redirect-to}))))
(defroutes home-routes (defroutes home-routes
(GET "/" [] (home-page)) (GET "/" [] (home-page))
(GET "/docs" [] (-> (response/ok (-> "docs/docs.md" io/resource slurp)) (GET "/home" [] (home-page))
(response/header "Content-Type" "text/plain; charset=utf-8")))) (GET "/about" [] (about-page))
(GET "/app" [] (route/restricted (app-page)))
(GET "/call-me" [] (call-me-page nil))
(POST "/call-me" request (call-me-page request))
(GET "/auth" request (login-page request))
(POST "/auth" request (login-page request))
(GET "/notyet" [] (layout/render "notyet.html"
{:title "Can we persuade you?"}))
(GET "/supporter" [] (layout/render "supporter.html"
{:title "Have you signed up as a canvasser yet?"})))

View file

@ -1,3 +1,26 @@
(ns youyesyet.validation (ns youyesyet.validation
(:require [bouncer.core :as b] (:require [bouncer.core :as b]
[bouncer.validators :as v])) [bouncer.validators :as v]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.validation:
;;;;
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License
;;;; as published by the Free Software Foundation; either version 2
;;;; of the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;;;; USA.
;;;;
;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -1,6 +1,30 @@
(ns youyesyet.ajax (ns youyesyet.ajax
(:require [ajax.core :as ajax])) (:require [ajax.core :as ajax]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; youyesyet.ajax: transciever for ajax packets.
;;;;
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License
;;;; as published by the Free Software Foundation; either version 2
;;;; of the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
;;;; USA.
;;;;
;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign
;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn local-uri? [{:keys [uri]}] (defn local-uri? [{:keys [uri]}]
(not (re-find #"^\w+?://" uri))) (not (re-find #"^\w+?://" uri)))