Skip to content

Commit b534556

Browse files
authored
Merge pull request #1349 from microbiomedata/main
Merge `main` into `berkeley-schema-migration`
2 parents 8e9d032 + 5fd1083 commit b534556

File tree

17 files changed

+162
-22
lines changed

17 files changed

+162
-22
lines changed

.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
# ORCID OAuth Setup
88
# NMDC_ORCID_CLIENT_ID=changeme
99
# NMDC_ORCID_CLIENT_SECRET=changeme
10+
#
11+
# Base URL (without a trailing slash) at which the application can access an instance of ORCID.
12+
# Note: For the production instance of ORCID, use: "https://orcid.org" (default)
13+
# For the sandbox instance of ORCID, use: "https://sandbox.orcid.org"
14+
# NMDC_ORCID_BASE_URL="https://orcid.org"
1015

1116
# MongoDB Ingest Setup
1217
# NMDC_MONGO_USER=changeme

docs/development.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ NMDC_ORCID_CLIENT_SECRET=changeme
3131
```bash
3232
NMDC_SESSION_SECRET_KEY=changeme
3333
NMDC_API_JWT_SECRET=changeme
34-
34+
```
3535
### Production Redirect URIs
3636

3737
These are the set of redirect URIs enabled in ORCiD. We need to file a support ticket with ORCID to modify these.

nmdc_server/api.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,10 @@ async def list_submissions(
633633
db: Session = Depends(get_db),
634634
user: models.User = Depends(get_current_user),
635635
pagination: Pagination = Depends(),
636+
column_sort: str = "created",
637+
sort_order: str = "desc",
636638
):
637-
query = crud.get_submissions_for_user(db, user)
639+
query = crud.get_submissions_for_user(db, user, column_sort, sort_order)
638640
return pagination.response(query)
639641

640642

@@ -671,6 +673,8 @@ async def get_submission(
671673
created=submission.created,
672674
author=schemas.User(**submission.author.__dict__),
673675
permission_level=permission_level,
676+
templates=submission.templates,
677+
study_name=submission.study_name,
674678
)
675679
if submission.locked_by is not None:
676680
submission_metadata_schema.locked_by = schemas.User(**submission.locked_by.__dict__)
@@ -938,8 +942,14 @@ async def submit_metadata(
938942
db: Session = Depends(get_db),
939943
user: models.User = Depends(get_current_user),
940944
):
941-
submission = SubmissionMetadata(**body.dict(), author_orcid=user.orcid)
945+
submission = SubmissionMetadata(
946+
**body.dict(),
947+
author_orcid=user.orcid,
948+
)
942949
submission.author_id = user.id
950+
submission.study_name = body.metadata_submission.studyForm.studyName
951+
submission.templates = body.metadata_submission.templates
952+
943953
db.add(submission)
944954
db.commit()
945955
owner_role = SubmissionRole(

nmdc_server/auth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
)
5959

6060
API_JWT_ALGORITHM = "HS256"
61-
ORCID_JWT_ISSUER = "https://orcid.org"
61+
ORCID_JWT_ISSUER = settings.orcid_base_url # e.g. "https://orcid.org", "https://sandbox.orcid.org"
6262

6363

6464
class JwtTypes(str, Enum):

nmdc_server/config.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,24 @@ class Settings(BaseSettings):
3333

3434
# for orcid oauth
3535
session_secret_key: str = "secret"
36+
orcid_base_url: str = "https://orcid.org"
3637
orcid_client_id: str = "oauth client id"
3738
orcid_client_secret: str = "oauth secret key"
38-
orcid_openid_config_url: str = "https://orcid.org/.well-known/openid-configuration"
3939
orcid_authorize_scope: str = "/authenticate"
4040

41+
@property
42+
def orcid_openid_config_url(self) -> str:
43+
r"""
44+
Derives the `orcid_openid_config_url` field's value based upon another field's value.
45+
Note: This project currently depends upon Pydantic version 1, which does not offer
46+
the `@computed_field` decorator offered by Pydantic version 2. So, we implement
47+
a "getter" method using Python's built-in `@property` decorator instead.
48+
References:
49+
- https://docs.python.org/3/library/functions.html#property
50+
- https://docs.pydantic.dev/2.7/concepts/fields/#the-computed_field-decorator
51+
"""
52+
return f"{self.orcid_base_url}/.well-known/openid-configuration"
53+
4154
# host name for the ORCID oauth2 redirect and our own JWT issuer
4255
host: str = "http://127.0.0.1:8000"
4356

nmdc_server/crud.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -629,10 +629,18 @@ def can_edit_entire_submission(db: Session, submission_id: str, user_orcid: str)
629629
return (role and models.SubmissionEditorRole(role.role) in contributors_edit_roles) is True
630630

631631

632-
def get_submissions_for_user(db: Session, user: models.User):
632+
def get_submissions_for_user(db: Session, user: models.User, column_sort: str, order: str):
633633
"""Return all submissions that a user has permission to view."""
634-
all_submissions = db.query(models.SubmissionMetadata).order_by(
635-
models.SubmissionMetadata.created.desc()
634+
column = (
635+
models.User.name
636+
if column_sort == "author.name"
637+
else getattr(models.SubmissionMetadata, column_sort)
638+
)
639+
640+
all_submissions = (
641+
db.query(models.SubmissionMetadata)
642+
.join(models.User, models.SubmissionMetadata.author_id == models.User.id)
643+
.order_by(column.asc() if order == "asc" else column.desc())
636644
)
637645

638646
if user.is_admin:

nmdc_server/fakes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ class Meta:
345345
author = SubFactory(UserFactory)
346346
author_orcid = Faker("pystr")
347347
status = "In Progress"
348+
study_name = Faker("word")
349+
templates = Faker("pylist", nb_elements=2, value_types=[str])
348350
created = datetime.utcnow()
349351
# TODO specify all fields!
350352
metadata_submission = {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""Add study_name and template columns to submission_metadata
2+
3+
Revision ID: 0ff690fb929d
4+
Revises: c0b36f8dc4b8
5+
Create Date: 2024-08-01 16:01:05.023371
6+
7+
"""
8+
9+
from typing import Optional
10+
11+
import sqlalchemy as sa
12+
from alembic import op
13+
from sqlalchemy.dialects.postgresql import JSONB
14+
from sqlalchemy.sql import column, table
15+
16+
# revision identifiers, used by Alembic.
17+
revision: str = "0ff690fb929d"
18+
down_revision: Optional[str] = "c0b36f8dc4b8"
19+
branch_labels: Optional[str] = None
20+
depends_on: Optional[str] = None
21+
22+
23+
def upgrade():
24+
# ### commands auto generated by Alembic - please adjust! ###
25+
op.add_column("submission_metadata", sa.Column("study_name", sa.String(), nullable=True))
26+
op.add_column(
27+
"submission_metadata",
28+
sa.Column("templates", JSONB(astext_type=sa.Text()), nullable=True), # type:ignore
29+
)
30+
submission_metadata = table(
31+
"submission_metadata",
32+
column("id", sa.String),
33+
column("metadata_submission", JSONB),
34+
column("study_name", sa.String),
35+
column("templates", JSONB),
36+
)
37+
38+
connection = op.get_bind()
39+
submissions = connection.execute(
40+
sa.select([submission_metadata.c.id, submission_metadata.c.metadata_submission])
41+
)
42+
43+
for submission in submissions:
44+
study_name = submission.metadata_submission["studyForm"].get("studyName")
45+
templates = submission.metadata_submission.get("templates")
46+
if study_name:
47+
connection.execute(
48+
submission_metadata.update()
49+
.where(submission_metadata.c.id == submission.id)
50+
.values(study_name=study_name)
51+
)
52+
if templates:
53+
connection.execute(
54+
submission_metadata.update()
55+
.where(submission_metadata.c.id == submission.id)
56+
.values(templates=templates)
57+
)
58+
# ### end Alembic commands ###
59+
60+
61+
def downgrade():
62+
# ### commands auto generated by Alembic - please adjust! ###
63+
op.drop_column("submission_metadata", "templates")
64+
op.drop_column("submission_metadata", "study_name")
65+
# ### end Alembic commands ###

nmdc_server/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,8 @@ class SubmissionMetadata(Base):
851851
status = Column(String, nullable=False, default="in-progress")
852852
metadata_submission = Column(JSONB, nullable=False)
853853
author_id = Column(UUID(as_uuid=True), ForeignKey(User.id))
854+
study_name = Column(String, nullable=True)
855+
templates = Column(JSONB, nullable=True)
854856

855857
# The client which initially created the submission. A null value indicates it was created by
856858
# an "unregistered" client. This could be legitimate usage, but it should be monitored.

nmdc_server/schemas_submission.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ class SubmissionMetadataSchema(SubmissionMetadataSchemaCreate):
111111
created: datetime
112112
status: str
113113
author: schemas.User
114+
templates: List[str]
115+
study_name: Optional[str]
114116

115117
lock_updated: Optional[datetime]
116118
locked_by: Optional[schemas.User]

0 commit comments

Comments
 (0)