Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • startuplab/courses/tjts5901-continuous-software-engineering/TJTS5901-K23_template
  • planet-of-the-apes/tjts-5901-apeuction
  • uunot-yliopiston-leivissa/tjts-5901-uunot
  • contain-the-cry/tjts-5901-auction-system
  • avengers/avengers
  • cse6/cse-6
  • 13th/13-sins-of-gitlab
  • fast-and-furious/fast-and-furious
  • back-to-the-future/delorean-auction
  • monty-pythons-the-meaning-of-life/the-meaning-of-life
  • team-atlantis/the-empire
  • code-with-the-wind/auction-project
  • the-pirates/the-pirates
  • do-the-right-thing/do-the-right-thing
  • inception/inception
  • the-social-network-syndicate/the-social-auction-network
  • team-the-hunt-for-red-october/tjts-5901-k-23-red-october
  • good-on-paper/good-paper-project
  • desperados/desperados
19 results
Show changes
Commits on Source (115)
Showing with 641 additions and 136 deletions
......@@ -165,3 +165,6 @@ cython_debug/
_docs/
.env
.DS_Store
# Ignore certificates
azure-sp.pem
......@@ -2,6 +2,8 @@
stages:
- build
- test
- staging
- smoketest
- deploy
variables:
......@@ -13,6 +15,8 @@ variables:
## (Optional) More verbose output from pipeline. Enabling it might reveal secrets.
#CI_DEBUG_TRACE: "true"
include:
- template: Jobs/SAST.gitlab-ci.yml
## Use buildkit to build the container.
## Buildkit: https://github.com/moby/buildkit
......@@ -45,6 +49,13 @@ build:
--opt build-arg:CI_COMMIT_SHA=${CI_COMMIT_SHA} \
--output type=image,name=${DOCKER_IMAGE_NAME}:${DOCKER_TAG},push=true
sast:
## Static Application Security Test
## You can override the included template(s) by including variable overrides
## SAST customization:
## https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
stage: test
## Run the tests. If any of the tests fails, pipeline is rejected.
test:
## Optional: include stage and environment name
......@@ -60,12 +71,99 @@ test:
- name: mongo:4.2 # update to reflect same version used on production
alias: mongo
script:
- pip install --disable-pip-version-check -e .[test]
- pytest -v
- echo "Test run succesfully!"
- pip install -e .[test]
## Run tests with coverage reporting
- coverage run -m pytest
## Run basic reporting for badge
- coverage report
## Generate detailed report for gitlab annotations.
- coverage xml -o coverage.xml
coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
## Job to setup new staging job.
deploy to staging:
stage: staging
## Only run this stage when main branch receives changes.
only:
- main
## Use microsoft provided azure cli image, that contains az cli.
image: mcr.microsoft.com/azure-cli
## Setup the environment variables. The can be accessed through the gitlab
## Deployments -> Environments. Generates url based on the app and branch name.
environment:
name: $CI_JOB_STAGE
url: https://${AZURE_APP_NAME}-${CI_ENVIRONMENT_SLUG}.azurewebsites.net
before_script:
## Make sanity check that gitlab variables stage is done.
- test -z "${AZURE_SP_NAME}" && (echo "Missing required variable AZURE_SP_NAME. See 'Staging.md'"; exit 1)
- test -f "${AZURE_SP_CERT}" || ( echo "AZURE_SP_CERT (${AZURE_SP_CERT}) file is missing!"; exit 1)
- test -z "${AZURE_APP_NAME}" && (echo "Missing required variable AZURE_APP_NAME. See 'Staging.md'"; exit 1)
- test -z "${AZURE_RESOURCE_GROUP}" && (echo "Missing required variable DOCKER_AUTH_CONFIG. See 'Staging.md'"; exit 1)
## Login into azure
- az login --service-principal -u "${AZURE_SP_NAME}" -p "${AZURE_SP_CERT}" --tenant "jyu.onmicrosoft.com"
script:
## Create staging slot and copy settings from production
- |
az webapp deployment slot create -n "$AZURE_APP_NAME" -g "$AZURE_RESOURCE_GROUP" \
--slot "$CI_ENVIRONMENT_SLUG" --configuration-source "$AZURE_APP_NAME"
## TODO: Create a snapshot of database, and use it.
## If you need to change settings see: https://docs.microsoft.com/en-us/cli/azure/webapp/config/appsettings
## Change container tag to reflect branch we're running on
- |
az webapp config container set -n "$AZURE_APP_NAME" -g "$AZURE_RESOURCE_GROUP" \
--docker-custom-image-name "${DOCKER_IMAGE_NAME}:${DOCKER_TAG}" -s "$CI_ENVIRONMENT_SLUG"
## In case slot already existed, restart the slot
- az webapp restart -n "$AZURE_APP_NAME" -g "$AZURE_RESOURCE_GROUP" -s "$CI_ENVIRONMENT_SLUG"
## Deploy latest image to the production
deploy:
## Restart is not immediate, it takes a sec or two, depending on container changes.
- sleep 20
## Store server info as artifact for prosperity
- curl "$CI_ENVIRONMENT_URL/server-info" -o server-info.json
artifacts:
paths:
- server-info.json
## Run smoketest to check that staging app is responding as expected.
staging smoketest:
stage: smoketest
image: ${DOCKER_IMAGE_NAME}:${DOCKER_TAG}
environment:
name: staging
url: https://${AZURE_APP_NAME}-${CI_ENVIRONMENT_SLUG}.azurewebsites.net
only:
- main
script:
- pip install --disable-pip-version-check -e .[test]
## Environment url can be inherited from CI_ENVIROMNENT_URL, which is one defined
## in the `environment.url:`. Using it here explicitly.
- echo "Testing againsta deployment address ${CI_ENVIROMNENT_URL}"
- pytest -v --environment-url="${CI_ENVIROMNENT_URL}" tests/test_smoke.py
## Push latest image into registry with the `latest` tag.
docker tag latest:
stage: deploy
environment: production
image: docker:20.10.23
......@@ -76,3 +174,25 @@ deploy:
- mkdir -p ${HOME}/.docker && echo "${DOCKER_AUTH_CONFIG}" > "${HOME}/.docker/config.json"
## Add the `latest` tag to the image we have build.
- docker buildx imagetools create ${DOCKER_IMAGE_NAME}:${DOCKER_TAG} --tag ${DOCKER_IMAGE_NAME}:latest
## Swap the production and staging slots around.
staging to production:
stage: deploy
## Only run this stage when main branch receives changes.
only:
- main
## Use microsoft provided azure cli image, that contains az cli.
image: mcr.microsoft.com/azure-cli
environment:
name: production
url: https://${AZURE_APP_NAME}.azurewebsites.net/
before_script:
## Login into azure
- az login --service-principal -u "${AZURE_SP_NAME}" -p "${AZURE_SP_CERT}" --tenant "jyu.onmicrosoft.com"
script:
## Swap production and staging slots.
- az webapp deployment slot swap -g "$AZURE_RESOURCE_GROUP" -n "$AZURE_APP_NAME" -s staging --target-slot production
### Summary
Briefly explain the issue and its impact on the project concisely.
### Steps to reproduce
1. List the steps to reproduce the issue
2. Provide any relevant details such as browser, device, version, etc.
### Expected outcome
What should happen after following the steps?
### Actual outcome
What actually happens after following the steps
### Additional information
- Include possible screenshots, logs, code snippets here
- Indicate if the issue occcurs only in certain conditions, environments or browsers.
### Possible fixes
If you think you might have a clue what is causing the bug, feel free to help!
Thank you!
/label ~"Bug Hunt"
......@@ -49,6 +49,10 @@ RUN pip --disable-pip-version-check install -r /tmp/pip-tmp/requirements.txt &&
## Copy app to WORKDIR folder
COPY . .
## Compile translations before installing app. This is done to make sure that
## translations are compiled before app is installed.
RUN pybabel compile -f -d src/tjts5901/translations/
## Install self as editable (`-e`) module. In a long run it would be recommeded
## to remove `COPY` and only install app as a package.
RUN pip --disable-pip-version-check install -v -e .
......
# TJTS5901 Course Template Project
[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7020/badge)](https://bestpractices.coreinfrastructure.org/projects/7020)
# TJTS5901 Course app
This project will be ficusing on creating application that is supose to serve for auctionaing items. What we plan to inculde as it's features:
- User can register, login
- User can bid on items, and be notified once the auction is finished
- multilocalization
- restAPI for to use for more advance users
Keep in mind that everything we do is a school project and this application will never be depolyed to the general public.
## TJTS5901 Course Template Project
Project template for 2023 TJTS5901 Continuous Software Engineering -course.
......@@ -7,7 +19,7 @@ Project template for 2023 TJTS5901 Continuous Software Engineering -course.
To get started with the project, see [`week_1.md`](./week_1.md)
The application is deployed at <https://tjts5901-app.azurewebsites.net>
Application address/deployment url : https://team13-webapp.azurewebsites.net/
## Start the app
......@@ -25,3 +37,16 @@ docker run -it -p 5001:5001 -e "FLASK_DEBUG=1" -v "${PWD}:/app" tjts5901
```
Please see the `docs/tjts5901` folder for more complete documentation.
## Security issue/bug reporting
To report bugs and security issues, please use [the project "issues" form](https://gitlab.jyu.fi/13th/13-sins-of-gitlab/-/issues/new?issuable_template=Bug%20Hunt)
**Endpoints** and **other usfull things** that you can use to interact with our restAPI:
1. Register yourself using (https://team13-webapp.azurewebsites.net/register?email=\<your mail>&password=\<password you want>), omit the \<>
2. Login using GET (https://team13-webapp.azurewebsites.net/login?email=\<your mail>&password=\<your password>) or you can use POST with JSON.
3. You will recive a JWT token that is valid for 2 hours, keep it confidential!
4. For every request from now on don't forget to use your token in token bearer! If you want to try the API, but you don't want to do any fancy url writing use [this app](https://reqbin.com/)
5. Request all the items using [this link](https://team13-webapp.azurewebsites.net/auction_item/)
6. Bid on items using [this address](https://team13-webapp.azurewebsites.net/bid), don't forget to send a payload of type JSON structured in this way: {"item_id" : "item id you want to bid on", "bid_price" : amount_you_want_to_bid}
\ No newline at end of file
[python: **.py]
[jinja2: **/templates/**.html]
[jinja2: **/templates/**.html.j2]
# Week one report
Radek Valigura from now on just **Radek**.
Olli Mehtonen from now on just **Olli**.
Aapo Kauranen from now on just **Aapo**.
What have we done so far:
---
Radek:
- wrote one user story
- set up the pipeline
- wrote OWASP security risks considerations
Olli:
- Wrote multiple user stories
- Wrote some of the ways of working stuff
- Set up my local dev environment
- Set up Azure resource group
- Container registry selected and setup
Aapo: (Added February 2nd)
- Had plenty of issues with docker daemon and almost gave up.
- Wrote some user stories.
- set up CI/CD
## OWASP security risks
1. Broken access control - We should secure our API, so that only a request to the pre-specified paths is possible.
2. Cryptographic failure - We should hash (salt and paper) all the passwords of our users. Creating a secure environment for our users.
3. Injection - all our database manipulation should go trough predefined API.
4. Security Logging and Monitoring Failures - We should establish logging for failed password attempt and also create a temporary time block on an account in case of password hard cracking.
5. Security Logging and Monitoring Failures - We should store our logs on a local machine and remote server as well.
# Week two report
Radek Valigura from now on just **Radek**.
Olli Mehtonen from now on just **Olli**.
Aapo Kauranen from now on just **Aapo**.
What have we done so far:
---
Radek:
- wrote three user stories
- Created first backend structure and restAPI interface
- Created future user class, and api to access the data in DB.
- Users can now add Items.
- wrote OWASP security risks considerations
Olli:
- Wrote some user stories/created the template for gitlab
- Got the pipeline to work/some DB initializing on Azure
- Will check on the testing stage tomorrow
- Set uped Database
Aapo:
- Wrote one user story.
- Created webpage template and frontend code to handle most of the bid submission. Actual request to backend will be written on 2nd or 3rd February.
## OWASP security risks
1. Broken access control - Limit API calls send alerts to the admins once there were to many tries.
2. Cryptographic failure - Usage of outdated or cracked crypto/ hashing algorithms should be avoided.
3. Injection - Prevent the too many argument injection, giving the user higher privileges.
4. Injection - We should implement some form of validation of incoming data.
5. Insecure design - We will only use widely used, regularly updated and verified libraries, to prevent inclusion of unsecured code.
# Week three report
Radek Valigura from now on just **Radek**.
Olli Mehtonen from now on just **Olli**.
Aapo Kauranen from now on just **Aapo**.
What have we done so far:
---
Radek:
- Setup logging and monitoring
- Created endpoint for user login and auth with jwt
- Created endpoint for bidding
- Wrote more tests
- fixed few bugs
Olli:
- Administrative tasks
- Tests and pipeline implementation
- SAST
- Localization support and multi-currency support
Aapo:
- Login and authorization and registration.
- Profile page basics
- Bidding page for user.
- User can share items on social media.
## OWASP security risks
1. Security Misconfiguration - Make sure that permissions and roles and properly configured on cloud services (on azure).
2. Vulnerable and Outdated Components - Proper testing on the compatibility of different libraries we use together.
3. Security Misconfiguration - Let's not install any unnecessary features and frameworks, try to keep things minimal and not overloaded/complicated.
4. Identification and Authentication Failures - Let's not allow passwords that are too easy (needs to have minimum lenght, small and capital letters, numbers/symbols/letters mixed etc.)
5. Identification and Authentication Failures - Implement multifactor authentication, pretty basic.
# Week three report
Radek Valigura from now on just **Radek**.
Olli Mehtonen from now on just **Olli**.
Aapo Kauranen from now on just **Aapo**.
What have we done so far:
---
Radek:
- connected with the sentry
- restAPI for users to use for bidding on items
- created a restAPI documentation for bughunt
- wrote more tests
- played the “Privacy’s not dead!” game
- did OpenSSF Best Practices badge
- Add third-party authentication system (does JWT or Oauth2 count?)
- created new enpoints for users to use
- fixed issues and cleaned up a project a bit
Olli:
- Sentry stuff on Azure
- Localisation and its tests
- Played the "Privacy's not dead!" game
- User stories
- Bug Hunt
- Added staging to pipeline
Aapo:
- Saving items and bids to backend.
- Some Azure configuration for database.
- Hunted bugs.
- played the “Privacy’s not dead!” game
- Sharing links to social media.
- Multicurrency support added.
## OWASP security risks
1. Security Misconfiguration - Make sure that permissions and roles and properly configured on cloud services (on azure).
2. Vulnerable and Outdated Components - Proper testing on the compatibility of different libraries we use together.
3. Security Misconfiguration - Let's not install any unnecessary features and frameworks, try to keep things minimal and not overloaded/complicated.
4. Identification and Authentication Failures - Let's not allow passwords that are too easy (needs to have minimum lenght, small and capital letters, numbers/symbols/letters mixed etc.)
5. Identification and Authentication Failures - Implement multifactor authentication, pretty basic.
# Week three report
Radek Valigura from now on just **Radek**.
Olli Mehtonen from now on just **Olli**.
Aapo Kauranen from now on just **Aapo**.
What have we done so far:
---
Radek:
- Resolved the following bughunt issues:
1. Registration failure
**issue** - https://team13-webapp.azurewebsites.net/auth/register doesn't work
**solution** - it was artifact that was created form accidental merge
2. User creation via API failure
**issue** - user can do GET reqest on [registration URL](https://team13-webapp.azurewebsites.net/register) but the POST reqest doesn't exist
**solution** - Added POST to already exisitng GET
3. Documentation url for items is wrong
**issue** - Documentation has mentioned wrong URL with ending /auction_items/
**soluton** - correct the readme to /auction_item/
4. Cannot open registering page
**issue** - user could post a item with starting price -999999999999
**solution** - added simple value check
- Did minor refactoring
- added more API endpoints
- documented his crappy code!
- Pressed few keys that resulted in writing something on the final report
Olli:
-
Aapo:
- Resloved the bug issues:
1. Cannot open registering page
**issue** - /reg endpoint doesn't work
**solution** - added files that were needed for rendering the template, since they weren't included in main branch
## OWASP security risks
1. Security Misconfiguration - Make sure that permissions and roles and properly configured on cloud services (on azure).
2. Vulnerable and Outdated Components - Proper testing on the compatibility of different libraries we use together.
3. Security Misconfiguration - Let's not install any unnecessary features and frameworks, try to keep things minimal and not overloaded/complicated.
4. Identification and Authentication Failures - Let's not allow passwords that are too easy (needs to have minimum lenght, small and capital letters, numbers/symbols/letters mixed etc.)
5. Identification and Authentication Failures - Implement multifactor authentication, pretty basic.
\ No newline at end of file
......@@ -29,3 +29,6 @@ MONGO_URL=mongodb://mongodb:27017/tjts5901
# Setup sentry environment to separate development issues from production. This variable name is
# maybe set by gitlab pipeline. <https://docs.gitlab.com/ee/ci/environments/>
CI_ENVIRONMENT_NAME=development
# Setup CI environment url to point on localhost for testing purposes.
CI_ENVIRONMENT_URL=http://localhost:5001
......@@ -29,6 +29,7 @@ dependencies = {file = ["requirements.txt"]}
test = [
"pytest",
"coverage",
"requests",
]
docs = [
"mkdocs",
......
......@@ -2,7 +2,18 @@
importlib-metadata
# Framework and libraries
flask==2.2.2
flask
flask-restful
flask-rich
pytest
pyjwt
flask_jwt_extended
bcrypt
requests
flask-babel
#DB connections
pymongo
python-dotenv
flask-mongoengine==1.0
......
......@@ -10,21 +10,54 @@ Flask tutorial: https://flask.palletsprojects.com/en/2.2.x/tutorial/
import logging
from os import environ
import os
import sentry_sdk
from typing import Dict, Literal, Optional
from flask_babel import _
from .i18n import init_babel
from dotenv import load_dotenv
from flask import (
Flask,
jsonify,
Response,
request,
render_template,
redirect,
make_response,
url_for,
session
)
from sentry_sdk.integrations.flask import FlaskIntegration
from flask_restful import Resource, Api, reqparse, abort
from flask_jwt_extended import (
JWTManager, jwt_required, create_access_token,
get_jwt_identity)
#login info handling decorators
from tjts5901.backend.logincookies import logged_in, admin_logged_in, login_with_user, admin_with_user, logout_all
#item api class
import tjts5901.backend.item_api as items
import tjts5901.backend.admin_api as admin_api
import tjts5901.backend.login_api as log_in
import tjts5901.backend.bid_api as bid
import tjts5901.backend.register_api as register_api
import tjts5901.backend.models.users as reg_user
from .utils import get_version
from .db import init_db
from . import views # pylint: disable=import-outside-toplevel
logger = logging.getLogger(__name__)
# Register blueprints
def create_app(config: Optional[Dict] = None) -> Flask:
"""
......@@ -32,12 +65,18 @@ def create_app(config: Optional[Dict] = None) -> Flask:
:param name: The name of the application.
"""
flask_app = Flask(__name__, instance_relative_config=True)
flask_app = Flask(__name__, instance_relative_config=True, static_folder='./frontend')
#Change of static folder location above
flask_app.config.from_mapping(
SECRET_KEY='dev',
BRAND="Hill Valley DMC dealership",
BRAND=_("13th auction app"),
)
flask_app.register_blueprint(views.bp, url_prefix='')
# load the instance config, if it exists, when not testing
if config is None:
......@@ -45,6 +84,7 @@ def create_app(config: Optional[Dict] = None) -> Flask:
else:
flask_app.config.from_mapping(config)
# Initialize logging early, so that we can log the rest of the initialization.
from .logging import init_logging # pylint: disable=import-outside-toplevel
init_logging(flask_app)
......@@ -54,25 +94,30 @@ def create_app(config: Optional[Dict] = None) -> Flask:
os.makedirs(flask_app.instance_path)
except OSError:
pass
# Initialize the Flask-Babel extension.
init_babel(flask_app)
# Initialize the database connection.
init_db(flask_app)
#init_db(flask_app)
@flask_app.route('/debug-sentry')
def trigger_error():
division_by_zero = 1 / 0
#@flask_app.route('/debug-sentry')
#def trigger_error():
# division_by_zero = 1 / 0
# a simple page that says hello
@flask_app.route('/hello')
def hello():
return 'Hello, World!'
return _('Hello, World!')
from . import auth
flask_app.register_blueprint(auth.bp)
#from . import auth
#flask_app.register_blueprint(auth.bp)
from . import items
flask_app.register_blueprint(items.bp)
flask_app.add_url_rule('/', endpoint='index')
#from . import items
#flask_app.register_blueprint(items.bp)
#flask_app.add_url_rule('/', endpoint='index')
#Ensure the flask jwt token location has cookies
return flask_app
......@@ -81,8 +126,42 @@ def create_app(config: Optional[Dict] = None) -> Flask:
# template and how to use it.
load_dotenv()
sentry_sdk.init(
dsn="https://2eaf6ba1a9ef42d89c9d5e660d3c5f19@o1104883.ingest.sentry.io/4504668957900800",
integrations=[
FlaskIntegration(),
],
# Set traces_sample_rate to 1.0 to capture 100%
# of transactions for performance monitoring.
# We recommend adjusting this value in production.
traces_sample_rate=1.0
)
# Create the Flask application.
flask_app = create_app()
# Addad time till token expires from 10 min to 2 hours
flask_app.config['JWT_ACCESS_TOKEN_EXPIRES'] = 7200
# create flast restapi
api = Api(flask_app)
#create JSON web token bearer
jwt = JWTManager(flask_app)
# added auction item resource
api.add_resource(items.AuctionItem, "/auction_item/", "/auction_item/<id>")
api.add_resource(admin_api.AdminAPI, "/users/", "/users/<email>")
api.add_resource(bid.Bid, "/bid")
api.add_resource(register_api.Register, "/register")
@flask_app.route('/debug-sentry')
def trigger_error():
try:
division_by_zero = 1 / 0
except Exception as er:
return {"Error" : er}, 400
@flask_app.route("/server-info")
......@@ -98,7 +177,7 @@ def server_info() -> Response:
database_ping = False
try:
from .db import db # pylint: disable=import-outside-toplevel
database_ping = db.connection.admin.command('ping').get("ok", False) and True
database_ping = db.connection.admin.command('ping').get("ok", False) #and True
except Exception as exc: # pylint: disable=broad-except
logger.warning("Error querying mongodb server: %r", exc,
exc_info=True,
......@@ -127,3 +206,105 @@ def server_info() -> Response:
response["pong"] = f"{ping}"
return jsonify(response)
@flask_app.route('/login', methods=['GET', 'POST'])
def login():
"""Login route for users
Returns:
_type_: 401 in case email or password is not matching, else 200
"""
# Get the username and password from the request
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
save_as_cookie = request.form.get('to_cookie', True)
elif request.method == 'GET':
email = request.args.get('email')
password = request.args.get('password')
save_as_cookie = False
# Authenticate the user
user = log_in.UserLogin.authenticate(email, password)
if not user:
return {'message': 'Invalid email or password'}, 401
#Save data to session
if save_as_cookie:
login_with_user(user['email'])
# Generate a JWT access token
access_token = create_access_token(identity=user["email"])
return {'access_token': access_token}, 200
@flask_app.route('/adminlogin', methods=['POST'])
def admin_login():
"""Admin login route for users
Returns:
_type_: 401 in case email or password is not matching, else 200
"""
# Get the username and password from the request
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
#if not email or not password:
# abort(400, message="Both email and password are required!")
# Authenticate the user
user = log_in.UserLogin.authenticate(email, password)
if not user or not password:
return {'message': 'Invalid email or password'}, 401
#Save data to session
admin_with_user(user['email'])
# Generate a JWT access token
access_token = create_access_token(identity=user["email"])
return {'access_token': access_token}, 200
@flask_app.route('/protected')
@jwt_required()
def protected():
"""Just a test route
Returns:
str: formatted output
"""
# Access the identity of the current user from the JWT
current_user = get_jwt_identity()
return {'message': 'Hello, {}!'.format(current_user)}
@flask_app.route('/login_page', methods=['GET'])
def login_page():
"""View for logging in
Returns:
Login page in case of authentication failure and redirect to main page if authenticated.
"""
return render_template('login.html', login_fail=False)
@flask_app.route('/reg')
def reg_page():
"""
View for registering new users.
"""
return render_template('auth/register.html')
@flask_app.route('/alpage')
def admin_login_page():
return render_template('alogin.html', login_fail=False)
@flask_app.route('/logout')
def logout():
logout_all()
return redirect(url_for('login_page'))
import functools
from flask import (
Blueprint, flash, g, redirect, render_template, request, session, url_for
)
from werkzeug.security import check_password_hash, generate_password_hash
from sentry_sdk import set_user
from .models import User
from mongoengine import DoesNotExist
bp = Blueprint('auth', __name__, url_prefix='/auth')
@bp.before_app_request
def load_logged_in_user():
"""
If a user id is stored in the session, load the user object from
"""
user_id = session.get('user_id')
if user_id is None:
g.user = None
set_user(None)
else:
g.user = User.objects.get(id=user_id)
set_user({"id": str(g.user.id), "email": g.user.email})
def login_required(view):
@functools.wraps(view)
def wrapped_view(**kwargs):
if g.user is None:
return redirect(url_for('auth.login'))
return view(**kwargs)
return wrapped_view
@bp.route('/register', methods=('GET', 'POST'))
def register():
if request.method == 'POST':
print("Registering user...")
email = request.form['email']
password = request.form['password']
password2 = request.form['password2']
terms = request.form.get('terms', False)
error = None
if not email:
error = 'Username is required.'
elif not password:
error = 'Password is required.'
elif password != password2:
error = 'Passwords do not match.'
elif not terms:
error = 'You must agree to the terms.'
if error is None:
try:
user = User(
email=email,
password=generate_password_hash(password)
)
user.save()
flash("You have been registered. Please log in.")
except Exception as exc:
error = f"Error creating user: {exc!s}"
else:
return redirect(url_for("auth.login"))
print("Could not register user:", error)
flash(error)
return render_template('auth/register.html')
@bp.route('/login', methods=('GET', 'POST'))
def login():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
error = None
try:
user = User.objects.get(email=email)
except DoesNotExist:
error = 'Incorrect username.'
if user is None:
error = 'Incorrect username.'
elif not check_password_hash(user['password'], password):
error = 'Incorrect password.'
if error is None:
session.clear()
session['user_id'] = str(user['id'])
flash(f"Hello {email}, You have been logged in.")
return redirect(url_for('items.index'))
print("Error logging in:", error)
flash(error)
return render_template('auth/login.html')
@bp.route('/logout')
def logout():
session.clear()
flash("You have been logged out.")
return redirect(url_for('index'))
File added
File added
import json
import logging
from flask import request, jsonify
from flask_restful import Resource, abort
import tjts5901.backend.models.users as users
from flask_jwt_extended import (jwt_required, get_jwt_identity)
logger = logging.getLogger(__name__)
class AdminAPI (Resource):
"""Admin rest call interface
Args:
Resource (_type_): _description_
"""
@jwt_required()
def get(self, email = None):
user = users.User()
#current_user = get_jwt_identity()
if not email:
logger.info("retriving all users!")
query_result = user.get_all()
user_from_db = [user_from_db for user_from_db in query_result]
temp = json.dumps(user_from_db, default=str)
return temp
logger.info(f"Trying to retrive a user with id: {id}")
try:
query_result = user.get_user(email)
temp = json.dumps(query_result, default=str)
return temp
except Exception as err:
abort(404, message = err)
@jwt_required()
def post(self):
#TODO: connection with db
data = request.get_json()
user = users.User(**data)
user.add()
addad_user = json.dumps(user.serialize(), default=str)
return {'status' : addad_user}, 201
\ No newline at end of file