#5: Started work on roles switching
This commit is contained in:
parent
68bb22bd31
commit
e425c56ec2
218
doc/specification/database.md
Normal file
218
doc/specification/database.md
Normal 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
|
||||||
|
);
|
|
@ -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 |
|
@ -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');
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
74
resources/templates/base-authenticated.html
Normal file
74
resources/templates/base-authenticated.html
Normal 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>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
58
resources/templates/base-unauthenticated.html
Normal file
58
resources/templates/base-unauthenticated.html
Normal 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>
|
13
resources/templates/roles.html
Normal file
13
resources/templates/roles.html
Normal 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 %}
|
|
@ -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")
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
35
src/clj/youyesyet/routes/authenticated.clj
Normal file
35
src/clj/youyesyet/routes/authenticated.clj
Normal 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
|
|
@ -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?"})))
|
||||||
|
|
|
@ -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
|
||||||
|
;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue