Skip to content

Commit

Permalink
Merge pull request #1537 from ScilifelabDataCentre/dev
Browse files Browse the repository at this point in the history
New Release
  • Loading branch information
rv0lt authored Jun 28, 2024
2 parents 24e01fa + cdad1a7 commit e83cf75
Show file tree
Hide file tree
Showing 13 changed files with 3,033 additions and 70 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
Changelog
==========

.. _2.7.1:

2.7.1 - 2024-06-26
~~~~~~~~~~~~~~~~~~~~~~~

- New features:
- Fix the Project endpoint according to OpenAPI standard.
- Fix the Superadmin endpoint according to OpenAPI standard.
- Dependencies:
- `Authlib` from `0.15.5` to `1.3.1`
- `PyMySQL` from `1.0.2` to `1.1.1`
- Node modules:
- `braces` from `3.0.2` to `3.0.3`
- `fill-range` from `7.0.1` to `7.1.1`
- `ip` from `2.0.0` to `9.0.5`
- `socks` from `2.7.1` to `2.8.3`
- `tar` from `6.1.15` to `6.2.1`

.. _2.7.0:

2.7.0 - 2024-05-29
Expand Down
11 changes: 11 additions & 0 deletions SPRINTLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,3 +393,14 @@ _Nothing merged in CLI during this sprint_
- Fix raising error when archiving project, bucket deleted but DB error ([#1524](https://github.com/ScilifelabDataCentre/dds_web/pull/1524))
- Increase the identified less covered files([#1521](https://github.com/ScilifelabDataCentre/dds_web/pull/1521))
- Parse boolean inputs correctly ([#1528](https://github.com/ScilifelabDataCentre/dds_web/pull/1528))

# 2024-06-03 - 2024-06-14

- Fix the project endpoints according to the OpenAPI standard ([#1527](https://github.com/ScilifelabDataCentre/dds_web/pull/1527))
- Fix the Superadmin endpoints according to the OpenAPI standard ([#1533](https://github.com/ScilifelabDataCentre/dds_web/pull/1533))

# 2024-06-17 - 2024-06-28

- Update pymysql to address cve ([#1534](https://github.com/ScilifelabDataCentre/dds_web/pull/1534))
- Update authlib to address cve ([#1535](https://github.com/ScilifelabDataCentre/dds_web/pull/1535))
- Update node packages to address cve ([#1536](https://github.com/ScilifelabDataCentre/dds_web/pull/1536))
30 changes: 30 additions & 0 deletions dds_web/api/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

# Installed
import flask_restful
from flask_restful import inputs
import flask
import sqlalchemy
import datetime
Expand Down Expand Up @@ -59,6 +60,35 @@ class ProjectStatus(flask_restful.Resource):
@handle_validation_errors
def get(self):
"""Get current project status and optionally entire status history"""
if "api/v1" in flask.request.path:
# requests comming from api/v1 should be handled as before
return self.old_get()

elif "api/v3" in flask.request.path:
# Get project ID, project and verify access
project_id = dds_web.utils.get_required_item(obj=flask.request.args, req="project")
project = dds_web.utils.collect_project(project_id=project_id)
dds_web.utils.verify_project_access(project=project)

# Get current status and deadline
return_info = {"current_status": project.current_status}
if project.current_deadline:
return_info["current_deadline"] = project.current_deadline

# Get status history
history = flask.request.args.get("history", type=inputs.boolean, default=False)
if history:
history_info = []
for pstatus in project.project_statuses:
history_info.append(tuple((pstatus.status, pstatus.date_created)))
history_info.sort(key=lambda x: x[1], reverse=True)
return_info.update({"history": history_info})

return return_info

def old_get(self):
"""Implementation of old get method. Should be removed when api/v1 is removed."""

# Get project ID, project and verify access
project_id = dds_web.utils.get_required_item(obj=flask.request.args, req="project")
project = dds_web.utils.collect_project(project_id=project_id)
Expand Down
52 changes: 49 additions & 3 deletions dds_web/api/superadmin_only.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# Installed
import flask_restful
from flask_restful import inputs
import flask
import structlog
import flask_mail
Expand Down Expand Up @@ -204,11 +205,31 @@ class FindUser(flask_restful.Resource):

@auth.login_required(role=["Super Admin"])
@logging_bind_request
@json_required
@handle_db_error
def get(self):
"""Return users or a confirmation on if one exists."""
# Get request info
if "api/v1" in flask.request.path:
# requests comming from api/v1 should be handled as before
return self.old_get()

elif "api/v3" in flask.request.path:
"""Return all users or confirmation whether a specific user is in the database."""

# Get username from request
user_to_find = flask.request.args.get("username")
if not user_to_find:
raise ddserr.DDSArgumentError(
message="Username required to check existence of account."
)

return {
"exists": models.User.query.filter_by(username=user_to_find).one_or_none()
is not None
}

@json_required
def old_get(self):
"""Implementation of old get method. Should be removed when api/v1 is removed.""" # Get request info

request_json = flask.request.get_json(silent=True) # Verified by json_required

# Get username from request
Expand Down Expand Up @@ -303,6 +324,31 @@ class AnyProjectsBusy(flask_restful.Resource):
@handle_db_error
def get(self):
"""Check if any projects are busy."""
if "api/v1" in flask.request.path:
# requests comming from api/v1 should be handled as before
return self.old_get()

elif "api/v3" in flask.request.path:
# Get busy projects
projects_busy: typing.List = models.Project.query.filter_by(busy=True).all()
num_busy: int = len(projects_busy)

# Set info to always return nu
return_info: typing.Dict = {"num": num_busy}

# Return 0 if none are busy
if num_busy == 0:
return return_info

# Check if user listing busy projects
if flask.request.args.get("list", type=inputs.boolean, default=False):
return_info.update(
{"projects": {p.public_id: p.date_updated for p in projects_busy}}
)

return return_info

def old_get(self):
# Get busy projects
projects_busy: typing.List = models.Project.query.filter_by(busy=True).all()
num_busy: int = len(projects_busy)
Expand Down
9 changes: 5 additions & 4 deletions dds_web/security/project_user_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

import argon2
import cryptography.exceptions
from cryptography.hazmat.primitives import asymmetric, ciphers, hashes, serialization
from cryptography.hazmat.primitives import asymmetric, hashes, serialization
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import flask
import gc

Expand Down Expand Up @@ -178,7 +179,7 @@ def __encrypt_with_aes(key, plaintext, aad=None):
:param plaintext: a byte string
:param aad: Additional data that should be authenticated with the key, but is not encrypted. Can be None.
"""
aesgcm = ciphers.aead.AESGCM(key)
aesgcm = AESGCM(key)
nonce = os.urandom(12)
return nonce, aesgcm.encrypt(nonce, plaintext, aad)

Expand All @@ -192,7 +193,7 @@ def __decrypt_with_aes(key, ciphertext, nonce, aad=None):
:param aad: Additional data that should be authenticated with the key, but is not encrypted. Can be None.
"""
try:
aesgcm = ciphers.aead.AESGCM(key=key)
aesgcm = AESGCM(key=key)
return aesgcm.decrypt(nonce=nonce, data=ciphertext, associated_data=aad)
except (cryptography.exceptions.InvalidTag, ValueError):
return None
Expand All @@ -205,7 +206,7 @@ def __owner_identifier(owner):
def __encrypt_owner_private_key(owner, private_key, owner_key=None):
"""Encrypt owners private key."""
# Generate key or use current key if exists
key = owner_key or ciphers.aead.AESGCM.generate_key(bit_length=256)
key = owner_key or AESGCM.generate_key(bit_length=256)

# Encrypt private key
nonce, encrypted_key = __encrypt_with_aes(
Expand Down
Loading

0 comments on commit e83cf75

Please sign in to comment.