Skip to content
Snippets Groups Projects
Commit 5aa1a2c0 authored by Victor Löfgren's avatar Victor Löfgren
Browse files

Resolve "Add presentation authorization"

parent bbba7f31
No related branches found
No related tags found
1 merge request!102Resolve "Add presentation authorization"
Pipeline #42771 passed
Showing
with 236 additions and 90 deletions
......@@ -13,24 +13,62 @@ def validate_editor(db_item, *views):
abort(http_codes.UNAUTHORIZED)
def check_jwt(editor=False, *views):
def wrapper(fn):
@wraps(fn)
def decorator(*args, **kwargs):
def _is_allowed(allowed, actual):
return actual and "*" in allowed or actual in allowed
def _has_access(in_claim, in_route):
in_route = int(in_route) if in_route else None
return not in_route or in_claim and in_claim == in_route
def protect_route(allowed_roles=None, allowed_views=None):
def wrapper(func):
def inner(*args, **kwargs):
verify_jwt_in_request()
claims = get_jwt_claims()
# Authorize request if roles has access to the route #
nonlocal allowed_roles
allowed_roles = allowed_roles or []
role = claims.get("role")
if _is_allowed(allowed_roles, role):
return func(*args, **kwargs)
# Authorize request if view has access and is trying to access the
# competition its in. Also check team if client is a team.
# Allow request if route doesn't belong to any competition.
nonlocal allowed_views
allowed_views = allowed_views or []
view = claims.get("view")
if role == "Admin":
return fn(*args, **kwargs)
elif editor and role == "Editor":
return fn(*args, **kwargs)
elif view in views:
return fn(*args, **kwargs)
else:
abort(http_codes.UNAUTHORIZED)
return decorator
if not _is_allowed(allowed_views, view):
abort(
http_codes.UNAUTHORIZED,
f"Client with view '{view}' is not allowed to access route with allowed views {allowed_views}.",
)
claim_competition_id = claims.get("competition_id")
route_competition_id = kwargs.get("competition_id")
if not _has_access(claim_competition_id, route_competition_id):
abort(
http_codes.UNAUTHORIZED,
f"Client in competition '{claim_competition_id}' is not allowed to access competition '{route_competition_id}'.",
)
if view == "Team":
claim_team_id = claims.get("team_id")
route_team_id = kwargs.get("team_id")
if not _has_access(claim_team_id, route_team_id):
abort(
http_codes.UNAUTHORIZED,
f"Client in team '{claim_team_id}' is not allowed to access team '{route_team_id}'.",
)
return func(*args, **kwargs)
return inner
return wrapper
......
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core.dto import QuestionAlternativeDTO
from flask_restx import Resource
from flask_restx import reqparse
......@@ -17,12 +17,12 @@ question_alternative_parser.add_argument("value", type=int, default=None, locati
@api.route("")
@api.param("competition_id, slide_id, question_id")
class QuestionAlternativeList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def get(self, competition_id, slide_id, question_id):
items = dbc.get.question_alternative_list(competition_id, slide_id, question_id)
return list_response(list_schema.dump(items))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def post(self, competition_id, slide_id, question_id):
args = question_alternative_parser.parse_args(strict=True)
item = dbc.add.question_alternative(**args, question_id=question_id)
......@@ -32,19 +32,19 @@ class QuestionAlternativeList(Resource):
@api.route("/<alternative_id>")
@api.param("competition_id, slide_id, question_id, alternative_id")
class QuestionAlternatives(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def get(self, competition_id, slide_id, question_id, alternative_id):
items = dbc.get.question_alternative(competition_id, slide_id, question_id, alternative_id)
return item_response(schema.dump(items))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def put(self, competition_id, slide_id, question_id, alternative_id):
args = question_alternative_parser.parse_args(strict=True)
item = dbc.get.question_alternative(competition_id, slide_id, question_id, alternative_id)
item = dbc.edit.default(item, **args)
return item_response(schema.dump(item))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def delete(self, competition_id, slide_id, question_id, alternative_id):
item = dbc.get.question_alternative(competition_id, slide_id, question_id, alternative_id)
dbc.delete.default(item)
......
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core.dto import QuestionAnswerDTO
from flask_restx import Resource
from flask_restx import reqparse
......@@ -22,12 +22,12 @@ question_answer_edit_parser.add_argument("score", type=int, default=None, locati
@api.route("")
@api.param("competition_id, team_id")
class QuestionAnswerList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def get(self, competition_id, team_id):
items = dbc.get.question_answer_list(competition_id, team_id)
return list_response(list_schema.dump(items))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def post(self, competition_id, team_id):
args = question_answer_parser.parse_args(strict=True)
item = dbc.add.question_answer(**args, team_id=team_id)
......@@ -37,11 +37,12 @@ class QuestionAnswerList(Resource):
@api.route("/<answer_id>")
@api.param("competition_id, team_id, answer_id")
class QuestionAnswers(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def get(self, competition_id, team_id, answer_id):
item = dbc.get.question_answer(competition_id, team_id, answer_id)
return item_response(schema.dump(item))
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def put(self, competition_id, team_id, answer_id):
args = question_answer_edit_parser.parse_args(strict=True)
item = dbc.get.question_answer(competition_id, team_id, answer_id)
......
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import check_jwt, item_response, text_response
from app.apis import item_response, protect_route, text_response
from app.core.codes import verify_code
from app.core.dto import AuthDTO, CodeDTO
from flask_jwt_extended import (
......@@ -12,6 +12,8 @@ from flask_jwt_extended import (
)
from flask_restx import Resource
from flask_restx import inputs, reqparse
from datetime import timedelta
from app.core import sockets
api = AuthDTO.api
schema = AuthDTO.schema
......@@ -33,9 +35,13 @@ def get_user_claims(item_user):
return {"role": item_user.role.name, "city_id": item_user.city_id}
def get_code_claims(item_code):
return {"view": item_code.view_type.name, "competition_id": item_code.competition_id, "team_id": item_code.team_id}
@api.route("/signup")
class AuthSignup(Resource):
@check_jwt(editor=False)
@protect_route(allowed_roles=["Admin"])
def post(self):
args = create_user_parser.parse_args(strict=True)
email = args.get("email")
......@@ -50,7 +56,7 @@ class AuthSignup(Resource):
@api.route("/delete/<ID>")
@api.param("ID")
class AuthDelete(Resource):
@check_jwt(editor=False)
@protect_route(allowed_roles=["Admin"])
def delete(self, ID):
item_user = dbc.get.user(ID)
......@@ -86,24 +92,38 @@ class AuthLoginCode(Resource):
code = args["code"]
if not verify_code(code):
api.abort(codes.BAD_REQUEST, "Invalid code")
api.abort(codes.UNAUTHORIZED, "Invalid code")
item_code = dbc.get.code_by_code(code)
return item_response(CodeDTO.schema.dump(item_code))
if item_code.competition_id not in sockets.presentations:
api.abort(codes.UNAUTHORIZED, "Competition not active")
access_token = create_access_token(
item_code.id, user_claims=get_code_claims(item_code), expires_delta=timedelta(hours=8)
)
response = {
"competition_id": item_code.competition_id,
"view_type_id": item_code.view_type_id,
"team_id": item_code.team_id,
"access_token": access_token,
}
return response
@api.route("/logout")
class AuthLogout(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def post(self):
jti = get_raw_jwt()["jti"]
dbc.add.blacklist(jti)
return text_response("User logout")
return text_response("Logout")
@api.route("/refresh")
class AuthRefresh(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
@jwt_refresh_token_required
def post(self):
old_jti = get_raw_jwt()["jti"]
......
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core import http_codes as codes
from app.core.dto import CodeDTO
from app.database.models import Code
......@@ -13,7 +13,7 @@ list_schema = CodeDTO.list_schema
@api.route("")
@api.param("competition_id")
class CodesList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self, competition_id):
items = dbc.get.code_list(competition_id)
return list_response(list_schema.dump(items), len(items))
......@@ -22,7 +22,7 @@ class CodesList(Resource):
@api.route("/<code_id>")
@api.param("competition_id, code_id")
class CodesById(Resource):
@check_jwt(editor=False)
@protect_route(allowed_roles=["*"])
def put(self, competition_id, code_id):
item = dbc.get.one(Code, code_id)
item.code = dbc.utils.generate_unique_code()
......
import time
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core.dto import CompetitionDTO
from app.database.models import Competition
from flask_restx import Resource
......@@ -29,7 +29,7 @@ competition_search_parser.add_argument("city_id", type=int, default=None, locati
@api.route("")
class CompetitionsList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def post(self):
args = competition_parser.parse_args(strict=True)
......@@ -44,12 +44,13 @@ class CompetitionsList(Resource):
@api.route("/<competition_id>")
@api.param("competition_id")
class Competitions(Resource):
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def get(self, competition_id):
item = dbc.get.competition(competition_id)
return item_response(rich_schema.dump(item))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def put(self, competition_id):
args = competition_edit_parser.parse_args(strict=True)
item = dbc.get.one(Competition, competition_id)
......@@ -57,7 +58,7 @@ class Competitions(Resource):
return item_response(schema.dump(item))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def delete(self, competition_id):
item = dbc.get.one(Competition, competition_id)
dbc.delete.competition(item)
......@@ -67,7 +68,7 @@ class Competitions(Resource):
@api.route("/search")
class CompetitionSearch(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self):
args = competition_search_parser.parse_args(strict=True)
items, total = dbc.search.competition(**args)
......@@ -77,7 +78,7 @@ class CompetitionSearch(Resource):
@api.route("/<competition_id>/copy")
@api.param("competition_id")
class SlidesOrder(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def post(self, competition_id):
item_competition = dbc.get.competition(competition_id)
......
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core.dto import ComponentDTO
from flask_restx import Resource
from flask_restx import reqparse
......@@ -27,12 +27,12 @@ component_create_parser.add_argument("type_id", type=int, required=True, locatio
@api.route("/<component_id>")
@api.param("competition_id, slide_id, component_id")
class ComponentByID(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def get(self, competition_id, slide_id, component_id):
item = dbc.get.component(competition_id, slide_id, component_id)
return item_response(schema.dump(item))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def put(self, competition_id, slide_id, component_id):
args = component_edit_parser.parse_args(strict=True)
item = dbc.get.component(competition_id, slide_id, component_id)
......@@ -40,7 +40,7 @@ class ComponentByID(Resource):
item = dbc.edit.default(item, **args_without_none)
return item_response(schema.dump(item))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def delete(self, competition_id, slide_id, component_id):
item = dbc.get.component(competition_id, slide_id, component_id)
dbc.delete.component(item)
......@@ -50,12 +50,12 @@ class ComponentByID(Resource):
@api.route("")
@api.param("competition_id, slide_id")
class ComponentList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def get(self, competition_id, slide_id):
items = dbc.get.component_list(competition_id, slide_id)
return list_response(list_schema.dump(items))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def post(self, competition_id, slide_id):
args = component_create_parser.parse_args()
item = dbc.add.component(slide_id=slide_id, **args)
......
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core.dto import MediaDTO
from app.core.parsers import search_parser
from app.database.models import Media
......@@ -22,13 +22,13 @@ media_parser_search.add_argument("filename", type=str, default=None, location="a
@api.route("/images")
class ImageList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self):
args = media_parser_search.parse_args(strict=True)
items, total = dbc.search.image(**args)
return list_response(list_schema.dump(items), total)
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def post(self):
if "image" not in request.files:
api.abort(codes.BAD_REQUEST, "Missing image in request.files")
......@@ -48,12 +48,12 @@ class ImageList(Resource):
@api.route("/images/<ID>")
@api.param("ID")
class ImageList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def get(self, ID):
item = dbc.get.one(Media, ID)
return item_response(schema.dump(item))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def delete(self, ID):
item = dbc.get.one(Media, ID)
try:
......
import app.database.controller as dbc
from app.apis import check_jwt, list_response
from app.apis import list_response, protect_route
from app.core import http_codes
from app.core.dto import MiscDTO
from app.database.models import City, Competition, ComponentType, MediaType, QuestionType, Role, User, ViewType
......@@ -23,6 +23,7 @@ name_parser.add_argument("name", type=str, required=True, location="json")
@api.route("/types")
class TypesList(Resource):
@protect_route(allowed_roles=["*"], allowed_views=["*"])
def get(self):
result = {}
result["media_types"] = media_type_schema.dump(dbc.get.all(MediaType))
......@@ -34,7 +35,7 @@ class TypesList(Resource):
@api.route("/roles")
class RoleList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self):
items = dbc.get.all(Role)
return list_response(role_schema.dump(items))
......@@ -42,12 +43,12 @@ class RoleList(Resource):
@api.route("/cities")
class CitiesList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self):
items = dbc.get.all(City)
return list_response(city_schema.dump(items))
@check_jwt(editor=False)
@protect_route(allowed_roles=["Admin"])
def post(self):
args = name_parser.parse_args(strict=True)
dbc.add.city(args["name"])
......@@ -58,7 +59,7 @@ class CitiesList(Resource):
@api.route("/cities/<ID>")
@api.param("ID")
class Cities(Resource):
@check_jwt(editor=False)
@protect_route(allowed_roles=["Admin"])
def put(self, ID):
item = dbc.get.one(City, ID)
args = name_parser.parse_args(strict=True)
......@@ -67,7 +68,7 @@ class Cities(Resource):
items = dbc.get.all(City)
return list_response(city_schema.dump(items))
@check_jwt(editor=False)
@protect_route(allowed_roles=["Admin"])
def delete(self, ID):
item = dbc.get.one(City, ID)
dbc.delete.default(item)
......@@ -77,7 +78,7 @@ class Cities(Resource):
@api.route("/statistics")
class Statistics(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self):
user_count = User.query.count()
competition_count = Competition.query.count()
......
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core.dto import QuestionDTO
from flask_restx import Resource
from flask_restx import reqparse
......@@ -18,7 +18,7 @@ question_parser.add_argument("type_id", type=int, default=None, location="json")
@api.route("/questions")
@api.param("competition_id")
class QuestionList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self, competition_id):
items = dbc.get.question_list_for_competition(competition_id)
return list_response(list_schema.dump(items))
......@@ -27,12 +27,12 @@ class QuestionList(Resource):
@api.route("/slides/<slide_id>/questions")
@api.param("competition_id, slide_id")
class QuestionListForSlide(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self, competition_id, slide_id):
items = dbc.get.question_list(competition_id, slide_id)
return list_response(list_schema.dump(items))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def post(self, competition_id, slide_id):
args = question_parser.parse_args(strict=True)
item = dbc.add.question(slide_id=slide_id, **args)
......@@ -42,12 +42,12 @@ class QuestionListForSlide(Resource):
@api.route("/slides/<slide_id>/questions/<question_id>")
@api.param("competition_id, slide_id, question_id")
class QuestionById(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self, competition_id, slide_id, question_id):
item_question = dbc.get.question(competition_id, slide_id, question_id)
return item_response(schema.dump(item_question))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def put(self, competition_id, slide_id, question_id):
args = question_parser.parse_args(strict=True)
......@@ -56,7 +56,7 @@ class QuestionById(Resource):
return item_response(schema.dump(item_question))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def delete(self, competition_id, slide_id, question_id):
item_question = dbc.get.question(competition_id, slide_id, question_id)
dbc.delete.question(item_question)
......
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core.dto import SlideDTO
from flask_restx import Resource
from flask_restx import reqparse
......@@ -19,12 +19,12 @@ slide_parser.add_argument("background_image_id", default=None, type=int, locatio
@api.route("")
@api.param("competition_id")
class SlidesList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self, competition_id):
items = dbc.get.slide_list(competition_id)
return list_response(list_schema.dump(items))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def post(self, competition_id):
item_slide = dbc.add.slide(competition_id)
return item_response(schema.dump(item_slide))
......@@ -33,12 +33,12 @@ class SlidesList(Resource):
@api.route("/<slide_id>")
@api.param("competition_id,slide_id")
class Slides(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self, competition_id, slide_id):
item_slide = dbc.get.slide(competition_id, slide_id)
return item_response(schema.dump(item_slide))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def put(self, competition_id, slide_id):
args = slide_parser.parse_args(strict=True)
......@@ -47,7 +47,7 @@ class Slides(Resource):
return item_response(schema.dump(item_slide))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def delete(self, competition_id, slide_id):
item_slide = dbc.get.slide(competition_id, slide_id)
......@@ -58,7 +58,7 @@ class Slides(Resource):
@api.route("/<slide_id>/order")
@api.param("competition_id,slide_id")
class SlideOrder(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def put(self, competition_id, slide_id):
args = slide_parser.parse_args(strict=True)
order = args.get("order")
......@@ -87,7 +87,7 @@ class SlideOrder(Resource):
@api.route("/<slide_id>/copy")
@api.param("competition_id,slide_id")
class SlideCopy(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def post(self, competition_id, slide_id):
item_slide = dbc.get.slide(competition_id, slide_id)
......
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core.dto import TeamDTO
from flask_restx import Resource, reqparse
from flask_restx import reqparse
......@@ -16,12 +16,12 @@ team_parser.add_argument("name", type=str, location="json")
@api.route("")
@api.param("competition_id")
class TeamsList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self, competition_id):
items = dbc.get.team_list(competition_id)
return list_response(list_schema.dump(items))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def post(self, competition_id):
args = team_parser.parse_args(strict=True)
item_team = dbc.add.team(args["name"], competition_id)
......@@ -31,19 +31,19 @@ class TeamsList(Resource):
@api.route("/<team_id>")
@api.param("competition_id,team_id")
class Teams(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self, competition_id, team_id):
item = dbc.get.team(competition_id, team_id)
return item_response(schema.dump(item))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def delete(self, competition_id, team_id):
item_team = dbc.get.team(competition_id, team_id)
dbc.delete.team(item_team)
return {}, codes.NO_CONTENT
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def put(self, competition_id, team_id):
args = team_parser.parse_args(strict=True)
name = args.get("name")
......
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import check_jwt, item_response, list_response
from app.apis import item_response, list_response, protect_route
from app.core.dto import UserDTO
from flask_jwt_extended import get_jwt_identity
from flask_restx import Resource
......@@ -40,12 +40,12 @@ def _edit_user(item_user, args):
@api.route("")
class UsersList(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self):
item = dbc.get.user(get_jwt_identity())
return item_response(schema.dump(item))
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def put(self):
args = user_parser.parse_args(strict=True)
item = dbc.get.user(get_jwt_identity())
......@@ -56,12 +56,12 @@ class UsersList(Resource):
@api.route("/<ID>")
@api.param("ID")
class Users(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self, ID):
item = dbc.get.user(ID)
return item_response(schema.dump(item))
@check_jwt(editor=False)
@protect_route(allowed_roles=["Admin"])
def put(self, ID):
args = user_parser.parse_args(strict=True)
item = dbc.get.user(ID)
......@@ -71,7 +71,7 @@ class Users(Resource):
@api.route("/search")
class UserSearch(Resource):
@check_jwt(editor=True)
@protect_route(allowed_roles=["*"])
def get(self):
args = user_search_parser.parse_args(strict=True)
items, total = dbc.search.user(**args)
......
......@@ -151,9 +151,13 @@ def competition(name, year, city_id):
# Add code for Judge view
code(2, item_competition.id)
# Add code for Audience view
code(3, item_competition.id)
# Add code for Operator view
code(4, item_competition.id)
item_competition = utils.refresh(item_competition)
return item_competition
......
......@@ -230,6 +230,8 @@ class Code(db.Model):
competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=False)
team_id = db.Column(db.Integer, db.ForeignKey("team.id"), nullable=True)
view_type = db.relationship("ViewType", uselist=False)
def __init__(self, code, view_type_id, competition_id=None, team_id=None):
self.code = code
self.view_type_id = view_type_id
......@@ -240,7 +242,6 @@ class Code(db.Model):
class ViewType(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
codes = db.relationship("Code", backref="view_type")
def __init__(self, name):
self.name = name
......
......@@ -3,7 +3,9 @@ This file tests the api function calls.
"""
import app.core.http_codes as codes
from app.database.controller.add import competition
from app.database.models import Slide
from app.core import sockets
from tests import app, client, db
from tests.test_helpers import add_default_values, change_order_test, delete, get, post, put
......@@ -342,7 +344,7 @@ def test_question_api(client):
slide_order = 1
response, body = get(client, f"/api/competitions/{CID}/questions", headers=headers)
assert response.status_code == codes.OK
assert body["count"] == 1
assert body["count"] == 2
# Get questions from another competition that should have some questions
CID = 3
......@@ -385,3 +387,67 @@ def test_question_api(client):
response, _ = delete(client, f"/api/competitions/{CID}/slides/{NEW_slide_order}/questions/{QID}", headers=headers)
assert response.status_code == codes.NOT_FOUND
"""
def test_authorization(client):
add_default_values()
# Fake that competition 1 is active
sockets.presentations[1] = {}
#### TEAM ####
# Login in with team code
response, body = post(client, "/api/auth/login/code", {"code": "111111"})
assert response.status_code == codes.OK
headers = {"Authorization": "Bearer " + body["access_token"]}
competition_id = body["competition_id"]
team_id = body["team_id"]
# Get competition team is in
response, body = get(client, f"/api/competitions/{competition_id}", headers=headers)
assert response.status_code == codes.OK
# Try to delete competition team is in
response, body = delete(client, f"/api/competitions/{competition_id}", headers=headers)
assert response.status_code == codes.UNAUTHORIZED
# Try to get a different competition
response, body = get(client, f"/api/competitions/{competition_id+1}", headers=headers)
assert response.status_code == codes.UNAUTHORIZED
# Get own answers
response, body = get(client, f"/api/competitions/{competition_id}/teams/{team_id}/answers", headers=headers)
assert response.status_code == codes.OK
# Try to get another teams answers
response, body = get(client, f"/api/competitions/{competition_id}/teams/{team_id+1}/answers", headers=headers)
assert response.status_code == codes.UNAUTHORIZED
#### JUDGE ####
# Login in with judge code
response, body = post(client, "/api/auth/login/code", {"code": "222222"})
assert response.status_code == codes.OK
headers = {"Authorization": "Bearer " + body["access_token"]}
competition_id = body["competition_id"]
# Get competition judge is in
response, body = get(client, f"/api/competitions/{competition_id}", headers=headers)
assert response.status_code == codes.OK
# Try to delete competition judge is in
response, body = delete(client, f"/api/competitions/{competition_id}", headers=headers)
assert response.status_code == codes.UNAUTHORIZED
# Try to get a different competition
response, body = get(client, f"/api/competitions/{competition_id+1}", headers=headers)
assert response.status_code == codes.UNAUTHORIZED
# Get team answers
response, body = get(client, f"/api/competitions/{competition_id}/teams/{team_id}/answers", headers=headers)
assert response.status_code == codes.OK
# Also get antoher teams answers
response, body = get(client, f"/api/competitions/{competition_id}/teams/{team_id+1}/answers", headers=headers)
assert response.status_code == codes.OK
\ No newline at end of file
......@@ -3,14 +3,14 @@ import json
import app.core.http_codes as codes
import app.database.controller as dbc
from app.core import db
from app.database.models import City, Role
from app.database.models import City, Code, Role
def add_default_values():
media_types = ["Image", "Video"]
question_types = ["Boolean", "Multiple", "Text"]
component_types = ["Text", "Image"]
view_types = ["Team", "Judge", "Audience"]
view_types = ["Team", "Judge", "Audience", "Operator"]
roles = ["Admin", "Editor"]
cities = ["Linköping", "Testköping"]
......@@ -40,6 +40,20 @@ def add_default_values():
# Add competitions
item_competition = dbc.add.competition("Tom tävling", 2012, item_city.id)
item_question = dbc.add.question("hej", 5, 1, item_competition.slides[0].id)
item_team1 = dbc.add.team("Hej lag 3", item_competition.id)
item_team2 = dbc.add.team("Hej lag 4", item_competition.id)
db.session.add(Code("111111", 1, item_competition.id, item_team1.id)) # Team
db.session.add(Code("222222", 2, item_competition.id)) # Judge
dbc.add.QuestionAnswer("hej", 5, item_question.id, item_team1)
dbc.add.QuestionAnswer("", 5, item_question.id, item_team2)
db.session.commit()
for j in range(2):
item_comp = dbc.add.competition(f"Tävling {j}", 2012, item_city.id)
# Add two more slides to competition
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment