- Motivation
- Getting Started
- Application Operation
The purpose of TeamPicker is to provide an application that enables the management of sports teams. Following registration, a manager must create a team during setup. Subsequently, players may register and must select a team during setup. Managers may then configure matches against other teams, and make their team selection from the list of players registered with their team. Following selection, players may confirm their availability. Please see Usage for additional details.
A reference application is hosted on Heroku and may be accessed at https://teampicker-fswd.herokuapp.com/.
See Pre-configured users for a list of users that have already been set up. See Additional users for details on adding new users, and Usage for details of application functionality.
The application structure is as follows:
├─ README.md - this file
├─ API.md - API specification
├─ requirements.txt - the dependencies to be installed, see Install dependencies
├─ teampicker.py - main script
├─ Procfile - commands that are executed by the app on startup
├─ runtime.txt - python runtime version
├─ src - backend application code
│ └─ team_picker - application code
│ │ ├─ auth - authentication code
│ │ ├─ controllers - controllers for processing API requests
│ │ ├─ forms - flask-wtf forms
│ │ ├─ models - database ORM models
│ │ ├─ public - javascript, css etc. files for UI
│ │ ├─ services - service layer interfacing between controllers and database
│ │ ├─ templates - jinja templates
│ │ └─ util - miscellaneous application code
│ ├─ __init__.py - application code
│ └─ constants.py - application constants
├─ test - test scripts
│ └─ postman - Postman collection
├─ instance - application instance folder, to store configurations etc. outside of version control
└─ migrations - Flask-Migarate versions folder, to store database configurations
The API documentation is available in API.md.
Follow instructions to install the latest version of python for your platform in the python docs
It is recommended that a virtual environment be used for development purposes. Please see Creating a virtual environment for details.
The following instructions are intended to be executed from a terminal window in the project root folder, in which the virtual environment is activated.
- Flask is a lightweight backend microservices framework. Flask is required to handle requests and responses.
- SQLAlchemy, Flask-SQLAlchemy and Flask-Migrate are libraries to provide database management and connectivity.
- python-jose JavaScript Object Signing and Encryption for JWTs. Useful for encoding, decoding, and verifying JWTs.
- Authlib and auth0-python provide authentication and management functionality via the Auth0 service.
- Jinja templating engine.
- Bootstrap framework.
- jQuery JavaScript library.
The details of the authorisation configuration on Auth0 are as follows:
The main TeamPicker application on Auth0 is a Regular web application.
There is also a Machine to Machine application, TeamPicker M2M, which is authorised to request access tokens for the TeamPicker API and the Auth0 Management API, by executing a client credentials exchange. TeamPicker M2M is used to assign roles to newly registered users.
The following are the details of the Auth0 API:
Permission | Description | TeamManager Role |
TeamPlayer Role |
---|---|---|---|
delete:match | Delete a match | ✓ | ✗ |
delete:own-user | Delete personal user | ✓ | ✓ |
get:match | Get a match | ✓ | ✓ |
get:own-user | Read personal user | ✓ | ✓ |
get:role | Read a role | ✓ | ✓ |
get:team | Read a team | ✓ | ✓ |
get:user | Read a user | ✓ | ✓ |
patch:match | Update a match | ✓ | ✗ |
patch:own-match | Update personal info for match | ✗ | ✓ |
patch:own-user | Update personal user | ✓ | ✓ |
patch:team | Update a team | ✓ | ✗ |
patch:user | Update a user | ✗ | ✗ |
post:match | Create a match | ✓ | ✗ |
post:team | Create a team | ✓ | ✗ |
post:user | Create a user | ✓ | ✗ |
The following database schema has been implemented:
Run the following command in a Terminal Window:
> pip3 install -r requirements.txt
Also see Using requirements files.
The application utilises environments variables, or a combination of configuration files and environments variables to specify the application configuration. There are three methods of configuring the application:
The database configuration must be set in one of three different ways. In order of precedence they are:
-
Set the
DB_URI
variable to a Connection URI. -
Set the
DB_URI_ENV_VAR
variable to the name of an environment variable which is set to a Connection URI.E.g. A typical use case is with a Heroku Postgres add-on which adds a
DATABASE_URL
environment variable that contains the database URI. -
Set the
DB_DIALECT
,DB_DRIVER
,DB_USERNAME
,DB_PASSWORD
,DB_HOST
,DB_PORT
andDB_DATABASE
variables from which a Connection URI is created.
- The configuration file should follow the format specified by sample.env.
For example, to configure the application to use:
- an SQLite database file
database.db
in the instance folder
-
Copy the file sample.env and save as
.env
, in the project root folder. -
Edit the new file to set the required database and authentication configuration.
DB_DIALECT = sqlite DB_DATABASE = database.db DB_INSTANCE_RELATIVE_CONFIG = True # Authentication related settings: AUTH0_DOMAIN = udacity-fsnd.auth0.com ALGORITHMS = ['RS256'] AUTH0_AUDIENCE = dev ...
Please see sample.env for additional information.
If variables are used in values, ensure they are surrounded with
{
and}
, like${VAR_TO_EXPAND}
, as bare variables such asVAR_TO_EXPAND
are not expanded.If a variable is defined in both
.env
and as a system environment variable, the system environment variable has precedence.
Depending on the operations system, environment variables are set differently:
For Linux and Mac: For Windows: For PowerShell:
$ export VARIABLE_NAME=value > set VARIABLE_NAME=value > $Env:VARIABLE_NAME=value
- The configuration file should follow the format specified by sample-config.py.
- The environment variables determine which configuration file to load.
-
APP_CONFIG_PATH
Configuration file path.
-
INST_REL_CONFIG
Flag indicating if instance_relative_config is relative to the instance folder. A setting of
f
,false
,n
,no
or0
is evaluated as False, otherwise the setting will be evaluated according to it's truthy value.
-
Ensure there is no
.env
file in the project root folder or any parent folders, otherwise an unexpected configuration may result.
For example, to configure the application to use:
- a configuration file
config.py
located in the instance folder, and - an SQLite database file
database.db
in the instance folder
-
Copy the file sample-config.py and save as
config.py
, in the instance folder. -
Edit the new file to set the required database and authentication configuration.
DB_DIALECT = 'sqlite' DB_DATABASE = 'database.db' DB_INSTANCE_RELATIVE_CONFIG = True # Authentication related settings: AUTH0_DOMAIN = 'udacity-fsnd.auth0.com' ALGORITHMS = ['RS256'] AUTH0_AUDIENCE = 'dev' ...
Please see sample-config.py for additional information.
As the configuration file is a python script, standard python string formatting may be used.
-
Set the environment variables,
APP_CONFIG_PATH
andINST_REL_CONFIG
appropriately.Variable Value APP_CONFIG_PATH config.py INST_REL_CONFIG true See Setting environment variables.
Environment variables corresponding to the keys in sample.env and sample-config.py should be set as appropriate.
An appropriately updated copy of the bash script sample.env.sh may be used to set the environment variables.
For example, to configure the application to use:
-
an SQLite database file
database.db
in the instance folderSet environment variables:
Variable Value INST_REL_CONFIG true DB_DIALECT sqlite DB_DATABASE database.db DB_INSTANCE_RELATIVE_CONFIG True AUTH0_DOMAIN udacity-fsnd.auth0.com ALGORITHMS ['RS256'] AUTH0_AUDIENCE dev See Setting environment variables.
For convenience, the location of the instance folder has been hardcoded to instance, as the default location determined by Flask varies depending on whether the application or test scripts are running. Please see Instance Folders for further information.
The application supports a number of arguments:
usage: TeamPicker [-h] [-idb] [-pt] [-ga GENERATE_API]
optional arguments:
-h, --help show this help message and exit
-idb, --initdb Initialise the database, default no
-pt, --postman_test Disable server-side sessions, default no
-ga GENERATE_API, --generate_api GENERATE_API
Generate API Markdown documentation, as specified file
Depending on the run method, these arguments must be passed as commandline arguments (Run using script), or as a dictionary (Run using Flask).
Environment variable equivalents of command line arguments have precedence over command line arguments.
When specified the database will be initialised before use, resulting on the removal of all data.
The environment variable equivalent is INIT_DB_ARG
.
This operation should not be confused with Database Migration which updates the database schema.
As Gunicorn has no inter-worker method of communication to coordinate the database initialisation, there must be only one worker when initialising the database. Gunicorn uses the
WEB_CONCURRENCY
environment variable as the default value for the number of workers. If not set, Heroku provides aWEB_CONCURRENCY
value depending on the dyno size.
Therefore, theWEB_CONCURRENCY
environment variable should be set to1
when utilising--initdb
orINIT_DB_ARG
on Heroku.
When specified, server-side sessions will be disabled. This setting is necessary when running Postman requests and using a JWT from a user logged-in on a browser in the Postman application.
The environment variable equivalent is POSTMAN_TEST_ARG
, however it should not be used on Heroku.
When specified, an API template Markdown document detailing all the application routes will be generated using the specified filename.
The environment variable equivalent is GENERATE_API_ARG
, however it should not be used on Heroku.
The API Markdown documentation file will be generated in the instance folder.
Once the application is configured for a blank database, as specified in Application Configuration, the database must be prepared for the application as follows:
-
Open a Terminal Window.
-
Set environment variables as detailed in Run the application.
-
Run the command
flask db upgrade
orpython -m flask db upgrade
Set environment variables:
Variable Value FLASK_APP see Run using flask
PYTHONPATH see Set python path > flask db upgrade
This will configure the database to the state required by the application, using the script 5604eccbf36a_initial_migration.py.
Once the database has been migrated, it may be re-initialised by specifying the Initialise the database (--initdb) application argument. When running as a script:
> python teampicker.py --initdb
or passed via the FLASK_APP
environment variable.
FLASK_APP=src.team_picker:create_app({"initdb":True})
The application can be run using the flask
command or directly by running the script.
Once an appropriate configuration has been created as per Application Configuration, from a Terminal Window, run the following commands:
For Linux and Mac: For Windows:
$ cd /path/to/project > cd \path\to\project
Set environment variables:
Variable | Value |
---|---|
PYTHONPATH | /path/to/project/src |
See Setting environment variables. |
From a Terminal Window, run the following commands:
> python teampicker.py
Set environment variables:
Variable | Value |
---|---|
FLASK_APP | src.team_picker:create_app({}) |
See Setting environment variables. |
From a Terminal Window, run the following commands:
> flask run
See Run The Application for other operating systems.
Note: To run with debug mode enabled specify the
--debug
option
> flask run --debug
A number of unit tests are available in the test folder. The tests are performed against an in-memory sqlite database.
From a Terminal Window, run the following commands to run all tests:
For Linux and Mac: For Windows:
$ cd /path/to/project/test > cd \path\to\project\test
Set python path, see Set python path.
> python -m test_all
Alternatively, to run tests individually:
Test | Command |
---|---|
Roles database tests | python -m test_roles |
Teams database tests | python -m test_teams |
Users database tests | python -m test_users |
Matches database tests | python -m test_matches |
Users UI tests | python -m test_user_setup_ui |
Matches UI tests | python -m test_match_ui |
Once the application has been set up as outlined in Getting Started, functionality can be verified locally. A number of Pre-configured users are available on the Auth0 service as a convenience, however these users need to be configured in the application database before use. User setup using Postman allows the swift completion of the setup of the Pre-configured users. Alternatively, they may be setup using the process outlined in Additional users.
The following users have been pre-configured on the Auth0 service:
Password | First name | Surname | Role | Team | |
---|---|---|---|---|---|
m1@team1.com | Manager1! | Manny | Uno | Manager | Team 1 |
p1@team1.com | Player1! | Patrik | Einer | Player | " |
p2@team1.com | Player2! | Pat | Ceann | Player | " |
p3@team1.com | Player3! | Patrice | Un | Player | " |
m2@team2.com | Manager2! | Manfred | Dos | Manager | Team 2 |
j1@team2.com | Player1! | Johann | Zwei | Player | " |
j2@team2.com | Player2! | Sean | Do | Player | " |
j3@team2.com | Player3! | Jean | Deux | Player | " |
m3@team3.com | Manager3! | Mildred | Tres | Manager | Team 3 |
s1@team3.com | Player1! | Joanna | Drei | Player | " |
s2@team3.com | Player2! | Dearbhla | Triur | Player | " |
s3@team3.com | Player3! | Jean | Trois | Player | " |
The Auth0 login credentials are the specified email and password. The first name, surname, role and team are suggestions.
To expedite the setup of these users on a new database, the Postman collection Udacity FSWD TeamPicker.postman_collection.json is available. The manager user's data is available in managers.json, and player's in players.json.
The application must be started with Disable server-side sessions option.
When running as a script:
> python teampicker.py --postman_test
or passed via the FLASK_APP
environment variable.
FLASK_APP=src.team_picker:create_app({"postman_test":True})
- Load Udacity FSWD TeamPicker.postman_collection.json into Postman.
- Open the collection and select the collection
Variables
tab. Set therun_mode
variable toiteration
, and save if necessary. - Select the
manager setup
folder from the collection. - Click the
Run
button to open the Collection Runner. - Click the
Select file
button, then browse to and select the managers.json file. - Click the
Run Udacity FSWD TeamPicker
button, to run the requests. - All the folder requests will run 3 times, once for each manager.
The requests should be run in the listed order. Failure to do so will result in incorrect user setup.
Follow the same procedure as for Setup managers, except for using the player setup
folder from the collection,
and the players.json data file.
All the folder requests will run 9 times, once for each player.
Please see Running collections with data files for more information.
In order to send individual requests from Udacity FSWD TeamPicker.postman_collection.json rather than the running in the listed order:
- Load Udacity FSWD TeamPicker.postman_collection.json into Postman.
- Open the collection and select the collection
Variables
tab. Set therun_mode
variable toindividual
. - Set the
username
,password
,firstname
,surname
,role_name
andteam_name
appropriately in order to pass response tests. - Save the collection variable changes.
Additional users may be added as required.
- On the application home screen, click the
Login or sign-up
button. - Select the
Sign up
link, and enter a username (email address) and password, and clickRegister
. - Authorise the application to access the user's new account.
- Enter a name and surname, and select a role on the
Create user
screen, and clickCreate
. - Manager's must enter a team name on the
Create team
screen. - Player's must select an existing team on the
Set team
screen.
The functionality available depends on the user's role.
Functionality | Manager | Player |
---|---|---|
Login | ✓ | ✓ |
Logout | ✓ | ✓ |
List matches | ✓ | ✓ |
Search matches | ✓ | ✓ |
Create/update matches | ✓ | ✗ |
Make match selections | ✓ | ✗ |
View match selections | ✓ | ✓ |
Confirm match selections | ✗ | ✓ |
On the application home screen, click the Login or sign-up
button, and enter username and password.
Notifications for any actions which the user needs to perform are displayed on the Home screen,
e.g., if a player need to confirm availability for a match.
Click the Logout
button on the top navigation bar.
Click Matches
on the top navigation bar, and select List
from the dropdown menu.
All the matches for the user's team will be listed.
Click Matches
on the top navigation bar, and select Search Match
from the dropdown menu.
Enter search criteria based on opposition and/or date.
All the matches for the user's team satisfying the criteria will be listed.
Click Matches
on the top navigation bar, and select New Match
from the dropdown menu.
The match venue, opposition and start time must be entered.
Click Edit
button corresponding to the match in the matches listing.
The match venue, opposition, start time, score and final result values may be updated.
Click Selections
button corresponding to the match in the matches listing.
A list of all players registered for the manager's team will be displayed.
Click on the Selected
checkbox to change their selected status.
Click Selections
button corresponding to the match in the matches listing.
A list of all players registered for the user's team will be displayed,
including the confirmation status of any who have confirmed their availability.
Click Selections
button corresponding to the match in the matches listing.
A list of all players registered for the player's team will be displayed.
In the event the player has been selected for the match, they can confirm their availability by
clicking on the Confirm
, Unsure
or Not available
buttons.
Click JWT
on the top navigation bar, to display the JWT token for the currently logged-in user.