Browse Source

added a small bcrypt secret to protect edit pages

master
crunk 4 years ago
parent
commit
acc7d0da1a
  1. 33
      library/borrowform.py
  2. 3
      library/csvparser/varlib.csv
  3. 38
      library/page.py
  4. 1
      library/secret
  5. 3
      library/static/css/style.css
  6. 11
      library/static/css/upload.css
  7. 26
      library/templates/publication.html
  8. 8
      library/templates/upload.html
  9. 9
      library/uploadform.py
  10. 1
      requirements.txt

33
library/borrowform.py

@ -0,0 +1,33 @@
"""Form object declaration."""
from flask_wtf import FlaskForm
from wtforms import (
StringField,
SubmitField,
)
from wtforms import validators
from wtforms.validators import Length
class BorrowForm(FlaskForm):
"""Borrow a book form."""
borrowed = StringField(
"Fill in your name if you're going to borrow this publication.",
[
validators.InputRequired(),
Length(
min=3, message="Just so we know who is borrowing this book."
),
],
)
secret = StringField(
"Librarians secret:",
[
validators.InputRequired(),
Length(
min=2, message="Fill in the secret to unlock to library."
),
],
)
submit = SubmitField("Borrow")

3
library/csvparser/varlib.csv

@ -1,6 +1,6 @@
Id,Publication,Author,Year,Custodian,Fields,Type,Publishers,License,LicenseShort,Highlights,Comments,Currently borrowed by Id,Publication,Author,Year,Custodian,Fields,Type,Publishers,License,LicenseShort,Highlights,Comments,Currently borrowed by
1,The Economics of Anarchism,Anarcho,2012,Varia,"Economics, Anarchism",Zine,theanarchistlibrary.org,Anti-copyright,Anti-copyright,"The labourer retains, even after he has recieved his wages, a natural right in the thing he has produced",,No one 1,The Economics of Anarchism,Anarcho,2012,Varia,"Economics, Anarchism",Zine,theanarchistlibrary.org,Anti-copyright,Anti-copyright,"The labourer retains, even after he has recieved his wages, a natural right in the thing he has produced",,No one
2,Identity Politics - An Anthology,The Anarchist Library,,Varia,Identity politics,Zine,Paper Jam Collective,No license mentioned,No license mentioned,,me, 2,Identity Politics - An Anthology,The Anarchist Library,,Varia,Identity politics,Zine,Paper Jam Collective,No license mentioned,No license mentioned,,me,Danny
3,The mythology of work,CrimeThinc.com,,Varia,"Work, Anticapitalism",Zine,CrimeThinc.com,No license mentioned,No license mentioned,,"A selection from 'Work', a 376-page analysis of contemporary capitalism", 3,The mythology of work,CrimeThinc.com,,Varia,"Work, Anticapitalism",Zine,CrimeThinc.com,No license mentioned,No license mentioned,,"A selection from 'Work', a 376-page analysis of contemporary capitalism",
4,Forget Shorter Showers - Why Personal Change Does Not Equal Political Change,Derrick Jensen,2009,Varia,Environmental justice,Zine,,No license mentioned,No license mentioned,Green consumerism isn't enough.,, 4,Forget Shorter Showers - Why Personal Change Does Not Equal Political Change,Derrick Jensen,2009,Varia,Environmental justice,Zine,,No license mentioned,No license mentioned,Green consumerism isn't enough.,,
5,Choreo-Graphic-Hypothesis,"<meta-author=""Joana Chicau"";>",2018,Varia,"Live Coding, Choreography",Paperback,Self published: Joana Chicau,Free Art License 1.3,Free Art License,"Theatrical actions are not necessary to the performance, Avoid if at all possible",, 5,Choreo-Graphic-Hypothesis,"<meta-author=""Joana Chicau"";>",2018,Varia,"Live Coding, Choreography",Paperback,Self published: Joana Chicau,Free Art License 1.3,Free Art License,"Theatrical actions are not necessary to the performance, Avoid if at all possible",,
@ -52,3 +52,4 @@ Id,Publication,Author,Year,Custodian,Fields,Type,Publishers,License,LicenseShort
60,Networks of one's own #1: Etherbox,"Michael Murtaugh, An Mertens, Roel Roscam Abbing, Femke Snelting",2018,Varia,"Networks, Digital Infrastructures, DIY, DIWO, Executable publication, Experimental Publishing, wireless",Paperback,Constant Verlag,Copyleft,Copyleft,,, 60,Networks of one's own #1: Etherbox,"Michael Murtaugh, An Mertens, Roel Roscam Abbing, Femke Snelting",2018,Varia,"Networks, Digital Infrastructures, DIY, DIWO, Executable publication, Experimental Publishing, wireless",Paperback,Constant Verlag,Copyleft,Copyleft,,,
61,Mots de la cage aux ours - woorden uit de berenkuil,Constant,2012,Varia,"words, language, Bruxelles",Softcover,Constant,Copyleft,Copyleft,,, 61,Mots de la cage aux ours - woorden uit de berenkuil,Constant,2012,Varia,"words, language, Bruxelles",Softcover,Constant,Copyleft,Copyleft,,,
62,Snake rituals and switching circuits,Florian Cramer,2009,Danny,"mass communication, personal communication, new media",paperback,Piet Zwart Institute,Creative Commons Attribution-Share Alike 3.0,Creative Commons,The function of a medium is ultimately decided by its users and not by its creators,, 62,Snake rituals and switching circuits,Florian Cramer,2009,Danny,"mass communication, personal communication, new media",paperback,Piet Zwart Institute,Creative Commons Attribution-Share Alike 3.0,Creative Commons,The function of a medium is ultimately decided by its users and not by its creators,,
63,Magium issue 1: On Eating in isolation,Alice Strete,2020,Varia,"food, sharing, personal stories, consumption",zine,Self Published,Free Art License,Free Art License,,,Danny

Can't render this file because it has a wrong number of fields in line 10.

38
library/page.py

@ -5,6 +5,7 @@ import flask
from requests import get from requests import get
from icalendar import Calendar from icalendar import Calendar
import datetime import datetime
import bcrypt
from flask import ( from flask import (
render_template, render_template,
redirect, redirect,
@ -12,6 +13,7 @@ from flask import (
) )
from rnrfeed.rnrfeeder import getevents, getlatestevent from rnrfeed.rnrfeeder import getevents, getlatestevent
from uploadform import PublicationForm from uploadform import PublicationForm
from borrowform import BorrowForm
from csvparser.csvparser import ( from csvparser.csvparser import (
getlicenses, getlicenses,
getpublications, getpublications,
@ -19,6 +21,7 @@ from csvparser.csvparser import (
getyears, getyears,
getfullpublication, getfullpublication,
writepublication, writepublication,
editborrowedby,
) )
from flask_wtf.csrf import CSRFProtect from flask_wtf.csrf import CSRFProtect
@ -50,7 +53,8 @@ def index():
def upload(): def upload():
uploadform = PublicationForm() uploadform = PublicationForm()
if request.method == 'POST': if request.method == 'POST':
if uploadform.validate_on_submit(): if (uploadform.validate_on_submit() and
checksecret(uploadform.secret.data)):
id = writepublication(uploadform) id = writepublication(uploadform)
return redirect(str(id), code=303) return redirect(str(id), code=303)
else: else:
@ -59,12 +63,29 @@ def upload():
return render_template("upload.html", uploadform=uploadform) return render_template("upload.html", uploadform=uploadform)
@APP.route("/<publicationID>") @APP.route("/<publicationID>", methods=["GET", "POST"])
def show_book(publicationID): def show_book(publicationID):
"""route for a publication, still needs to be made""" """route for a publication, still needs to be made"""
fullpublication = getfullpublication(publicationID) fullpublication = getfullpublication(publicationID)
# parse csv, render template with full list. borrowform = BorrowForm()
return render_template("publication.html", fullpublication=fullpublication) if request.method == 'POST':
if (borrowform.validate_on_submit() and
checksecret(borrowform.secret.data)):
editborrowedby(publicationID, borrowform.borrowed.data)
fullpublication["Borrowed"] = borrowform.borrowed.data
return render_template(
"publication.html",
fullpublication=fullpublication,
publicationID=publicationID,
borrowform=borrowform
)
# return a full publication with or without form errors
return render_template(
"publication.html",
fullpublication=fullpublication,
publicationID=publicationID,
borrowform=borrowform
)
@APP.route("/pastevents") @APP.route("/pastevents")
@ -100,6 +121,15 @@ def upcoming_or_latest():
return dict(upcoming=upcoming) return dict(upcoming=upcoming)
def checksecret(secret):
with open("secret") as f:
secrethash = f.readline().rstrip()
if bcrypt.checkpw(secret.encode("utf-8"), secrethash.encode("utf-8")):
return True
else:
return False
if __name__ == "__main__": if __name__ == "__main__":
APP.debug = True APP.debug = True
APP.run(port=5000) APP.run(port=5000)

1
library/secret

@ -0,0 +1 @@
$2b$12$kZC/e1smAiBCntQxLUpsZ.H0Y5VkWG/YLt18wIdGmONtijkXYaVsO

3
library/static/css/style.css

@ -69,6 +69,7 @@ body:after {
#bookshelf > div > a { #bookshelf > div > a {
color: black; color: black;
text-decoration: none;
} }
#publication { #publication {
@ -87,7 +88,7 @@ body:after {
.event { .event {
margin: 0 1em 1em; margin: 0 1em 1em;
max-width: 90%; max-width: calc(90% - 3em);
margin-top: 3em; margin-top: 3em;
padding: 6px; padding: 6px;
display: block; display: block;

11
library/static/css/upload.css

@ -15,7 +15,7 @@
.uploadform-field { .uploadform-field {
margin: 0; margin: 0;
padding: 1em; padding: 1em 0em 1em 0em;
} }
input[type=text], select { input[type=text], select {
@ -25,7 +25,6 @@ input[type=text], select {
margin: 1em 0; margin: 1em 0;
display: inline-block; display: inline-block;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box; box-sizing: border-box;
} }
@ -34,12 +33,16 @@ input[type=submit] {
text-align: right; text-align: right;
color: white; color: white;
padding: 1em 3em; padding: 1em 3em;
margin: 1em 1em;
border: none; border: none;
border-radius: 4px;
cursor: pointer; cursor: pointer;
} }
input[type=submit]:hover { input[type=submit]:hover {
background-color: #404d81; background-color: #404d81;
} }
fieldset{
border:0 none;
padding-top: 0em;
padding-left: 0em;
}

26
library/templates/publication.html

@ -47,8 +47,30 @@
<td><p>{{ fullpublication["Comments"] }}</p></td> <td><p>{{ fullpublication["Comments"] }}</p></td>
</tr> </tr>
<tr> <tr>
<td>Currently borrowed by</td> <td>Currently borrowed by:</td>
<td>No one</td> <td><p>{{ fullpublication["Borrowed"] }}</p></td>
</tr>
<tr>
<td colspan="2">
<form class="borrow" method="POST" action="/{{ publicationID }}">
{{ borrowform.csrf_token }}
<fieldset class="borrowform-field">
{{ borrowform.borrowed.label }}
{{ borrowform.borrowed }}
{% for message in borrowform.borrowed.errors %}
<div class="error">{{ message }}</div>
{% endfor %}
</fieldset>
<fieldset class="borrowform-field">
{{ borrowform.secret.label }}
{{ borrowform.secret }}
{% for message in borrowform.secret.errors %}
<div class="error">{{ message }}</div>
{% endfor %}
</fieldset>
{{ borrowform.submit }}
<form>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

8
library/templates/upload.html

@ -89,6 +89,14 @@
{{ uploadform.borrowed }} {{ uploadform.borrowed }}
</fieldset> </fieldset>
<fieldset class="borrowform-field">
{{ uploadform.secret.label }}
{{ uploadform.secret }}
{% for message in uploadform.secret.errors %}
<div class="error">{{ message }}</div>
{% endfor %}
</fieldset>
{{ uploadform.submit }} {{ uploadform.submit }}
</form> </form>

9
library/uploadform.py

@ -77,4 +77,13 @@ class PublicationForm(FlaskForm):
highlights = TextField("Highlights from the publication:") highlights = TextField("Highlights from the publication:")
comments = TextField("Comments on the publication:") comments = TextField("Comments on the publication:")
borrowed = StringField("Currently borrowed by:") borrowed = StringField("Currently borrowed by:")
secret = StringField(
"Librarians secret:",
[
validators.InputRequired(),
Length(
min=2, message="Fill in the secret to unlock to library."
),
],
)
submit = SubmitField("Submit") submit = SubmitField("Submit")

1
requirements.txt

@ -3,3 +3,4 @@ feedparser
flask flask
flask_wtf flask_wtf
requests requests
bcrypt

Loading…
Cancel
Save