Skip to content

Commit 6e3e917

Browse files
cubapgit-voothehabesmepripri
authored
Development (#202)
* update metadata (#171) * update metadata * modify route name and db.update * update db.update dependent * cleanup --------- Co-authored-by: Bryan Haberberger <bryan.j.haberberger@slu.edu> * quickfix * cleanup * modify db.update to receive one param {data, collection} * nodiff * restore action(data, collection) structure * undiff * Changed Collections Parameter for Save() * Removing /:id put Call * Removing the Limit from express.json() * Removing the Limit from express.json() * getting started with Vault (#190) * getting started with Vault * newer Vault * tests * removing redundant code * proper tests passing * sample Vault * Bryan's refusal to .jsonld makes this not work as expected * loading resources This is incomplete by design. We need to ask Vault to add any resources we want resolved * expanding the Manifest a bit * touch up for merge * touch up for merge --------- Co-authored-by: Bryan Haberberger <bryan.j.haberberger@slu.edu> * Current Project IIIF manifest Creation (#187) * Current Project IIIF manifest Creation * Refactored the exportManifest() and endpoint name * Changed the exportManifest() function * TPEN ID error handled * endpoint to move the manifest.json to TPEN-Static-Dev * Changed @id to id * Getting all Ids * Console Clean up * Added env variables * Adding Imports * Adding Imports * Deleting Ids * Updating Logic Added * User not a member cannot change the manifest * Removing project2 * Adding comments to functions * add hotkeys service (#184) * add hotkeys service * hotkey endpoints * aggregate hotkeys during project retrieval * specify hotkey fields to include * cleanup * Update Hotkeys.js * Update ProjectFactory.mjs * Return hotkeys as an Array of Strings * aligning with Class changes * remove create, since .save is not acting correctly * cleanup and drop .post * tests restored no Jest here, just checking exists. * tests and sinon upgrade * no db tests directly * Update exists_unit.test.mjs * putting post back in... * adding create back with safety * adding upsert to accomodate bad errors * Update Hotkeys.js * uncatch to let errors through * expect the errors to come back * switch to jest tests --------- Co-authored-by: cubap <cubap@slu.edu> * hotifx * hotfix for symbols. * delete enabled * Create API.md * collaborators and users * add markdown reader * package for markdown * Update API.md * Update API.md * touch * ah codes * proxy for internal use (#201) * Endpoint to save changes for the new layer (#199) * Adding endpoint to save changes from the layer * Adding New Layer * No Empty Label and no Annotations * Updated new Layer * Adding Items to partOf * Changing id convention * Removing updating layer * Annotation Change * Adding Delete Endpoint * not sure... This type of thing? * Label Change * Added Layer Class * Adding rerum ids to delete and add * Changing tests * Update exists.test.mjs * Changing LayerLabel * Changes AnnotationCollection Structure * Update Pages API * Updating partOf Ids in case of any change * Adding Layer Metadata Label Change * example results as a base for comments, delete these files before merge. * Adding AddLayer Commenting Rest of the APIs * Added DeleteLayer Back * Deleting json files * Updates to the comments * Making Project to Layer Changes * Renaming layerAnnotationCollection * Removing UpdateOne() changes * Removing UpdateOne() changes * Removing UpdateOne() changes * Error Handled for no ProjectID or LayerID * Clear Code * send() instead of json() --------- Co-authored-by: cubap <cubap@slu.edu> Co-authored-by: Bryan Haberberger <bryan.j.haberberger@slu.edu> --------- Co-authored-by: Onoja Victor <111019083+git-voo@users.noreply.github.com> Co-authored-by: Bryan Haberberger <bryan.j.haberberger@slu.edu> Co-authored-by: Onoja <onoja.jsdev@gmail.com> Co-authored-by: mepripri <mepripri0712@gmail.com> Co-authored-by: Priyal Patel <52342511+mepripri@users.noreply.github.com>
1 parent 9314bd0 commit 6e3e917

23 files changed

Lines changed: 2222 additions & 235 deletions

File tree

API.md

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
# TPEN Services API Documentation
2+
3+
This document provides an overview of the available routes in the TPEN Services API. These routes allow interaction with the application for various functionalities.
4+
5+
## Base URL
6+
7+
- **Production**: [https://api.t-pen.org](https://api.t-pen.org)
8+
- **Development**: [https://dev.api.t-pen.org](https://dev.api.t-pen.org)
9+
10+
## Endpoints
11+
12+
### 1. **Authentication**
13+
14+
Endpoints marked with a 🔐 requiring authentication expect a valid JWT token in the `Authorization` header. Use the [public TPEN3 login](https://three.t-pen.org/login/) to get one of these JWT tokens.
15+
16+
---
17+
18+
### 2. **Project**
19+
20+
#### `POST /project/create` 🔐
21+
22+
- **Description**: Create a new project. This is a high-skill maneuver requiring a complete project object.
23+
- **Request Body**:
24+
25+
```json
26+
{
27+
"label": "string",
28+
"metadata": [ { Metadata } ],
29+
"layers": [ { Layer } ],
30+
"manifests": [ "URIs<Manifest>" ],
31+
"creator": "URI<Agent>",
32+
"group": "hexstring"
33+
}
34+
```
35+
36+
- **Responses**:
37+
38+
- **201**: Project created successfully
39+
- **400**: Project creation failed, validation errors
40+
- **401**: Unauthorized
41+
- **500**: Server error
42+
43+
The Location header of a successful response is the Project id.
44+
45+
#### `POST /import?createFrom="URL"` 🔐
46+
47+
- **Description**: Create a new project by importing a web resource.
48+
- **Request Body**:
49+
50+
```json
51+
{
52+
"url": "URL<IIIF:Manifest>"
53+
}
54+
```
55+
56+
- **Responses**:
57+
58+
- **201**: Project created successfully
59+
- **400**: Project creation failed, validation errors
60+
- **401**: Unauthorized
61+
- **500**: Server error
62+
63+
The Location header of a successful response is the Project id. The project will be created with the label and metadata of the imported resource. A complete project object will be created with the imported resource as the first manifest and returned.
64+
65+
#### `GET /project/:id` 🔐
66+
67+
- **Description**: Retrieve a project by ID.
68+
- **Parameters**:
69+
- `id`: ID of the project.
70+
- **Responses**:
71+
72+
- **200**: Project found
73+
```json
74+
{
75+
"id": "string",
76+
"label": "string",
77+
"metadata": [ { Metadata } ],
78+
"creator": "URI<Agent>",
79+
"layers": [ { Layer } ],
80+
"manifests": [ "URIs<Manifest>" ],
81+
"group": "hexstring",
82+
"tools": [ "string" ],
83+
"options": { OptionsMap }
84+
}
85+
```
86+
- **404**: Project not found
87+
- **401**: Unauthorized
88+
- **403**: Forbidden
89+
- **500**: Server error
90+
91+
The response is not a complete Project data object, but a projection designed for use in the client interface.
92+
93+
---
94+
95+
### 3. **Collaborators**
96+
97+
Manage the users and roles in a Project.
98+
99+
#### `POST /project/:projectId/invite-member` 🔐
100+
101+
- **Description**: Invite a user to a project. If the user does not have a TPEN account, they will be sent an email invitation.
102+
- **Parameters**:
103+
- `projectId`: ID of the project as a hexstring or the Project slug.
104+
- **Request Body**:
105+
106+
```json
107+
{
108+
"email": "string",
109+
"roles": ["string"] | "string"
110+
}
111+
```
112+
113+
- `email`: The email address of the user to invite.
114+
- `roles`: The roles of the user in the project as an array or space-delimited string.
115+
- **Responses**:
116+
117+
- **200**: User invited successfully
118+
- **400**: User invitation failed, validation errors
119+
- **401**: Unauthorized
120+
- **403**: Forbidden
121+
- **500**: Server error
122+
123+
This API is not able to track the status of the invitation. Email addresses that fail to be delivered or are rejected by the recipient will not be reported.
124+
125+
#### `POST /project/:projectId/remove-member` 🔐
126+
127+
- **Description**: Remove a user from a project group.
128+
- **Parameters**:
129+
- `projectId`: ID of the project.
130+
- **Request Body**:
131+
132+
```json
133+
{
134+
"userID": "string"
135+
}
136+
```
137+
- **Responses**:
138+
139+
- **204**: User removed successfully
140+
- **401**: Unauthorized
141+
- **403**: Forbidden
142+
- **500**: Server error
143+
144+
This removes a user and their roles from the project. The user will no longer have access to the project, but their annotations will remain with full attribution.
145+
146+
#### `PUT /project/:projectId/collaborator/:collaboratorId/setRoles` 🔐
147+
148+
- **Description**: Set the roles of a User in a project, replacing all currently defined roles.
149+
- **Parameters**:
150+
- `projectId`: ID of the project.
151+
- `collaboratorId`: ID of the collaborator.
152+
- **Request Body**:
153+
154+
```json
155+
{
156+
"roles": ["string"] | "string"
157+
}
158+
```
159+
- **Responses**:
160+
161+
- **200**: Roles set successfully
162+
- **400**: Roles setting failed, validation errors
163+
- **401**: Unauthorized
164+
- **403**: Forbidden
165+
- **500**: Server error
166+
167+
The User requesting this action must have permissions to set roles for the collaborator. The <kbd>OWNER</kbd> role cannot be set using this endpoint.
168+
169+
#### `POST /project/:projectId/switch/owner` 🔐
170+
171+
- **Description**: Transfer ownership of a project to another user.
172+
- **Parameters**:
173+
- `projectId`: ID of the project.
174+
- **Request Body**:
175+
176+
```json
177+
{
178+
"newOwnerId": "hexstring"
179+
}
180+
```
181+
- **Responses**:
182+
183+
- **200**: Ownership transferred successfully
184+
- **400**: Ownership transfer failed, validation errors
185+
- **401**: Unauthorized
186+
- **403**: Forbidden
187+
- **500**: Server error
188+
189+
The User requesting this action must be the current owner of the project. The <kbd>OWNER</kbd> role will be removed from the current owner and assigned to the new owner. The new owner must be a member of the project. If the current owner has no other roles, the <kbd>CONTRIBUTOR</kbd> role will be assigned to them.
190+
191+
#### `POST /project/:projectId/setCustomRoles` 🔐
192+
193+
- **Description**: Set custom roles for a Project group. Custom roles must be provided as a JSON object with keys as roles and values as arrays of permissions or space-delimited strings.
194+
- **Parameters**:
195+
- `projectId`: ID of the project.
196+
- **Request Body**:
197+
198+
```json
199+
{
200+
"roles": {
201+
"roleName": ["permission1", "permission2"] | "space-delimited permissions"
202+
}
203+
}
204+
```
205+
206+
- **Responses**:
207+
208+
- **200**: Custom roles set successfully
209+
- **400**: Invalid request, validation errors
210+
- **401**: Unauthenticated request
211+
- **403**: Permission denied
212+
- **500**: Server error
213+
214+
The User requesting this action must have permissions to update roles. Default roles cannot be modified using this endpoint. Custom roles can be complicated and there is more detailed description of their use in the [Cookbook](#).
215+
216+
---
217+
218+
### 4. **Users**
219+
220+
Private account modification, personal details, and public profile retrieval.
221+
222+
#### `GET /my/profile` 🔐
223+
224+
- **Description**: Retrieve the profile of the authenticated user.
225+
- **Responses**:
226+
227+
- **200**: Profile found
228+
```json
229+
{
230+
"_id": "hexstring",
231+
"_sub": "string",
232+
"agent": "URI<Agent>",
233+
"email": "string",
234+
"profile": {
235+
"displayName": "string",
236+
"custom": Any
237+
}
238+
"name": "string"
239+
}
240+
```
241+
- **401**: Unauthorized
242+
- **500**: Server error
243+
244+
Users can always see and manipulate their own profile. The profile object is a projection of the full user object.
245+
246+
#### `GET /my/projects` 🔐
247+
248+
- **Description**: Retrieve a list of projects the authenticated user is a member of.
249+
- **Responses**:
250+
251+
- **200**: Projects found
252+
```json
253+
[
254+
{
255+
"_id": "hexstring",
256+
"label": "string",
257+
"roles": ["string"]
258+
}, ...
259+
]
260+
```
261+
- **401**: Unauthorized
262+
- **500**: Server error
263+
264+
The response is a list of projects the user is a member of regardless of the permissions afforded to them in each project.
265+
266+
#### `GET /user/:id`
267+
268+
- **Description**: Retrieve the public profile of a user.
269+
- **Parameters**:
270+
- `id`: ID of the user.
271+
- **Responses**:
272+
273+
- **200**: Profile found
274+
```json
275+
{
276+
"_id": "hexstring",
277+
"displayName": "string",
278+
"custom": Any
279+
}
280+
```
281+
- **404**: Profile not found
282+
- **500**: Server error
283+
284+
The response is a projection of the full user object. The public profile is available to all users and serialized into this response with whatever the user has chosen to share. The `custom` field is not an actual property - it is a placeholder for any additional fields the user has added to their profile. The `displayName` and `_id` fields are always present.

app.mjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ import manifestRouter from './manifest/index.mjs'
2424
import projectRouter from './project/index.mjs'
2525
import pageRouter from './page/index.mjs'
2626
import lineRouter from './line/index.mjs'
27-
import userProfileRouter from './userProfile/index.mjs'
27+
import userProfileRouter from './userProfile/index.mjs'
2828
import privateProfileRouter from './userProfile/privateProfile.mjs'
29+
import proxyRouter from './utilities/proxy.js'
2930

3031
let app = express()
3132

@@ -62,6 +63,7 @@ app.use('/line', lineRouter)
6263
app.use('/page', pageRouter)
6364
app.use('/user', userProfileRouter)
6465
app.use('/my', privateProfileRouter)
66+
app.use('/proxy', proxyRouter)
6567

6668
//catch 404 because of an invalid site path
6769
app.use('*', function(req, res, next) {

classes/Group/Group.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default class Group {
99
}
1010

1111
async #loadFromDB() {
12-
this.data = await database.getById(this._id, "groups")
12+
this.data = await database.getById(this._id, process.env.TPENGROUPS)
1313
return this
1414
}
1515

@@ -228,13 +228,13 @@ export default class Group {
228228
}
229229

230230
async save() {
231-
this.validateGroup()
231+
await this.validateGroup()
232232
return database.save(this.data, process.env.TPENGROUPS)
233233
}
234234

235235
async update() {
236236
await this.validateGroup()
237-
return database.update({ ...this.data, type: "Group" },)
237+
return database.update(this.data, process.env.TPENGROUPS)
238238
}
239239

240240
async validateGroup() {

0 commit comments

Comments
 (0)