Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
280 commits
Select commit Hold shift + click to select a range
a4c43e0
Endpoint to save changes for the new layer (#199)
mepripri Mar 31, 2025
22e9a2d
keep in line with main
thehabes Apr 2, 2025
747b7e0
Create sample.env
cubap Apr 2, 2025
bb9598f
Update sample.env
cubap Apr 3, 2025
c14dcf8
Update CODEOWNERS
cubap Apr 3, 2025
6348b32
Merge pull request #212 from CenterForDigitalHumanities/91-create-sam…
mepripri Apr 3, 2025
09dbb0c
dev it and hotkeys
cubap Apr 3, 2025
de8f371
Merge branch '91-create-sampleenv-file' into development
cubap Apr 3, 2025
7baff4b
188 epic middleware to upgrade imported manifests (#209)
cubap Apr 4, 2025
bc2ff72
139 factor out type type dependencies (#211)
cubap Apr 4, 2025
726a2dc
align with main
thehabes Apr 4, 2025
df9c0ab
Merge branch 'main' into development
thehabes Apr 4, 2025
6ca236e
Update driver.mjs (#217)
cubap Apr 4, 2025
ee38a05
188 epic middleware to upgrade imported manifests (#218)
cubap Apr 4, 2025
a05f665
hulk smash 👊🏽
cubap Apr 4, 2025
3f69eae
_sub is no longer missing on invitees
cubap Apr 7, 2025
5463482
add temp sub to new user
cubap Apr 7, 2025
4271df8
Update cd_dev.yaml
cubap Apr 7, 2025
24c38aa
Update cd_dev.yaml
cubap Apr 7, 2025
923196a
stop if things are missing
cubap Apr 7, 2025
7d97630
adding verify on main
cubap Apr 7, 2025
c2922a4
Removing fileSystem from Github API (#214)
mepripri Apr 10, 2025
94af054
220 services for bug reporting and feedback (#221)
cubap Apr 10, 2025
c5822ee
cicd (#222)
cubap Apr 10, 2025
73112d3
220 services for bug reporting and feedback (#224)
cubap Apr 14, 2025
5ce579a
API call to Update Profile (#223)
mepripri Apr 16, 2025
b87b731
Save AnnotationCollection, Pages and Annotations to RERUM (#215)
mepripri Apr 23, 2025
e9971bc
Update index.mjs
mepripri Apr 25, 2025
5dd077e
Update index.mjs
mepripri Apr 25, 2025
0906084
Update index.mjs
mepripri Apr 25, 2025
6bf9c9a
Update index.mjs
mepripri Apr 25, 2025
afe664e
Update index.mjs
mepripri Apr 28, 2025
b646fb7
Import TPEN28 (#226)
mepripri Apr 28, 2025
f390c1b
Merge branch 'development' of https://github.com/CenterForDigitalHuma…
cubap Apr 28, 2025
fd23a3e
Test restoration (#229)
cubap Apr 28, 2025
39eb96b
Merge branch 'development' of https://github.com/CenterForDigitalHuma…
cubap Apr 28, 2025
e7704b4
un-mjs
cubap Apr 28, 2025
20ce23c
Refactor all .mjs files to .js and update imports. Closes #194 (#228)
cubap Apr 29, 2025
d1f5eaa
Merge branch 'main' into development
cubap Apr 29, 2025
b5f46f8
Update package-lock.json
cubap Apr 29, 2025
673a5c5
Using UID to get User Projects
mepripri Apr 29, 2025
ac0182f
Update index.mjs
mepripri Apr 30, 2025
9f102fb
Merge branch 'development' of https://github.com/CenterForDigitalHuma…
cubap Apr 30, 2025
6e79a8d
Merge branch 'development' into import-tpen28
mepripri Apr 30, 2025
443d0a2
no label is fine for Pages
cubap Apr 30, 2025
2e5bbbd
Merge branch 'development' of https://github.com/CenterForDigitalHuma…
cubap May 1, 2025
83fac3a
Merge branch 'development' into import-tpen28
mepripri May 1, 2025
d2ec198
Origin Fetch
mepripri May 1, 2025
dde7c30
SetHeader Origin
mepripri May 1, 2025
f977234
Update index.js
mepripri May 1, 2025
280dd45
Update index.js
mepripri May 1, 2025
4ad48ec
Update index.js
mepripri May 1, 2025
52edaab
Getting User Projects (#237)
mepripri May 2, 2025
032ef45
Merge branch 'development' into import-tpen28
cubap May 5, 2025
447490b
Update validateURL.js
mepripri May 6, 2025
de392a1
Merge branch 'development' into import-tpen28
cubap May 7, 2025
44b75cf
Localhost URLS Validating (#242)
mepripri May 7, 2025
4ee227a
231 create overwrite layer (#239)
cubap May 7, 2025
20305c0
remove unused file
thehabes May 12, 2025
66b3b5c
235 save annotations (#240)
cubap May 14, 2025
1f4c5d2
230 clean up project routers (#245)
cubap May 16, 2025
13830ee
Adding Tools to Project (#244)
mepripri May 19, 2025
da4986d
Merge branch 'development' into import-tpen28
mepripri May 19, 2025
0537b1f
Merge branch 'development' into import-tpen28
mepripri May 19, 2025
3c59aea
Merge branch 'import-tpen28' of https://github.com/CenterForDigitalHu…
mepripri May 20, 2025
adf2e4f
Adding endpoint to add multiple lines to a page
mepripri May 20, 2025
8b1aad5
Update index.js
mepripri May 20, 2025
1957b73
Add project metrics to /my/projects (#227)
git-voo May 21, 2025
43a322e
Merge branch 'development' into import-tpen28
mepripri May 21, 2025
5b220f3
Update index.js
mepripri May 21, 2025
93cf7a4
Merge branch 'import-tpen28' of https://github.com/CenterForDigitalHu…
mepripri May 21, 2025
1e6df19
co-op
thehabes May 21, 2025
c6b69d6
co-op
thehabes May 21, 2025
2eba4aa
co-op
thehabes May 21, 2025
b8f1e24
OK log time
thehabes May 21, 2025
ccd2ad8
do 401 from TPEN2 the right way
thehabes May 21, 2025
1e103b6
do 401 from TPEN2 the right way
thehabes May 21, 2025
b8fa84c
do 401 from TPEN2 the right way
thehabes May 21, 2025
7b735f5
do 401 from TPEN2 the right way
thehabes May 21, 2025
ebdcd13
gotta import the function
thehabes May 21, 2025
272ca58
Update index.js
mepripri May 21, 2025
3a2769f
Merge branch 'import-tpen28' of https://github.com/CenterForDigitalHu…
mepripri May 21, 2025
4e9bcaf
Need to import Project
thehabes May 21, 2025
7e57428
Merge branch 'import-tpen28' of https://github.com/CenterForDigitalHu…
thehabes May 21, 2025
39c110f
Need to import Project
thehabes May 21, 2025
68da79d
Good to go
thehabes May 21, 2025
07db204
Separating files
mepripri May 21, 2025
a5ce55d
Merge pull request #251 from CenterForDigitalHumanities/import-tpen28
mepripri May 21, 2025
629447e
add metarecords to new Projects (#254)
cubap May 28, 2025
9ed3175
256 import creates bad ids (#257)
cubap May 28, 2025
d9a6d76
always trim lastModified
cubap May 29, 2025
0fd815b
hotifx invite code
thehabes May 29, 2025
c4c2512
Email invite, upgrade temp user (#259)
thehabes Jun 11, 2025
0c21de8
hotfix links in E-mail
thehabes Jun 11, 2025
f0d7bc2
hotfix links in E-mail
thehabes Jun 11, 2025
36ed128
Align User With Project After Invite (#263)
thehabes Jun 12, 2025
7d68ee8
Create New Project from One Image
mepripri Jun 16, 2025
0ad0888
Update ProjectFactory.js
mepripri Jun 16, 2025
e52c8cc
Removing services
mepripri Jun 17, 2025
7227a9e
Update ProjectFactory.js
mepripri Jun 18, 2025
b4f104d
Update ProjectFactory.js
mepripri Jun 18, 2025
6e4d54b
MimeTypes
mepripri Jun 18, 2025
b1dd2ba
cleanup
thehabes Jun 18, 2025
d6e4ac7
Merge pull request #265 from CenterForDigitalHumanities/create-new-pr…
mepripri Jun 18, 2025
33fde1e
Decline Project Invite - Service (#264)
thehabes Jun 20, 2025
1a8a684
support text/plain request bodies (#268)
thehabes Jun 23, 2025
b80228c
Implement optimistic locking for page and line updates
cubap Jun 24, 2025
48a60f5
IIIF Image Service (#266)
mepripri Jun 26, 2025
d147cea
270 multiple updates to a page in parallel discards data (#271)
cubap Jul 1, 2025
29d45c3
Copy Project API (#272)
mepripri Jul 9, 2025
ba418c0
Project label update API (#273)
mepripri Jul 9, 2025
3523fa7
Level 0 image fix for TPEN28 imported Projects (#274)
mepripri Jul 10, 2025
1b6f74a
Adding Creator (#275)
mepripri Jul 18, 2025
c98a41c
Layer and Page Management Endpoints (#278)
thehabes Jul 23, 2025
ab82078
Revert "Layer and Page Management Endpoints (#278)" (#283)
thehabes Jul 23, 2025
241b4af
Project Export Message (#277)
mepripri Jul 25, 2025
9445392
Layer and Page Management Endpoints (#284)
thehabes Jul 29, 2025
b3376d1
Update Copy Project Layer Fix (#285)
mepripri Jul 29, 2025
57d6365
Project export message (#286)
mepripri Jul 29, 2025
2d0b203
Page and Layer Label Hotfix (#287)
mepripri Jul 30, 2025
e145229
Pair Coding Hotfixes (#288)
thehabes Jul 30, 2025
6e25780
ugh
thehabes Jul 30, 2025
1bccbcd
ugh
thehabes Jul 30, 2025
546f1c4
ugh
thehabes Jul 30, 2025
4e9617e
ugh
thehabes Jul 30, 2025
9540159
ugh
thehabes Jul 30, 2025
6577fb6
ugh
thehabes Jul 30, 2025
470bf0b
ugh
thehabes Jul 30, 2025
7bde502
ugh
thehabes Jul 30, 2025
0e0edd1
remove logs from testing ugh
thehabes Jul 30, 2025
5d0c879
Project Tools Fix (#290)
mepripri Aug 1, 2025
b945e88
ah forgot to commit touchups
thehabes Aug 1, 2025
fedf0e2
Leave Project Endpoint (#289)
thehabes Aug 5, 2025
4e72e12
Creator on text and bounds (#294)
cubap Aug 7, 2025
a6c28ca
276 upgrade temp ids referenced in rerum data (#296)
cubap Aug 11, 2025
85889cf
Set line creator if not already defined (#305)
cubap Aug 19, 2025
875b98d
Project Update Roles (#291)
mepripri Aug 20, 2025
70b2207
Project roles fix (#306)
mepripri Aug 20, 2025
d4aec32
TPEN28 Fix (#300)
mepripri Aug 20, 2025
73988d2
295 contentchanged for layers and pages (#298)
cubap Aug 21, 2025
55f7cab
TPEN28 Multiple Users Fix (#307)
mepripri Sep 2, 2025
58bff9a
public-profile (#299)
mepripri Sep 2, 2025
e8ed4a8
Fix up error responses, and expectations for those responses in the t…
thehabes Sep 2, 2025
ea31512
/:lineid/text hotfix (#310)
thehabes Sep 4, 2025
836e9df
Tpen28 Cookies Change (#311)
mepripri Sep 9, 2025
e3ffcdd
Protect PATCH /:projectId/label Endpoint (#308)
thehabes Sep 11, 2025
4737e22
Merge branch 'development' of https://github.com/CenterForDigitalHuma…
cubap Sep 12, 2025
bdd8420
Add protection to /project/metadata route (#316)
thehabes Sep 12, 2025
6785e41
Protect POST /project/create with screenContentMiddleware to block su…
thehabes Sep 15, 2025
5f7fcdd
Merge branch 'main' into development
cubap Sep 15, 2025
3bc5bd0
Merge branch 'development' of https://github.com/CenterForDigitalHuma…
cubap Sep 15, 2025
b9ac9bf
Protect /project/addRoles and /project/setRoles routes (#322)
thehabes Sep 16, 2025
9f8d1f0
Add comprehensive CONTRIBUTING.md guide for Node.js, Git, and local d…
Copilot Sep 17, 2025
f451eb7
Revise CONTRIBUTING.md for clarity and updates
cubap Sep 17, 2025
2759f58
Protect /project/create Route (#320)
thehabes Sep 17, 2025
c50d357
Merge branch 'development' of https://github.com/CenterForDigitalHuma…
cubap Sep 19, 2025
8858fdf
Merge branch 'main' into development
cubap Sep 19, 2025
406b034
Remove unused optimistic locking utilities
cubap Sep 19, 2025
759867f
Update utilities/shared.js
cubap Sep 19, 2025
8d8ed01
Update utilities/checkIfSuspicious.js
cubap Sep 19, 2025
7e73531
Protect PUT /profile route (#331)
thehabes Sep 19, 2025
f48a8a1
Default Tools and New Project with custom Tools (#328)
mepripri Sep 19, 2025
f1ba631
Changes to Tools endpoint (#346)
mepripri Sep 23, 2025
15384c2
Protect /project/import and /project/import-image routes (#326)
thehabes Sep 23, 2025
5f0bdb4
suspicious test fix
thehabes Sep 23, 2025
163aace
Enhance /project/create request body validation to prevent malformed …
Copilot Sep 23, 2025
5594bb3
newLineIndex === -1 logic
thehabes Sep 23, 2025
9461e84
logical errors
thehabes Sep 23, 2025
b1daad0
Add suspicious content protection to POST /layer route (#350)
Copilot Sep 29, 2025
0b4b18b
Add suspicious content protection to PUT /layer/:layerId route (#351)
Copilot Sep 29, 2025
dc44bf4
tagName fix for Tools (#349)
mepripri Sep 30, 2025
2a7d1a0
Protect PUT /page/:pageid Route (#352)
thehabes Oct 1, 2025
3461008
Add suspicious content protection to POST /line/ route (#353)
Copilot Oct 1, 2025
423769b
Protect PUT /line/:lineid Route (#354)
thehabes Oct 1, 2025
c3c6c11
This one is too easy to let AI do (#356)
thehabes Oct 1, 2025
35dcea1
Add suspicious input validation to feedback and bug report routes (#358)
Copilot Oct 1, 2025
38ad147
Node 22.20.0 now
thehabes Oct 1, 2025
d89112b
Page Viewer URL Change (#357)
mepripri Oct 2, 2025
8acffa9
Metadata Fix (#360)
mepripri Oct 2, 2025
91cfbfb
hotfix test
thehabes Oct 2, 2025
70514cb
metadata hotfix (#361)
mepripri Oct 2, 2025
873bf48
Remove /manifest directory and unregister manifest routes (#363)
thehabes Oct 2, 2025
24aec94
Add web-friendly API documentation for TPEN services (#301)
Copilot Oct 3, 2025
c333b5f
NPM Package Updates for package.json (#359)
thehabes Oct 3, 2025
b1ba2a9
Update API.html styles for improved readability
cubap Oct 3, 2025
f2b52a4
fix line getter
thehabes Oct 3, 2025
84783f1
fix line getter
thehabes Oct 3, 2025
f9344d1
fix line getter
thehabes Oct 3, 2025
b6f4173
Update project/projectToolsRouter.js
thehabes Oct 3, 2025
d7ed12b
TPEN28 Tools Fix (#365)
mepripri Oct 6, 2025
1388354
Preview Transcription Default Tool (#368)
mepripri Oct 8, 2025
81c3484
Add Tests to Check If Routes Exist (#367)
thehabes Oct 8, 2025
43db3a3
Line Break URL (#371)
mepripri Oct 10, 2025
a0ea62e
369 support namespaced project metadata (#370)
cubap Oct 15, 2025
4e0b682
Location Fix (#372)
mepripri Oct 20, 2025
8f64829
Create Project with Multiple Images (#373)
mepripri Nov 3, 2025
38df33b
claude on development
thehabes Nov 10, 2025
36be993
Add Claude Code GitHub Actions workflow
thehabes Nov 10, 2025
8b7e5ba
Go prd (#374)
cubap Nov 10, 2025
e60d2dc
Merge branch 'main' into development
cubap Nov 10, 2025
3071a96
deduped
cubap Nov 10, 2025
e4e480b
how we feeling?
cubap Nov 10, 2025
5e88be0
Links into RERUM APIs and code and the TPEN3 home page.
thehabes Nov 10, 2025
4fc3339
Fix PM2 cluster mode environment variable loading (#379)
thehabes Nov 11, 2025
6ca1faa
ftw
thehabes Nov 11, 2025
a2d2940
The file
thehabes Nov 11, 2025
6ad60f1
cmon
thehabes Nov 11, 2025
2bd6757
redo with human
thehabes Nov 11, 2025
ca5f25c
cleanup
thehabes Nov 11, 2025
0370469
cleanup
thehabes Nov 11, 2025
5662474
Let's see how RHEL feels about this (#380)
thehabes Nov 11, 2025
6f86b7f
ah I see probably still need dotenv here in the app.js
thehabes Nov 11, 2025
f50439b
get them .env vars back cmon
thehabes Nov 11, 2025
fc37141
trying
thehabes Nov 11, 2025
37c8654
Ok then let's have you do it like before
thehabes Nov 11, 2025
c6324a0
Debug logs
thehabes Nov 11, 2025
e557882
Verified I can get it to work the old way, so take steps towards the …
thehabes Nov 11, 2025
b7b3b2d
closer, logs are being weird though.
thehabes Nov 11, 2025
9cd1bd1
paths maybe?
thehabes Nov 11, 2025
ae0e2da
stick a fork in it
thehabes Nov 11, 2025
c559c37
stick a fork in it
thehabes Nov 11, 2025
9767730
stick a fork in it
thehabes Nov 11, 2025
59e62a0
I think it works!
thehabes Nov 11, 2025
b160c8d
Closer
thehabes Nov 11, 2025
cdfdc18
stop smoking
thehabes Nov 11, 2025
8563249
yaml supports if tpen3_services isn't already registered in pm2
thehabes Nov 11, 2025
da30f02
Update env-loader.js
thehabes Nov 11, 2025
c9d2e1a
Update __tests__/mount.test.js
thehabes Nov 11, 2025
a559eb7
Update Group.js
cubap Nov 12, 2025
d0f1d02
Merge branch 'development' of https://github.com/CenterForDigitalHuma…
cubap Nov 12, 2025
2bd64a0
Cleanup (#381)
thehabes Nov 12, 2025
829c439
Merge branch 'main' into development
thehabes Nov 12, 2025
81c5ee9
Merge branch 'main' into development
thehabes Nov 12, 2025
699881c
Signup - Login - Logout - Invite - Reject (#412)
thehabes Nov 25, 2025
57f3194
/page/:pageid/resolved Endpoint (#397)
thehabes Nov 25, 2025
42becae
Remove introduced this.update() calls in Group.js
thehabes Nov 25, 2025
3b0fc91
Invite and Reject Flows (#417)
thehabes Nov 26, 2025
ea44f0a
Only Update Lines (Annotations) That Have Changed (#419)
thehabes Nov 26, 2025
10a1970
dang this needs to go to development as a hotfix (#420)
thehabes Nov 26, 2025
81fb9b5
Let Members Leave Projects (#421)
thehabes Dec 1, 2025
f96b930
Create a New Column (#396)
mepripri Dec 2, 2025
e955f60
hotfix test
thehabes Dec 2, 2025
9f5c4f3
Page update for columns (#424)
mepripri Dec 10, 2025
62fd563
Return 200 with empty array for /my/projects when user has no project…
Copilot Dec 10, 2025
2dae7bf
PATCH /text Runtime Improvements (#429)
thehabes Dec 10, 2025
be2c765
Error Catching and Logging In Routes (#423)
thehabes Dec 10, 2025
a403889
hotifx merge stuff
thehabes Dec 10, 2025
4139492
hotfix for column passing
thehabes Dec 10, 2025
2778414
'pixel' in fragment selector hotfix (#433)
thehabes Dec 12, 2025
7445f91
TPEN Services npm Package Updates (#438)
thehabes Dec 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ Always reference these instructions first and fallback to search or bash command
- MariaDB: Configure MARIADB, MARIADBNAME, MARIADBUSER, MARIADBPASSWORD in `.env`
- TinyPEN API: Configure TINYPEN in `.env`
- Default configurations in `config.env` point to localhost development services
- MongoDB Collections: TPENPROJECTS, TPENGROUPS, TPENUSERS, TPENCOLUMNS (configured in `config.env`)

### Development Workflow
1. Always start with: `cp .env.development .env && npm install`
Expand Down Expand Up @@ -151,6 +152,12 @@ Required for database functionality:
- `MARIADB` (MariaDB host)
- `MARIADBNAME`, `MARIADBUSER`, `MARIADBPASSWORD` (MariaDB credentials)

MongoDB collection names (configured in `config.env`):
- `TPENPROJECTS` (default: projects) - Project documents collection
- `TPENGROUPS` (default: groups) - User groups collection
- `TPENUSERS` (default: users) - User profiles collection
- `TPENCOLUMNS` (default: columns) - Column annotations collection

Required for authentication:
- `AUDIENCE` (Auth0 audience)
- `DOMAIN` (Auth0 domain)
Expand Down
8 changes: 8 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ This allows developers to work immediately with sensible defaults while keeping
- MariaDB: Configure MARIADB, MARIADBNAME, MARIADBUSER, MARIADBPASSWORD in `.env`
- TinyPEN API: Configure TINYPEN in `.env`
- Default configurations in `config.env` point to localhost development services
- MongoDB Collections: TPENPROJECTS, TPENGROUPS, TPENUSERS, TPENCOLUMNS (configured in `config.env`)

### Development Workflow

Expand Down Expand Up @@ -181,6 +182,13 @@ Required for database functionality:
- `MARIADB` (MariaDB host)
- `MARIADBNAME`, `MARIADBUSER`, `MARIADBPASSWORD` (MariaDB credentials)

MongoDB collection names (configured in `config.env`):

- `TPENPROJECTS` (default: projects) - Project documents collection
- `TPENGROUPS` (default: groups) - User groups collection
- `TPENUSERS` (default: users) - User profiles collection
- `TPENCOLUMNS` (default: columns) - Column annotations collection

Required for authentication:

- `AUDIENCE` (Auth0 audience)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cd_dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@master
with:
node-version: "^22.20.0"
node-version: "24"
- name: Cache node modules
uses: actions/cache@master
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cd_prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@master
with:
node-version: "^22.20.0"
node-version: "24"
- name: Cache node modules
uses: actions/cache@master
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci_dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@master
with:
node-version: "^22.20.0"
node-version: "24"
- name: Cache node modules
uses: actions/cache@master
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci_prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@master
with:
node-version: "^22.20.0"
node-version: "24"
- name: Cache node modules
uses: actions/cache@master
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_pushes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@master
with:
node-version: "^22.20.0"
node-version: "24"
- name: Cache node modules
uses: actions/cache@master
env:
Expand Down
95 changes: 86 additions & 9 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,20 +248,35 @@ Users can always see and manipulate their own profile. The profile object is a p
- **Description**: Retrieve a list of projects the authenticated user is a member of.
- **Responses**:

- **200**: Projects found
- **200**: Projects found (or empty list if user has no projects)
```json
[
{
"_id": "hexstring",
"label": "string",
"roles": ["string"]
}, ...
]
{
"metrics": {
"newest": "project:hexstring/page:hexstring",
"lastModified": "project:hexstring/page:hexstring",
"myRecent": "hexstring"
},
"projects": [
{
"_id": "hexstring",
"label": "string",
"roles": ["string"]
}, ...
]
}
```

When the user has no projects, returns:
```json
{
"metrics": null,
"projects": []
}
```
- **401**: Unauthorized
- **500**: Server error

The response is a list of projects the user is a member of regardless of the permissions afforded to them in each project.
The response includes a list of projects the user is a member of regardless of the permissions afforded to them in each project, along with metrics about the newest and most recently modified projects.

#### `GET /user/:id`

Expand Down Expand Up @@ -406,3 +421,65 @@ Note that you may not empty the canvases of an existing layer. If the `canvases
}
```
- **500**: Server error

#### `GET /project/:projectId/page/:pageid/resolved`

- **Description**: Get a fully resolved page with complete annotation data from RERUM. This endpoint resolves all annotation references in the page's items array by fetching the full annotation objects from RERUM which will include the Annotation body.
- **Parameters**:
- `projectId`: ID of the project.
- `pageId`: The ID of the page.

- **Responses**:

- **200**: Page found with fully resolved annotations
```json
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "string",
"type": "AnnotationPage",
"label": {
"none":[
"TPEN3 Page"
]
},
"target": "string",
"items": [
{
"@context": "http://iiif.io/api/presentation/3/context.json",
"id": "string",
"type": "Annotation",
"motivation": "transcribing",
"target": {
"source": "string",
"type": "SpecificResource",
"selector": {
"type": "FragmentSelector",
"value": "string"
}
},
"creator": "string",
"body": {
"type": "TextualBody",
"value": "string",
"format": "text/plain"
},
"_createdAt": "timestamp",
"_modifiedAt": "timestamp",
"__rerum": {
"@context": "http://store.rerum.io/v1/context.json",
"createdAt": "timestamp",
"isOverwritten": "string"
}
}
],
"partOf": [{"type":"Collection"}],
"prev": "string",
"next": "string",
"_createdAt": "timestamp",
"_modifiedAt": "timestamp"
}
```
- **404**: Page not found
- **500**: Server error

**Note**: This endpoint is useful when you need complete annotation data in a single request instead of making multiple API calls to fetch individual annotations from RERUM. The annotations are resolved in parallel for better performance.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,3 @@ For production deployments:
4. Never commit production secrets to the repository

See [CONFIG.md](./CONFIG.md) for detailed deployment instructions.

4 changes: 4 additions & 0 deletions __tests__/mount.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ describe('Check to see that all expected route patterns exist. #exists_unit', ()
it('GET /project/:projectId/collaborator/:collaboratorId/decline -- decline project invitation', () => {
expect(routeExists('/:projectId/collaborator/:collaboratorId/decline', 'get')).toBe(true)
})

it('POST /project/:projectId/leave -- member leave project', () => {
expect(routeExists('/:id/leave', 'post')).toBe(true)
})
})

describe('Project custom roles routes', () => {
Expand Down
16 changes: 11 additions & 5 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import userProfileRouter from './userProfile/index.js'
import privateProfileRouter from './userProfile/privateProfile.js'
import proxyRouter from './utilities/proxy.js'
import feedbackRouter from './feedback/feedbackRoutes.js'
import routeErrorHandler from './utilities/routeErrorHandler.js'
import { respondWithError } from './utilities/shared.js'

let app = express()

Expand Down Expand Up @@ -65,10 +67,11 @@ app.use(express.static(path.join(__dirname, 'public')))
*/
app.all('*_', (req, res, next) => {
if (process.env.DOWN === 'true') {
return res.status(503).json({
message:
'TPEN3 services are down for updates or maintenance at this time. We apologize for the inconvenience. Try again later.'
})
return respondWithError(
res,
503,
'TPEN3 services are down for updates or maintenance at this time. We apologize for the inconvenience. Try again later.'
)
}
next()
})
Expand All @@ -82,9 +85,12 @@ app.use('/my', privateProfileRouter)
app.use('/proxy', proxyRouter)
app.use('/beta', feedbackRouter)

// Centralized error handling middleware
app.use(routeErrorHandler)

//catch 404 because of an invalid site path
app.use('*_', (req, res) => {
res.status(404).json({ message: res.statusMessage ?? 'This page does not exist' })
return respondWithError(res, 404, res.statusMessage ?? 'This page does not exist')
})

export { app as default }
63 changes: 52 additions & 11 deletions auth/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { auth } from "express-oauth2-jwt-bearer"
import { extractToken, extractUser, isTokenExpired } from "../utilities/token.js"
import User from "../classes/User/User.js"

/**
* This function verifies authorization tokens using Auth0 library. to protect a route using this function in a different component:
1. import the function in that component
Expand All @@ -17,7 +15,7 @@ function auth0Middleware() {
issuerBaseURL: `https://${process.env.DOMAIN}/`,
})

// Extract user from the token and set req.user. req.user can be set to specific info from the payload, like sib, roles, etc.
// Extract user from the token and set req.user. req.user can be set to specific info from the payload, like sub, roles, etc.
async function setUser(req, res, next) {
const { payload } = req.auth

Expand All @@ -32,24 +30,67 @@ function auth0Middleware() {
try {
const uid = agent.split("id/")[1]
const user = new User(uid)
user.getSelf().then(async (u) => {
if(!u || !u?.profile) {
const u = await user.getSelf()
if(!u || !u?.profile) {
const email = payload.name

// Check if a temporary user exists with this email
let existingUser = null
try {
existingUser = await user.getByEmail(email)
} catch (err) {
// No user found - that's fine, continue
}

if (existingUser && existingUser.inviteCode) {
// Found a temporary user - merge their memberships into this new user
user.data = {
_id: uid,
agent,
_sub: payload.sub,
email: payload.name,
email: email,
profile: { displayName: payload.nickname },
}
user.save()
await user.mergeFromTemporaryUser(existingUser)
await user.save()
req.user = user
next()
Comment on lines +54 to +57
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The authentication middleware now handles temporary user merging, which could be a slow operation involving multiple database queries and group updates. This blocking operation happens on every authenticated request for new users. Consider offloading this to a background job or showing a loading state to the user, as this could cause request timeouts for users with many project invitations.

Suggested change
await user.mergeFromTemporaryUser(existingUser)
await user.save()
req.user = user
next()
// Offload the merge and save to a background job to avoid blocking the request
user.data.mergePending = true;
req.user = user;
// Start the merge in the background
setImmediate(async () => {
try {
await user.mergeFromTemporaryUser(existingUser);
await user.save();
// Optionally, clear the mergePending flag here if you want to update the user record
} catch (err) {
console.error("Background mergeFromTemporaryUser failed:", err);
}
});
next();

Copilot uses AI. Check for mistakes.
return
} else if (existingUser) {
// Non-temporary user with same email - this is a conflict
const err = new Error(`User with email ${email} already exists. Please contact TPEN3 administrators for assistance.`)
err.status = 409
next(err)
return
} else {
// No existing user - create new
user.data = {
_id: uid,
agent,
_sub: payload.sub,
email: email,
profile: { displayName: payload.nickname },
}
await user.save()
req.user = user
next()
return
}
req.user = u
next()
return
})
}
// Ensure no inviteCode on authenticated user
delete u.inviteCode

// If user exists but has wrong _sub (e.g., from temp user), update it
if (u._sub !== payload.sub) {
u._sub = payload.sub
const userObj = new User(uid)
userObj.data = u
await userObj.update()
}
Comment on lines +84 to +89
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition on line 84 checks u._sub !== payload.sub but u could have _sub as undefined. This will always evaluate to true for users created before this field was tracked, causing unnecessary database updates on every request for legacy users. Consider checking if u._sub exists before comparing, or add a migration to set _sub for all existing users.

Copilot uses AI. Check for mistakes.

req.user = u
next()
return
} catch (error) {
next(error)
}
Expand Down
Loading
Loading