Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
projects:member_portal:home [2025/10/07 22:57] samp20projects:member_portal:home [2025/10/24 00:15] (current) samp20
Line 7: Line 7:
 ===== Architecture ===== ===== Architecture =====
  
-The current proposed architecture is a Python Flask application with PostgreSQL as the backend database.+The system is based on a Python Flask application with PostgreSQL as the backend database.
  
-===== Tasks =====+Below is a diagram showing the system dependencies:
  
-^ Description ^ Depends on ^ Assigned to ^ +{{drawio>projects:member_portal:modules.png}} 
-| Copy across skeleton from storage project | | samp20 | + 
-| Implement [[projects:member_portal:session|]] | | samp20 | +===== Left to do ===== 
-| Initial [[projects:member_portal:oauth|]] implementation | Session management | - | + 
-| [[projects:member_portal:jwk|]] implementation | | - |+Required for initial demo: 
 + 
 +  * Portal homepage 
 +  * Hardcode OAuth permissions for demo 
 +  * Logout 
 +  * Host demo under Hackspace beta domain 
 +  * Sample OpenID compatible application (suggestions welcome) 
 + 
 +Shortly after
 +  * Rate limiter 
 +    * By attempted email address 
 +    * By IP address 
 +  * Object cleanup system 
 + 
 +Future work: 
 +  * Permissions system 
 +  * PKCE 
 +  * View/edit personal details 
 +  * View/delete active sessions 
 +  * External logins (keyfob) 
 +  * Admin pages 
 +    * Clients 
 +    * Roles 
 +    * Members
  
 ===== Project layout ===== ===== Project layout =====
  
-  * ''portal/''+  * ''portal/'': The whole application.
     * ''forms/'': WTForms.     * ''forms/'': WTForms.
-    * ''models.py'': SQLAlchemy models. 
     * ''static/'': Static files, e.g. css.     * ''static/'': Static files, e.g. css.
     * ''systems/'': Core systems, e.g. Session, OAuth, JWK.     * ''systems/'': Core systems, e.g. Session, OAuth, JWK.
     * ''templates/'': Jinja templates.     * ''templates/'': Jinja templates.
     * ''views/'': Flask Blueprints with routes. Glue between templates and systems.     * ''views/'': Flask Blueprints with routes. Glue between templates and systems.
 +    * ''%%__init__%%.py'': Application entrypoint.
 +    * ''extensions.py'': Instantiate extensions and systems.
 +    * ''models.py'': SQLAlchemy models.
   * ''tests/'': Tests. Mainly for systems.   * ''tests/'': Tests. Mainly for systems.
  
Line 57: Line 82:
 </code> </code>
  
 +===== Testing =====
 +
 +We will use pytest for our testing. We should aim to test each system in isolation.
 +
 +Some code will require an active request to test. We can create test endpoints to satisfy these instead of using the fully templated ones.
 +
 +For now we can probably use an in-memory SQLite database for testing. We may need to switch to a proper PostgreSQL database if we start to depend on DB specific features, at which point we'll need to clean the database before every test run.
 +
 +===== Models =====
 +
 +{{drawio>projects:member_portal:models.png}}
 +
 +===== Tokens =====
 +
 +A common pattern that's required is to store an external reference to a table row in a secure way. The pattern we use is to store an ''id'' of type UUID and a ''token_hash'' of type string in the table. The external token will refer to this using the string format ''{id.hex}:{token}''. The ID is used to select the correct row and the SHA256 of ''token'' is compared against ''token_hash''. The ''token'' is required as a layer of security as we cannot guarantee the ''id'' generation is cryptographically secure. It also allows us to rotate the ''token'' while still referring to the same row, for example cookie rotation.
  
  • projects/member_portal/home.1759877839
  • Last modified: 2 months ago
  • by samp20