Commit fea64741 authored by Barbora Kompišová's avatar Barbora Kompišová
Browse files

fixes, refactor

parent b015ce64
.idea/
*.pyc
__pycache__/
./coverage
.coverage
.pytest_cache/
portal.local.cfg
\ No newline at end of file
portal.local.cfg
Pipfile.lock
# This file is a template, and might need editing before it works on your project.
# Official framework image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/python
image: python:latest
# This folder is cached between builds
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
paths:
- ~/.cache/pip/
stages:
- build
build:
stage: build
tags:
- shared-fi
before_script:
- python -V # Print out python version for debugging
- pip install pipenv
script:
- pipenv install --dev
- pipenv run coverage run -m pytest
......@@ -2,10 +2,13 @@ FROM kontr2/base-pipenv
MAINTAINER barbora.kompisova@gmail.com
ADD . /portal
WORKDIR /portal
ADD . /app
WORKDIR /app
EXPOSE 8000
ONBUILD COPY Pipfile Pipfile
ONBUILD COPY Pipfile.lock Pipfile.lock
RUN pipenv install --system
ENTRYPOINT ["sh", "run.sh"]
......
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[packages]
flask = "*"
flask-sqlalchemy = "*"
pytest = "*"
flask-restful = "*"
marshmallow = "*"
flask-jwt-extended = "*"
marshmallow-enum = "*"
storage = { git="git@gitlab.fi.muni.cz:grp-kontr2/kontr-storage-module.git", editable='true' }
gitpython = "*"
flask-oauthlib = "*"
pyopenssl = "*"
gunicorn = "*"
flask-cors = "*"
[dev-packages]
pytest-cov = "*"
[requires]
python_version = "3.6"
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[packages]
flask = "*"
flask-sqlalchemy = "*"
pytest = "*"
flask-restful = "*"
marshmallow = "*"
flask-jwt-extended = "*"
marshmallow-enum = "*"
storage = {git = "git@gitlab.fi.muni.cz:grp-kontr2/kontr-storage-module.git", editable = true, ref = "master"}
gitpython = "*"
flask-oauthlib = "*"
pyopenssl = "*"
gunicorn = "*"
flask-cors = "*"
flask-emails = "*"
pytz = "*"
[dev-packages]
pytest-cov = "*"
[requires]
python_version = "3.6"
{
"_meta": {
"hash": {
"sha256": "698ae5f8e4b0e76fd498f674aa184274a02e9647ed8c70b732c28e94cd570e96"
},
"host-environment-markers": {
"implementation_name": "cpython",
"implementation_version": "3.6.4",
"os_name": "nt",
"platform_machine": "AMD64",
"platform_python_implementation": "CPython",
"platform_release": "10",
"platform_system": "Windows",
"platform_version": "10.0.16299",
"python_full_version": "3.6.4",
"python_version": "3.6",
"sys_platform": "win32"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.6"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.python.org/simple",
"verify_ssl": true
}
]
},
"default": {
"aniso8601": {
"hashes": [
"sha256:f7052eb342bf2000c6264a253acedb362513bf9270800be2bc8e3e229fe08b5a",
"sha256:7cf068e7aec00edeb21879c2bbda048656c34d281e133a77425be03b352122d8"
],
"version": "==3.0.0"
},
"asn1crypto": {
"hashes": [
"sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87",
"sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49"
],
"version": "==0.24.0"
},
"attrs": {
"hashes": [
"sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450",
"sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"
],
"version": "==17.4.0"
},
"certifi": {
"hashes": [
"sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0",
"sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7"
],
"version": "==2018.4.16"
},
"cffi": {
"hashes": [
"sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50",
"sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596",
"sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef",
"sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743",
"sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f",
"sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31",
"sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04",
"sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6",
"sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3",
"sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6",
"sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b",
"sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca",
"sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e",
"sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb",
"sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd",
"sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1",
"sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917",
"sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359",
"sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f",
"sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95",
"sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801",
"sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257",
"sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184",
"sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc",
"sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085",
"sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93",
"sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4"
],
"markers": "platform_python_implementation != 'PyPy'",
"version": "==1.11.5"
},
"chardet": {
"hashes": [
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
],
"version": "==3.0.4"
},
"click": {
"hashes": [
"sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
"sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
],
"version": "==6.7"
},
"colorama": {
"hashes": [
"sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda",
"sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"
],
"markers": "sys_platform == 'win32'",
"version": "==0.3.9"
},
"cryptography": {
"hashes": [
"sha256:abd070b5849ed64e6d349199bef955ee0ad99aefbad792f0c587f8effa681a5e",
"sha256:3f3b65d5a16e6b52fba63dc860b62ca9832f51f1a2ae5083c78b6840275f12dd",
"sha256:77d0ad229d47a6e0272d00f6bf8ac06ce14715a9fd02c9a97f5a2869aab3ccb2",
"sha256:808fe471b1a6b777f026f7dc7bd9a4959da4bfab64972f2bbe91e22527c1c037",
"sha256:6fef51ec447fe9f8351894024e94736862900d3a9aa2961528e602eb65c92bdb",
"sha256:60bda7f12ecb828358be53095fc9c6edda7de8f1ef571f96c00b2363643fa3cd",
"sha256:5cb990056b7cadcca26813311187ad751ea644712022a3976443691168781b6f",
"sha256:c332118647f084c983c6a3e1dba0f3bcb051f69d12baccac68db8d62d177eb8a",
"sha256:f57008eaff597c69cf692c3518f6d4800f0309253bb138b526a37fe9ef0c7471",
"sha256:551a3abfe0c8c6833df4192a63371aa2ff43afd8f570ed345d31f251d78e7e04",
"sha256:db6013746f73bf8edd9c3d1d3f94db635b9422f503db3fc5ef105233d4c011ab",
"sha256:d6f46e862ee36df81e6342c2177ba84e70f722d9dc9c6c394f9f1f434c4a5563",
"sha256:9b62fb4d18529c84b961efd9187fecbb48e89aa1a0f9f4161c61b7fc42a101bd",
"sha256:9e5bed45ec6b4f828866ac6a6bedf08388ffcfa68abe9e94b34bb40977aba531",
"sha256:f6c821ac253c19f2ad4c8691633ae1d1a17f120d5b01ea1d256d7b602bc59887",
"sha256:ba6a774749b6e510cffc2fb98535f717e0e5fd91c7c99a61d223293df79ab351",
"sha256:9fc295bf69130a342e7a19a39d7bbeb15c0bcaabc7382ec33ef3b2b7d18d2f63"
],
"version": "==2.2.2"
},
"flask": {
"hashes": [
"sha256:0749df235e3ff61ac108f69ac178c9770caeaccad2509cb762ce1f65570a8856",
"sha256:49f44461237b69ecd901cc7ce66feea0319b9158743dd27a2899962ab214dac1"
],
"version": "==0.12.2"
},
"flask-cors": {
"hashes": [
"sha256:55eb3864b4290f939ff19a2250fcb47d8c0f63d250c6780b922629299d011ec8",
"sha256:ac4b81b3d90f5f18714c995c807f94501df8c9bbc22ef4261c1cd850748c3850",
"sha256:62ebc5ad80dc21ca0ea9f57466c2c74e24a62274af890b391790c260eb7b754b"
],
"version": "==3.0.3"
},
"flask-jwt-extended": {
"hashes": [
"sha256:349c6c202ca3ef0cbbf53bd80f0f55db06e9bf077a1df02a92db08f73bbb0ed8"
],
"version": "==3.8.1"
},
"flask-oauthlib": {
"hashes": [
"sha256:3afd6b4bd886a3a38e30894dc1ecbb8781368a3ffc63bc84d6cbc94f1e29f553",
"sha256:bcd6f2f4f58c764824a1de31b9beae22585c5191992d298c0be0b3118dfcbdc6"
],
"version": "==0.9.4"
},
"flask-restful": {
"hashes": [
"sha256:e2f1b8063de3944b94c7f8be5cee4d2161db0267c54c5b757d875295061776fa",
"sha256:5795519501347e108c436b693ff9a4d7b373a3ac9069627d64e4001c05dd3407"
],
"version": "==0.3.6"
},
"flask-sqlalchemy": {
"hashes": [
"sha256:3bc0fac969dd8c0ace01b32060f0c729565293302f0c4269beed154b46bec50b",
"sha256:5971b9852b5888655f11db634e87725a9031e170f37c0ce7851cf83497f56e53"
],
"version": "==2.3.2"
},
"gitdb2": {
"hashes": [
"sha256:cf9a4b68e8c4da8d42e48728c944ff7af2d8c9db303ac1ab32eac37aa4194b0e",
"sha256:b60e29d4533e5e25bb50b7678bbc187c8f6bcff1344b4f293b2ba55c85795f09"
],
"version": "==2.0.3"
},
"gitpython": {
"hashes": [
"sha256:05069e26177c650b3cb945dd543a7ef7ca449f8db5b73038b465105673c1ef61",
"sha256:c47cc31af6e88979c57a33962cbc30a7c25508d74a1b3a19ec5aa7ed64b03129"
],
"version": "==2.1.9"
},
"gunicorn": {
"hashes": [
"sha256:75af03c99389535f218cc596c7de74df4763803f7b63eb09d77e92b3956b36c6",
"sha256:eee1169f0ca667be05db3351a0960765620dad53f53434262ff8901b68a1b622"
],
"version": "==19.7.1"
},
"idna": {
"hashes": [
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4",
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f"
],
"version": "==2.6"
},
"itsdangerous": {
"hashes": [
"sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519"
],
"version": "==0.24"
},
"jinja2": {
"hashes": [
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
],
"version": "==2.10"
},
"markupsafe": {
"hashes": [
"sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"
],
"version": "==1.0"
},
"marshmallow": {
"hashes": [
"sha256:8740ada95f47fa19f905772aa4932dc5512226a90c30da5672d6d6bf3dd791a7",
"sha256:d3f31fe7be2106b1d783cbd0765ef4e1c6615505514695f33082805f929dd584"
],
"version": "==2.15.0"
},
"marshmallow-enum": {
"hashes": [
"sha256:f5ad5dd187bbdca3165159db34e7b26f8a16e75e44aee5fc648ef18a2bd37b42",
"sha256:022400a2196ba55d5e6de67e6e4991e232190d25cbe26efa302c2e889e55ebf1"
],
"version": "==1.4.1"
},
"more-itertools": {
"hashes": [
"sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e",
"sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea",
"sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44"
],
"version": "==4.1.0"
},
"oauthlib": {
"hashes": [
"sha256:09d438bcac8f004ae348e721e9d8a7792a9e23cd574634e973173344046287f5",
"sha256:909665297635fa11fe9914c146d875f2ed41c8c2d78e21a529dd71c0ba756508"
],
"version": "==2.0.7"
},
"pluggy": {
"hashes": [
"sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c",
"sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5",
"sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
],
"version": "==0.6.0"
},
"py": {
"hashes": [
"sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a",
"sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881"
],
"version": "==1.5.3"
},
"pycparser": {
"hashes": [
"sha256:99a8ca03e29851d96616ad0404b4aad7d9ee16f25c9f9708a11faf2810f7b226"
],
"version": "==2.18"
},
"pyjwt": {
"hashes": [
"sha256:bca523ef95586d3a8a5be2da766fe6f82754acba27689c984e28e77a12174593",
"sha256:dacba5786fe3bf1a0ae8673874e29f9ac497860955c501289c63b15d3daae63a"
],
"version": "==1.6.1"
},
"pyopenssl": {
"hashes": [
"sha256:07a2de1a54de07448732a81e38a55df7da109b2f47f599f8bb35b0cbec69d4bd",
"sha256:2c10cfba46a52c0b0950118981d61e72c1e5b1aac451ca1bc77de1a679456773"
],
"version": "==17.5.0"
},
"pytest": {
"hashes": [
"sha256:6266f87ab64692112e5477eba395cfedda53b1933ccd29478e671e73b420c19c",
"sha256:fae491d1874f199537fd5872b5e1f0e74a009b979df9d53d1553fd03da1703e1"
],
"version": "==3.5.0"
},
"pytz": {
"hashes": [
"sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555",
"sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749"
],
"version": "==2018.4"
},
"requests": {
"hashes": [
"sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
"sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
],
"version": "==2.18.4"
},
"requests-oauthlib": {
"hashes": [
"sha256:50a8ae2ce8273e384895972b56193c7409601a66d4975774c60c2aed869639ca",
"sha256:883ac416757eada6d3d07054ec7092ac21c7f35cb1d2cf82faf205637081f468"
],
"version": "==0.8.0"
},
"six": {
"hashes": [
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
],
"version": "==1.11.0"
},
"smmap2": {
"hashes": [
"sha256:b78ee0f1f5772d69ff50b1cbdb01b8c6647a8354f02f23b488cf4b2cfc923956",
"sha256:c7530db63f15f09f8251094b22091298e82bf6c699a6b8344aaaef3f2e1276c3"
],
"version": "==2.0.3"
},
"sqlalchemy": {
"hashes": [
"sha256:7cb00cc9b9f92ef8b4391c8a2051f81eeafefe32d63c6b395fd51401e9a39edb"
],
"version": "==1.2.6"
},
"storage": {
"editable": "true",
"git": "git@gitlab.fi.muni.cz:grp-kontr2/kontr-storage-module.git"
},
"urllib3": {
"hashes": [
"sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
"sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
],
"version": "==1.22"
},
"werkzeug": {
"hashes": [
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b",
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c"
],
"version": "==0.14.1"
}
},
"develop": {}
}
import portal.tools.logging
from flask import Flask
from flask_cors import CORS
from flask_jwt_extended import JWTManager
......@@ -14,12 +16,7 @@ db = SQLAlchemy()
jwt = JWTManager()
oauth = OAuth()
cors = CORS(resources=r'*', origins=[r'http://localhost:4200/*', 'https://*.pstanko.net/*'], supports_credentials=True)
# TODO - urgent
storage = Storage({
"submissions_dir": "todo",
"test_files_dir": "todo",
"workspace_dir": "todo"
})
storage = Storage()
def config_app(flask_app):
......@@ -29,15 +26,25 @@ def config_app(flask_app):
if config_object is None:
raise RuntimeError()
flask_app.config.from_object(config_object)
flask_app.config.from_pyfile(ROOT_DIR + '/portal.local.cfg', silent=True)
flask_app.config.from_pyfile(ROOT_DIR / 'portal.local.cfg', silent=True)
flask_app.config.from_envvar('PORTAL_CONFIG', silent=True)
# app.logger.removeHandler(default_handler) # from Flask release 1.0, not yet available
def configure_storage(app):
storage_config = dict(
test_files_dir=app.config.get('KONTR_STORAGE_TEST_FILES_DIR'),
submissions_dir=app.config.get('KONTR_STORAGE_SUBMISSIONS_DIR'),
workspace_dir=app.config.get('KONTR_STORAGE_WORKSPACE_DIR')
)
storage.init_storage(**storage_config)
def create_app():
app = Flask('portal')
# app configuration
config_app(app)
configure_storage(app)
# database bind to app
db.init_app(app)
# init the jwt
......
import logging
import os
import tempfile
log = logging.getLogger(__name__)
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY') or 'super-safe'
JWT_EXPIRATION_DELTA = 600
LOGGER_NAME = "flask"
API_PREFIX = os.environ.get('PORTAL_API_PREFIX', default="/api/v1.0/")
class DevelopmentConfig(Config):
print('configuring with devel config')
SQLALCHEMY_DATABASE_URI = 'sqlite://'
SQLALCHEMY_TRACK_MODIFICATIONS = True
JWT_EXPIRATION_DELTA = 300
DEBUG = True
......@@ -20,10 +25,13 @@ class ProductionConfig(Config):
class TestConfig(Config):
SQLALCHEMY_DATABASE_URI = 'sqlite://'
SQLALCHEMY_TRACK_MODIFICATIONS = False
TESTING = True
#SQLALCHEMY_ECHO = True
# SQLALCHEMY_ECHO = True
KONTR_STORAGE_BASE_DIR = tempfile.mkdtemp()
KONTR_STORAGE_TEST_FILES_DIR = f"{KONTR_STORAGE_BASE_DIR}/test-files"
KONTR_STORAGE_WORKSPACE_DIR = f"{KONTR_STORAGE_BASE_DIR}/workspace"
KONTR_STORAGE_SUBMISSIONS_DIR = f"{KONTR_STORAGE_BASE_DIR}/submissions"
CONFIGURATIONS = dict(
......@@ -31,4 +39,3 @@ CONFIGURATIONS = dict(
test=TestConfig(),
production=ProductionConfig()
)
......@@ -2,6 +2,7 @@ import uuid
import enum
import datetime
import pytz
from flask_sqlalchemy import BaseQuery
from sqlalchemy import event
from sqlalchemy.ext.hybrid import hybrid_property
......@@ -17,6 +18,7 @@ from portal.tools import time
# uuid as primary key source:
# https://stackoverflow.com/questions/36806403/cant-render-element-of-type-class-sqlalchemy-dialects-postgresql-base-uuid
from portal.tools.time import normalize_time
def _repr(instance):
......@@ -111,7 +113,7 @@ class User(db.Model, EntityBase):
.filter(Project.id == project.id)
return base_query.join(Group.users).filter(User.id == self.id)
def get_groups_in_course(self, course: 'Course', project: 'Project') -> list:
def get_groups_in_course(self, course: 'Course', project: 'Project' = None) -> list:
"""Gers user's groups for course and project(optional)
Args:
......@@ -136,7 +138,7 @@ class User(db.Model, EntityBase):
groups = self.query_groups_in_course(course=course, project=project).subquery()
grp_alias = aliased(Group)
return User.query.join(grp_alias, User.groups) \
.join(groups).join(User.roles).filter(Role == role)
.join(groups).join(User.roles).filter(Role.id == role.id)
def get_users_in_group_based_on_role(self, course: 'Course', project: 'Project',
role: 'Role') -> list:
......@@ -152,6 +154,15 @@ class User(db.Model, EntityBase):
return self.query_users_in_group_based_on_role(course=course, project=project,
role=role).all()
def query_permissions_for_course(self, course: 'Course'):
permissions = RolePermissions.query.join(RolePermissions.role)\
.filter_by(course=course) \
.join(Role.users).filter(User.id == self.id)
return permissions
def get_permissions_for_course(self, course: 'Course'):
return self.query_permissions_for_course(course=course).all()
def __init__(self, uco, email, username, is_admin=False) -> None:
self.uco = uco
self.email = email
......@@ -227,7 +238,7 @@ class Project(db.Model, EntityBase):
db.UniqueConstraint('course_id', 'name', name='course_unique_name'),
)
def state(self, timestamp=datetime.datetime.now()) -> ProjectState:
def state(self, timestamp=time.NOW()) -> ProjectState:
if not (self.config.submissions_allowed_from or self.config.submissions_allowed_to or self.config.archive_from):
return ProjectState.INACTIVE