summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2016-02-12 01:09:01 -0600
committerMichael Merickel <michael@merickel.org>2016-02-12 01:09:01 -0600
commite6e4f655f2abe8d1d5ff63ecd70255094af6de73 (patch)
tree9b8042ee5be832787005f008c0daacf5ba59ea6c
parent81e5989ed5b2bd7ea1a2b843dea9726b253b38ce (diff)
downloadpyramid-e6e4f655f2abe8d1d5ff63ecd70255094af6de73.tar.gz
pyramid-e6e4f655f2abe8d1d5ff63ecd70255094af6de73.tar.bz2
pyramid-e6e4f655f2abe8d1d5ff63ecd70255094af6de73.zip
let's go ahead and bite off more than we can chew by adding object-security
we'll allow anyone to create pages, not just editors finally we'll allow page creators of pages to edit their pages even if they are not editors
-rw-r--r--docs/tutorials/wiki2/definingmodels.rst65
-rw-r--r--docs/tutorials/wiki2/design.rst82
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py6
3 files changed, 94 insertions, 59 deletions
diff --git a/docs/tutorials/wiki2/definingmodels.rst b/docs/tutorials/wiki2/definingmodels.rst
index b90bf77e6..5af8110da 100644
--- a/docs/tutorials/wiki2/definingmodels.rst
+++ b/docs/tutorials/wiki2/definingmodels.rst
@@ -106,28 +106,49 @@ made to both the models.py file and to the initializedb.py file. See
Success will look something like this::
- 2015-05-24 15:34:14,542 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
- 2015-05-24 15:34:14,542 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
- 2015-05-24 15:34:14,543 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
- 2015-05-24 15:34:14,543 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
- 2015-05-24 15:34:14,543 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("pages")
- 2015-05-24 15:34:14,544 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
- 2015-05-24 15:34:14,544 INFO [sqlalchemy.engine.base.Engine:1097][MainThread]
- CREATE TABLE pages (
- id INTEGER NOT NULL,
- name TEXT,
- data TEXT,
- PRIMARY KEY (id),
- UNIQUE (name)
- )
-
-
- 2015-05-24 15:34:14,545 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
- 2015-05-24 15:34:14,546 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
- 2015-05-24 15:34:14,548 INFO [sqlalchemy.engine.base.Engine:646][MainThread] BEGIN (implicit)
- 2015-05-24 15:34:14,549 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO pages (name, data) VALUES (?, ?)
- 2015-05-24 15:34:14,549 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ('FrontPage', 'This is the front page')
- 2015-05-24 15:34:14,550 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
+ 2016-02-12 01:06:35,855 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
+ 2016-02-12 01:06:35,855 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
+ 2016-02-12 01:06:35,855 INFO [sqlalchemy.engine.base.Engine:1192][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
+ 2016-02-12 01:06:35,855 INFO [sqlalchemy.engine.base.Engine:1193][MainThread] ()
+ 2016-02-12 01:06:35,856 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("pages")
+ 2016-02-12 01:06:35,856 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
+ 2016-02-12 01:06:35,856 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] PRAGMA table_info("users")
+ 2016-02-12 01:06:35,856 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
+ 2016-02-12 01:06:35,857 INFO [sqlalchemy.engine.base.Engine:1097][MainThread]
+ CREATE TABLE users (
+ id INTEGER NOT NULL,
+ name TEXT NOT NULL,
+ role TEXT NOT NULL,
+ password_hash TEXT,
+ CONSTRAINT pk_users PRIMARY KEY (id),
+ CONSTRAINT uq_users_name UNIQUE (name)
+ )
+
+
+ 2016-02-12 01:06:35,857 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
+ 2016-02-12 01:06:35,858 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
+ 2016-02-12 01:06:35,858 INFO [sqlalchemy.engine.base.Engine:1097][MainThread]
+ CREATE TABLE pages (
+ id INTEGER NOT NULL,
+ name TEXT NOT NULL,
+ data INTEGER NOT NULL,
+ creator_id INTEGER NOT NULL,
+ CONSTRAINT pk_pages PRIMARY KEY (id),
+ CONSTRAINT uq_pages_name UNIQUE (name),
+ CONSTRAINT fk_pages_creator_id_users FOREIGN KEY(creator_id) REFERENCES users (id)
+ )
+
+
+ 2016-02-12 01:06:35,859 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ()
+ 2016-02-12 01:06:35,859 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
+ 2016-02-12 01:06:36,383 INFO [sqlalchemy.engine.base.Engine:646][MainThread] BEGIN (implicit)
+ 2016-02-12 01:06:36,384 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
+ 2016-02-12 01:06:36,384 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ('editor', 'editor', '$2b$12$bSr5QR3wFs1LAnld7R94e.TXPj7DVoTxu2hA1kY6rm.Q3cAhD.AQO')
+ 2016-02-12 01:06:36,384 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO users (name, role, password_hash) VALUES (?, ?, ?)
+ 2016-02-12 01:06:36,384 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ('basic', 'basic', '$2b$12$.v0BQK2xWEQOnywbX2BFs.qzXo5Qf9oZohGWux/MOSj6Z.pVaY2Z6')
+ 2016-02-12 01:06:36,385 INFO [sqlalchemy.engine.base.Engine:1097][MainThread] INSERT INTO pages (name, data, creator_id) VALUES (?, ?, ?)
+ 2016-02-12 01:06:36,385 INFO [sqlalchemy.engine.base.Engine:1100][MainThread] ('FrontPage', 'This is the front page', 1)
+ 2016-02-12 01:06:36,385 INFO [sqlalchemy.engine.base.Engine:686][MainThread] COMMIT
View the application in a browser
---------------------------------
diff --git a/docs/tutorials/wiki2/design.rst b/docs/tutorials/wiki2/design.rst
index 8e3bb4c13..42f06f7bf 100644
--- a/docs/tutorials/wiki2/design.rst
+++ b/docs/tutorials/wiki2/design.rst
@@ -19,11 +19,17 @@ Models
We'll be using an SQLite database to hold our wiki data, and we'll be using
:term:`SQLAlchemy` to access the data in this database.
-Within the database, we define a single table named `pages`, whose elements
-will store the wiki pages. There are two columns: `name` and `data`.
+Within the database, we will define two tables:
-URLs like ``/PageName`` will try to find an element in the table that has a
-corresponding name.
+- The `users` table which will store the `name`, `password_hash` and `role`.
+- The `pages` table, whose elements will store the wiki pages.
+ There are three columns: `name`, `data` and `creator_id`.
+
+There is a one-to-many relationship between `users` and `pages` tracking
+the user who created each wiki page.
+
+URLs like ``/PageName`` will try to find an element in the `pages` table that
+has a corresponding name.
To add a page to the wiki, a new row is created and the text is stored in
`data`.
@@ -32,8 +38,8 @@ A page named ``FrontPage`` containing the text *This is the front page*, will
be created when the storage is initialized, and will be used as the wiki home
page.
-Views
------
+Wiki Views
+----------
There will be three views to handle the normal operations of adding, editing,
and viewing wiki pages, plus one view for the wiki front page. Two templates
@@ -47,33 +53,41 @@ templates.
Security
--------
-We'll eventually be adding security to our application. The components we'll
-use to do this are below.
-
-- USERS, a dictionary mapping :term:`userids <userid>` to their corresponding
- passwords.
-
-- GROUPS, a dictionary mapping :term:`userids <userid>` to a list of groups to
- which they belong.
-
-- ``groupfinder``, an *authorization callback* that looks up USERS and GROUPS.
- It will be provided in a new ``security/default.py`` subpackage and file.
-
-- An :term:`ACL` is attached to the root :term:`resource`. Each row below
- details an :term:`ACE`:
-
- +----------+----------------+----------------+
- | Action | Principal | Permission |
- +==========+================+================+
- | Allow | Everyone | View |
- +----------+----------------+----------------+
- | Allow | group:editors | Edit |
- +----------+----------------+----------------+
-
-- Permission declarations are added to the views to assert the security
- policies as each request is handled.
-
-Two additional views and one template will handle the login and logout tasks.
+We'll eventually be adding security to our application. To do this, we'll
+be using a very simple role-based security model. We'll assign a single
+role category to each user in our system.
+
+`basic`
+ An authenticated user who can view content and create new pages. A `basic`
+ user may also edit the pages they have created but not pages created by
+ other users.
+
+`editor`
+ An authenticated user who can create and edit any content in the system.
+
+In order to accomplish this we'll need to define an authentication policy
+which can identify users by their :term:`userid` and role. Then we'll
+need to define a page :term:`resource` which contains the appropriate
+:term:`ACL`:
+
++----------+--------------------+----------------+
+| Action | Principal | Permission |
++==========+====================+================+
+| Allow | Everyone | view |
++----------+--------------------+----------------+
+| Allow | group:basic | create |
++----------+--------------------+----------------+
+| Allow | group:editors | edit |
++----------+--------------------+----------------+
+| Allow | <creator of page> | edit |
++----------+--------------------+----------------+
+
+Permission declarations will be added to the views to assert the security
+policies as each request is handled.
+
+On the security side of the application there are two additional views for
+handling login and logout as well as two exception views for handling
+invalid access attempts and unhandled URLs.
Summary
-------
@@ -102,7 +116,7 @@ in the following table:
| | submitted, redirect | | | |
| | to /PageName | | | |
+----------------------+-----------------------+-------------+----------------+------------+
-| /add_page/PageName | Create the page | add_page | edit.jinja2 | edit |
+| /add_page/PageName | Create the page | add_page | edit.jinja2 | create |
| | *PageName* in | | | |
| | storage, display | | | |
| | the edit form | | | |
diff --git a/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
index 175b7190f..f3c0a6fef 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
@@ -45,9 +45,9 @@ def main(argv=sys.argv):
editor.set_password('editor')
dbsession.add(editor)
- viewer = User(name='viewer', role='viewer')
- viewer.set_password('viewer')
- dbsession.add(viewer)
+ basic = User(name='basic', role='basic')
+ basic.set_password('basic')
+ dbsession.add(basic)
page = Page(
name='FrontPage',