diff --git a/.dev-js/package.json b/.dev-js/package.json new file mode 100644 index 0000000000000000000000000000000000000000..f1a3b8b143115ffb8f0fee2d452ec2830cd888a3 --- /dev/null +++ b/.dev-js/package.json @@ -0,0 +1,14 @@ +{ + "name": "aleksis-builddeps", + "version": "1.0.0", + "dependencies": { + "@intlify/eslint-plugin-vue-i18n": "^2.0.0", + "eslint": "^8.26.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-vue": "^9.7.0", + "prettier": "^3.0.0", + "stylelint": "^15.0.0", + "stylelint-config-prettier": "^9.0.3", + "stylelint-config-standard": "^34.0.0" + } +} diff --git a/aleksis/apps/cursus/frontend/components/SubjectChip.vue b/aleksis/apps/cursus/frontend/components/SubjectChip.vue index 266fae9eb345c0ef88cc36b3263624e8e6b2db4a..a341d1873303ed81aa5d5484ea38f213e30f10d8 100644 --- a/aleksis/apps/cursus/frontend/components/SubjectChip.vue +++ b/aleksis/apps/cursus/frontend/components/SubjectChip.vue @@ -11,6 +11,11 @@ export default { required: false, default: false, }, + appendIcon: { + type: String, + default: null, + required: false, + }, }, }; </script> @@ -18,5 +23,6 @@ export default { <template> <v-chip :color="subject.colourBg" :text-color="subject.colourFg"> {{ shortName ? subject.shortName : subject.name }} + <v-icon right v-if="appendIcon">{{ appendIcon }}</v-icon> </v-chip> </template> diff --git a/aleksis/apps/cursus/schema.py b/aleksis/apps/cursus/schema.py index a1e05e811e28bdac0936ba5a1c7b6d71d992a705..33ed506581ae9c5e1d2e5b512818769988a61713 100644 --- a/aleksis/apps/cursus/schema.py +++ b/aleksis/apps/cursus/schema.py @@ -138,7 +138,11 @@ class CourseType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectType): @staticmethod def resolve_groups(root, info, **kwargs): - return get_objects_for_user(info.context.user, "core.view_group", root.groups.all()) + by_permission = get_objects_for_user( + info.context.user, "core.view_group", root.groups.all() + ) + by_ownership = info.context.user.person.owner_of.all() & root.groups.all() + return by_permission | by_ownership @staticmethod def resolve_course_id(root, info, **kwargs): @@ -267,10 +271,7 @@ class Query(graphene.ObjectType): def resolve_courses_of_teacher(root, info, teacher=None): if not has_person(info.context.user): raise PermissionDenied() - if teacher: - teacher = Person.objects.get(pk=teacher) - else: - teacher = info.context.user.person + teacher = Person.objects.get(pk=teacher) if teacher else info.context.user.person # FIXME: Permission checking. But maybe it's done in get_queryset return teacher.courses_as_teacher.all() diff --git a/pyproject.toml b/pyproject.toml index a3880633acc0e55c1cf933ec60188fa4d5e5d57f..0a229883233684df0f867b218f33de2c27503df0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ priority = "primary" name = "gitlab" url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple" priority = "supplemental" + [tool.poetry.dependencies] python = "^3.10" aleksis-core = "^4.0.0.dev3" @@ -44,19 +45,7 @@ cursus = "aleksis.apps.cursus.apps:DefaultConfig" django-stubs = "^4.2" safety = "^2.3.5" -flake8 = "^6.0.0" -flake8-django = "^1.0.0" -flake8-fixme = "^1.1.1" -flake8-bandit = "^4.1.1" -flake8-builtins = "^2.0.0" -flake8-docstrings = "^1.5.0" -flake8-rst-docstrings = "^0.3.0" - -black = ">=21.0" -flake8-black = "^0.3.0" - -isort = "^5.0.0" -flake8-isort = "^6.0.0" +ruff = "^0.1.5" curlylint = "^0.13.0" @@ -79,10 +68,6 @@ sphinxcontrib-svg2pdfconverter = "^1.1.1" sphinx-autodoc-typehints = "^1.7" sphinx_material = "^0.0.35" -[tool.black] -line-length = 100 -exclude = "/migrations/" - [tool.curlylint] include = '\.html' @@ -95,6 +80,21 @@ meta_viewport = true no_autofocus = true tabindex_no_positive = true + +[tool.ruff] +exclude = ["migrations", "tests"] +line-length = 100 + +[tool.ruff.lint] +select = ["E", "F", "UP", "B", "SIM", "I", "DJ", "A", "S"] +ignore = ["UP034", "UP015", "B028"] + +[tool.ruff.isort] +known-first-party = ["aleksis"] +section-order = ["future", "standard-library", "django", "third-party", "first-party", "local-folder"] + +[tool.ruff.isort.sections] +django = ["django"] [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" diff --git a/tox.ini b/tox.ini index 85c2494a5a2f5480bb05d48781edfaa74803eeab..294e65bc96d4e06262b67e3e6b8a987307b226e4 100644 --- a/tox.ini +++ b/tox.ini @@ -4,11 +4,12 @@ skip_missing_interpreters = true envlist = py39,py310,py311 [testenv] -allowlist_externals = poetry +allowlist_externals = + poetry + yarnpkg skip_install = true -envdir = {toxworkdir}/globalenv commands_pre = - poetry install + poetry install --all-extras poetry run aleksis-admin vite build poetry run aleksis-admin collectstatic --no-input commands = @@ -22,14 +23,17 @@ setenv = TEST_HOST = {env:TEST_HOST:172.17.0.1} [testenv:lint] +commands_pre = + poetry install --only=dev + yarnpkg --cwd=.dev-js commands = - poetry run black --check --diff aleksis/ - poetry run isort -c --diff --stdout aleksis/ - poetry run flake8 {posargs} aleksis/ - poetry run sh -c "aleksis-admin yarn run prettier --check --ignore-path={toxinidir}/.prettierignore {toxinidir}" - poetry run sh -c "aleksis-admin yarn run eslint {toxinidir}/aleksis/**/*/frontend/**/*.{js,vue} --config={toxinidir}/.eslintrc.js --resolve-plugins-relative-to=." + poetry run ruff check {posargs} aleksis/ + yarnpkg --cwd=.dev-js run prettier --ignore-path={toxinidir}/.prettierignore {posargs} --check .. + yarnpkg --cwd=.dev-js run eslint ../aleksis/**/*/frontend/**/*.{js,vue} --config={toxinidir}/.eslintrc.js --resolve-plugins-relative-to=. [testenv:security] +commands_pre = + poetry install --all-extras commands = poetry show --no-dev poetry run safety check --full-report @@ -41,33 +45,25 @@ commands_pre = commands = poetry build [testenv:docs] +commands_pre = + poetry install --with docs commands = poetry run make -C docs/ html {posargs} [testenv:reformat] +commands_pre = + poetry install --only=dev + yarnpkg --cwd=.dev-js commands = - poetry run isort aleksis/ - poetry run black aleksis/ - poetry run sh -c "aleksis-admin yarn run prettier --write --ignore-path={toxinidir}/.prettierignore {toxinidir}" + poetry run ruff format aleksis/ + yarnpkg --cwd=.dev-js run prettier --ignore-path={toxinidir}/.prettierignore --write .. [testenv:makemessages] +commands_pre = + poetry install commands = poetry run aleksis-admin makemessages --no-wrap -e html,txt,py,email -i static -l ar -l de_DE -l fr -l nb_NO -l tr_TR -l la -l uk -l ru poetry run aleksis-admin makemessages --no-wrap -d djangojs -i **/node_modules -l ar -l de_DE -l fr -l nb_NO -l tr_TR -l la -l uk -l ru -[flake8] -max_line_length = 100 -exclude = migrations,tests -ignore = BLK100,E203,E231,W503,D100,D101,D102,D103,D104,D105,D106,D107,RST215,RST214,F821,F841,S106,T100,T101,DJ05 - -[isort] -profile = black -line_length = 100 -default_section = THIRDPARTY -known_first_party = aleksis -known_django = django -skip = migrations -sections = FUTURE,STDLIB,DJANGO,THIRDPARTY,FIRSTPARTY,LOCALFOLDER - [pytest] DJANGO_SETTINGS_MODULE = aleksis.core.settings junit_family = legacy