Skip to content

Commit

Permalink
Merge branch 'main' into jdb/item-graph-configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
ml-evs authored Aug 1, 2024
2 parents 50fc5a1 + 51f0486 commit 84aa82c
Show file tree
Hide file tree
Showing 37 changed files with 1,102 additions and 215 deletions.
2 changes: 1 addition & 1 deletion .github/utils/update_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pipenv run invoke dev.set-version -v ${GITHUB_REF#refs/tags/}

echo "\n-o- Commit updates - Changelog -o-"
git add pydatalab/__init__.py
git commit -m "Release ${GITHUB_REF#refs/tags/}"
git commit --allow-empty -m "Release ${GITHUB_REF#refs/tags/}"

echo -e "\n-o- Update version tag -o-"
git tag -f ${GITHUB_REF#refs/tags/}
18 changes: 16 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ jobs:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 2
max-parallel: 3
matrix:
browser-backend: ["electron", "chrome"]
browser-backend: ["electron", "chrome", "firefox"]

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -158,5 +158,19 @@ jobs:
working-directory: ./webapp
record: true
browser: ${{ matrix.browser-backend }}
group: "End-to-end tests (${{ matrix.browser-backend }})"
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

- name: Run component tests
uses: cypress-io/github-action@v6
with:
working-directory: ./webapp
record: true
install: false
component: true
publish-summary: false
browser: ${{ matrix.browser-backend }}
group: "Component tests (${{ matrix.browser-backend }})"
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,51 @@
# Changelog

## v0.4.3 (July 2024

This release simply re-enables Firefox testing in the CI, and reorganises the associated cloud runs.

## What's Changed
* Re-enable Firefox e2e tests by @ml-evs in https://github.com/datalab-org/datalab/pull/711

**Full Changelog**: https://github.com/datalab-org/datalab/compare/v0.4.2...v0.4.3


## v0.4.2 (July 2024)

This release adds an update to the batch item creation UI to include other item types, and includes a new preview of the tabular UI which can be accessed at the path `/next`, as well as several UI tweaks and fixes.

## What's Changed

* Rebrand repo to the group-agnostic gh organisation by @ml-evs in https://github.com/datalab-org/datalab/pull/809
* Change docker compose restart policy to "unless-stopped" by @ml-evs in https://github.com/datalab-org/datalab/pull/810
* Update INSTALL.md by @jdbocarsly in https://github.com/datalab-org/datalab/pull/816
* Fix logo link taking full screen width by @ml-evs in https://github.com/datalab-org/datalab/pull/821
* Improve sample table component by @BenjaminCharmes in https://github.com/datalab-org/datalab/pull/784
* Add simple component test for `ChemFormInput` by @ml-evs in https://github.com/datalab-org/datalab/pull/743
* Add ability to add batch of cells by @jdbocarsly in https://github.com/datalab-org/datalab/pull/797
* Add config options to automatically activate accounts from GitHub, email or any auth source by @ml-evs in https://github.com/datalab-org/datalab/pull/822
* Bump version number to 0.4.2 by @ml-evs in https://github.com/datalab-org/datalab/pull/824

**Full Changelog**: https://github.com/datalab-org/datalab/compare/v0.4.1...v0.4.2

## v0.4.1 (July 2024)

This minor release adds some quality-of-life fixes to the UI, a new cell format type "in situ (optical)" and tweaks to our development workflow.

## What's Changed

* Run vue3-recommended linting by @jdbocarsly in https://github.com/the-grey-group/datalab/pull/756
* Corrected blockInfo computed property value by @BenjaminCharmes in https://github.com/the-grey-group/datalab/pull/775
* Changes to pre-commit by @jdbocarsly in https://github.com/the-grey-group/datalab/pull/785
* Add 'optical' cellFormat by @BenjaminCharmes in https://github.com/the-grey-group/datalab/pull/788
* Remove cheminventory import task (which is now in `datalab-api`) by @ml-evs in https://github.com/the-grey-group/datalab/pull/793
* Add gpt4o and other updated models by @jdbocarsly in https://github.com/the-grey-group/datalab/pull/736
* Report runtime server config at `/info` and use this in UI by @ml-evs in https://github.com/the-grey-group/datalab/pull/801
* Development docker, pre-commit and eslint updates & refactoring by @ml-evs in https://github.com/the-grey-group/datalab/pull/805
* Disable `ChemicalFormula` component by @ml-evs in https://github.com/the-grey-group/datalab/pull/806

**Full Changelog**: https://github.com/the-grey-group/datalab/compare/v0.4.0...v0.4.1

## v0.4.0 (June 2024)

This release of *datalab* contains significant new functionality whilst broadly maintaining compatibility with the 0.3.x series.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# <div align="center"><i>datalab</i></div>

<div align="center" style="padding-bottom: 5px">
<a href="https://public.datalab.odbx.science"><img src="https://img.shields.io/badge/try_it_out!-public_demo_server-orange?logo=firefox"></a>
<a href="https://demo.datalab-org.io"><img src="https://img.shields.io/badge/try_it_out!-public_demo_server-orange?logo=firefox"></a>
</div>

<div align="center">
Expand Down
2 changes: 1 addition & 1 deletion pydatalab/pydatalab/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.4.1"
__version__ = "0.4.3"
15 changes: 15 additions & 0 deletions pydatalab/pydatalab/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,21 @@ class ServerConfig(BaseSettings):
description="Whether to automatically activate accounts created via ORCID registration.",
)

GITHUB_AUTO_ACTIVATE_ACCOUNTS: bool = Field(
False,
description="Whether to automatically activate accounts created via GitHub registration.",
)

EMAIL_AUTO_ACTIVATE_ACCOUNTS: bool = Field(
False,
description="Whether to automatically activate accounts created via email registration.",
)

AUTO_ACTIVATE_ACCOUNTS: bool = Field(
False,
description="Whether to automatically activate accounts created via any registration method.",
)

EMAIL_DOMAIN_ALLOW_LIST: Optional[List[str]] = Field(
[],
description="A list of domains for which users will be able to register accounts if they have a matching verified email address, which still need to be verified by an admin. Setting the value to `None` will allow any email addresses at any domain to register *and activate* an account, otherwise the default `[]` will not allow any email addresses registration.",
Expand Down
11 changes: 10 additions & 1 deletion pydatalab/pydatalab/permissions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from functools import wraps
from typing import Any, Dict

from bson import ObjectId
from flask import request
from flask_login import current_user

Expand All @@ -10,6 +11,8 @@
from pydatalab.models.people import AccountStatus
from pydatalab.mongo import get_database

PUBLIC_USER_ID = ObjectId(24 * "0")


def active_users_or_get_only(func):
"""Decorator to ensure that only active user accounts can access the route,
Expand Down Expand Up @@ -81,7 +84,13 @@ def get_default_permissions(user_only: bool = True) -> Dict[str, Any]:
):
return {}

null_perm = {"$or": [{"creator_ids": {"$size": 0}}, {"creator_ids": {"$exists": False}}]}
null_perm = {
"$or": [
{"creator_ids": {"$size": 0}},
{"creator_ids": {"$in": [PUBLIC_USER_ID]}},
{"creator_ids": {"$exists": False}},
]
}
if current_user.is_authenticated and current_user.person is not None:
# find managed users under the given user (can later be expanded to groups)
managed_users = list(
Expand Down
11 changes: 9 additions & 2 deletions pydatalab/pydatalab/routes/v0_1/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,11 @@ def email_logged_in():
raise UserRegistrationForbidden

create_account = AccountStatus.UNVERIFIED
if CONFIG.EMAIL_DOMAIN_ALLOW_LIST is None:
if (
CONFIG.EMAIL_DOMAIN_ALLOW_LIST is None
or CONFIG.EMAIL_AUTO_ACTIVATE_ACCOUNTS
or CONFIG.AUTO_ACTIVATE_ACCOUNTS
):
create_account = AccountStatus.ACTIVE

find_create_or_modify_user(
Expand Down Expand Up @@ -426,6 +430,9 @@ def github_logged_in(blueprint, token):
elif CONFIG.GITHUB_ORG_ALLOW_LIST is None:
create_account = True

if CONFIG.GITHUB_AUTO_ACTIVATE_ACCOUNTS or CONFIG.AUTO_ACTIVATE_ACCOUNTS:
create_account = AccountStatus.ACTIVE

find_create_or_modify_user(
github_user_id,
IdentityType.GITHUB,
Expand All @@ -452,7 +459,7 @@ def orcid_logged_in(_, token):

# New ORCID accounts must be activated by an admin unless configured otherwise
create_account = AccountStatus.UNVERIFIED
if CONFIG.ORCID_AUTO_ACTIVATE_ACCOUNTS:
if CONFIG.ORCID_AUTO_ACTIVATE_ACCOUNTS or CONFIG.AUTO_ACTIVATE_ACCOUNTS:
create_account = AccountStatus.ACTIVE

find_create_or_modify_user(
Expand Down
4 changes: 1 addition & 3 deletions pydatalab/pydatalab/routes/v0_1/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,7 @@ def create_collection():

if CONFIG.TESTING:
data["creator_ids"] = [24 * "0"]
data["creators"] = [
{"display_name": "Public testing user", "contact_email": "datalab@odbx.science"}
]
data["creators"] = [{"display_name": "Public testing user"}]
else:
data["creator_ids"] = [current_user.person.immutable_id]
data["creators"] = [
Expand Down
63 changes: 41 additions & 22 deletions pydatalab/pydatalab/routes/v0_1/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from pydatalab.models.relationships import RelationshipType
from pydatalab.models.utils import generate_unique_refcode
from pydatalab.mongo import flask_mongo
from pydatalab.permissions import active_users_or_get_only, get_default_permissions
from pydatalab.permissions import PUBLIC_USER_ID, active_users_or_get_only, get_default_permissions

ITEMS = Blueprint("items", __name__)

Expand Down Expand Up @@ -396,17 +396,16 @@ def _create_sample(
"negative_electrode",
"electrolyte",
):
if copied_doc.get(component):
existing_consituent_ids = [
constituent["item"].get("item_id", None)
for constituent in copied_doc[component]
]
copied_doc[component] += [
constituent
for constituent in sample_dict.get(component, [])
if constituent["item"].get("item_id", None) is None
or constituent["item"].get("item_id") not in existing_consituent_ids
]
existing_consituent_ids = [
constituent["item"].get("item_id", None)
for constituent in copied_doc[component]
]
copied_doc[component] += [
constituent
for constituent in sample_dict.get(component, [])
if constituent["item"].get("item_id", None) is None
or constituent["item"].get("item_id") not in existing_consituent_ids
]

sample_dict = copied_doc

Expand All @@ -424,10 +423,10 @@ def _create_sample(
)

sample_dict.pop("refcode", None)
type = sample_dict["type"]
if type not in ITEM_MODELS:
type_ = sample_dict["type"]
if type_ not in ITEM_MODELS:
raise RuntimeError("Invalid type")
model = ITEM_MODELS[type]
model = ITEM_MODELS[type_]

## the following code was used previously to explicitely check schema properties.
## it doesn't seem to be necessary now, with extra = "ignore" turned on in the pydantic models,
Expand All @@ -437,19 +436,18 @@ def _create_sample(
# new_sample = {k: sample_dict[k] for k in schema["properties"] if k in sample_dict}
new_sample = sample_dict

if type in ("starting_materials", "equipment"):
if type_ in ("starting_materials", "equipment"):
# starting_materials and equipment are open to all in the deploment at this point,
# so no creators are assigned
new_sample["creator_ids"] = []
new_sample["creators"] = []
elif CONFIG.TESTING:
# Set fake ID to ObjectId("000000000000000000000000") so a dummy user can be created
# locally for testing creator UI elements
new_sample["creator_ids"] = [24 * "0"]
new_sample["creator_ids"] = [PUBLIC_USER_ID]
new_sample["creators"] = [
{
"display_name": "Public testing user",
"contact_email": "datalab@odbx.science",
}
]
else:
Expand Down Expand Up @@ -632,10 +630,13 @@ def delete_sample():
)


@ITEMS.route("/items/<refcode>", methods=["GET"])
@ITEMS.route("/get-item-data/<item_id>", methods=["GET"])
def get_item_data(item_id, load_blocks: bool = False):
def get_item_data(
item_id: str | None = None, refcode: str | None = None, load_blocks: bool = False
):
"""Generates a JSON response for the item with the given `item_id`,
additionally resolving relationships to files and other items.
or `refcode` additionally resolving relationships to files and other items.
Parameters:
load_blocks: Whether to regenerate any data blocks associated with this
Expand All @@ -644,12 +645,30 @@ def get_item_data(item_id, load_blocks: bool = False):
"""

if item_id:
match = {"item_id": item_id}
elif refcode:
if not len(refcode.split(":")) == 2:
refcode = f"{CONFIG.IDENTIFIER_PREFIX}:{refcode}"

match = {"refcode": refcode}
else:
return (
jsonify(
{
"status": "error",
"message": "No item_id or refcode provided.",
}
),
400,
)

# retrieve the entry from the database:
cursor = flask_mongo.db.items.aggregate(
[
{
"$match": {
"item_id": item_id,
**match,
**get_default_permissions(user_only=False),
}
},
Expand All @@ -673,7 +692,7 @@ def get_item_data(item_id, load_blocks: bool = False):
jsonify(
{
"status": "error",
"message": f"No matching item {item_id=} with current authorization.",
"message": f"No matching items for {match=} with current authorization.",
}
),
404,
Expand Down
7 changes: 6 additions & 1 deletion pydatalab/pydatalab/send_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from flask_mail import Mail, Message

from pydatalab.config import CONFIG
from pydatalab.logger import LOGGER

MAIL = Mail()
Expand All @@ -22,8 +23,12 @@ def send_mail(recipient: str, subject: str, body: str):
"""
LOGGER.debug("Sending email to %s", recipient)

sender = None
if CONFIG.EMAIL_AUTH_SMTP_SETTINGS is not None:
sender = CONFIG.EMAIL_AUTH_SMTP_SETTINGS.MAIL_DEFAULT_SENDER

message = Message(
sender="datalab@odbx.science",
sender=sender,
recipients=[recipient],
body=body,
subject=subject,
Expand Down
Loading

0 comments on commit 84aa82c

Please sign in to comment.