mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
Merge pull request #23605 from opf/feat/flat-meeting-objects
Flat meeting API objects
This commit is contained in:
@@ -272,20 +272,32 @@ paths:
|
||||
"/api/v3/meetings/{id}":
|
||||
"$ref": "./paths/meeting.yml"
|
||||
"/api/v3/meetings/{id}/agenda_items":
|
||||
"$ref": "./paths/meeting_agenda_items.yml"
|
||||
"$ref": "./paths/meeting_agenda_items_by_meeting.yml"
|
||||
"/api/v3/meetings/{meeting_id}/agenda_items/{id}":
|
||||
"$ref": "./paths/meeting_agenda_item_by_meeting.yml"
|
||||
"/api/v3/meeting_agenda_items":
|
||||
"$ref": "./paths/meeting_agenda_items.yml"
|
||||
"/api/v3/meeting_agenda_items/{id}":
|
||||
"$ref": "./paths/meeting_agenda_item.yml"
|
||||
"/api/v3/meetings/{meeting_id}/agenda_items/{agenda_item_id}/outcomes":
|
||||
"$ref": "./paths/meeting_agenda_item_outcomes.yml"
|
||||
"/api/v3/meetings/{meeting_id}/agenda_items/{agenda_item_id}/outcomes/{id}":
|
||||
"$ref": "./paths/meeting_agenda_item_outcome.yml"
|
||||
"/api/v3/meeting_outcomes":
|
||||
"$ref": "./paths/meeting_outcomes.yml"
|
||||
"/api/v3/meeting_outcomes/{id}":
|
||||
"$ref": "./paths/meeting_outcome.yml"
|
||||
"/api/v3/meetings/{id}/attachments":
|
||||
"$ref": "./paths/meeting_attachments.yml"
|
||||
"/api/v3/meetings/{id}/form":
|
||||
"$ref": "./paths/meeting_form.yml"
|
||||
"/api/v3/meetings/{id}/sections":
|
||||
"$ref": "./paths/meeting_sections.yml"
|
||||
"$ref": "./paths/meeting_sections_by_meeting.yml"
|
||||
"/api/v3/meetings/{meeting_id}/sections/{id}":
|
||||
"$ref": "./paths/meeting_section_by_meeting.yml"
|
||||
"/api/v3/meeting_sections":
|
||||
"$ref": "./paths/meeting_sections.yml"
|
||||
"/api/v3/meeting_sections/{id}":
|
||||
"$ref": "./paths/meeting_section.yml"
|
||||
"/api/v3/meetings/form":
|
||||
"$ref": "./paths/meetings_form.yml"
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
# /api/v3/meetings/{meeting_id}/agenda_items/{id}
|
||||
# /api/v3/meeting_agenda_items/{id}
|
||||
---
|
||||
get:
|
||||
summary: Get a meeting agenda item
|
||||
operationId: get_meeting_agenda_item
|
||||
tags:
|
||||
- Meetings
|
||||
description: Retrieve an individual agenda item of a meeting.
|
||||
description: Retrieve an individual agenda item.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Agenda item identifier
|
||||
example: 1
|
||||
in: path
|
||||
@@ -40,7 +33,7 @@ get:
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the agenda item or meeting does not exist or the client does not have sufficient permissions.
|
||||
Returned if the agenda item does not exist or the client does not have sufficient permissions.
|
||||
|
||||
patch:
|
||||
summary: Update a meeting agenda item
|
||||
@@ -49,13 +42,6 @@ patch:
|
||||
- Meetings
|
||||
description: Updates the given agenda item.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Agenda item identifier
|
||||
example: 1
|
||||
in: path
|
||||
@@ -82,12 +68,6 @@ patch:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
|
||||
message: You are not authorized to access this resource.
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
@@ -97,14 +77,8 @@ patch:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the agenda item or meeting does not exist.
|
||||
Returned if the agenda item does not exist or the client does not have sufficient permissions.
|
||||
'406':
|
||||
$ref: "../components/responses/missing_content_type.yml"
|
||||
'415':
|
||||
@@ -122,13 +96,6 @@ delete:
|
||||
- Meetings
|
||||
description: Deletes the agenda item.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Agenda item identifier
|
||||
example: 1
|
||||
in: path
|
||||
@@ -144,12 +111,6 @@ delete:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
|
||||
message: You are not authorized to access this resource.
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
@@ -159,11 +120,5 @@ delete:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the agenda item or meeting does not exist.
|
||||
Returned if the agenda item does not exist or the client does not have sufficient permissions.
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# /api/v3/meetings/{meeting_id}/agenda_items/{id}
|
||||
---
|
||||
get:
|
||||
summary: Get a meeting agenda item
|
||||
operationId: get_meeting_agenda_item_by_meeting
|
||||
tags:
|
||||
- Meetings
|
||||
description: Retrieve an individual agenda item of a meeting.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Agenda item identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_agenda_item_model.yml"
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the agenda item or meeting does not exist or the client does not have sufficient permissions.
|
||||
@@ -2,7 +2,7 @@
|
||||
---
|
||||
get:
|
||||
summary: Get a meeting outcome
|
||||
operationId: get_meeting_outcome
|
||||
operationId: get_meeting_outcome_by_agenda_item
|
||||
tags:
|
||||
- Meetings
|
||||
description: Retrieve an individual outcome of a meeting agenda item.
|
||||
@@ -48,143 +48,3 @@ get:
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the outcome, agenda item, or meeting does not exist or the client does not have sufficient permissions.
|
||||
|
||||
patch:
|
||||
summary: Update a meeting outcome
|
||||
operationId: update_meeting_outcome
|
||||
tags:
|
||||
- Meetings
|
||||
description: Updates the given meeting outcome.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Agenda item identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: agenda_item_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Outcome identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_outcome_write_model.yml"
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_outcome_model.yml"
|
||||
'400':
|
||||
$ref: "../components/responses/invalid_request_body.yml"
|
||||
'403':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
|
||||
message: You are not authorized to access this resource.
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
**Required permission:** manage outcomes
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the outcome, agenda item, or meeting does not exist.
|
||||
'406':
|
||||
$ref: "../components/responses/missing_content_type.yml"
|
||||
'415':
|
||||
$ref: "../components/responses/unsupported_media_type.yml"
|
||||
'422':
|
||||
description: |-
|
||||
Returned if:
|
||||
|
||||
* a constraint for a property was violated (`PropertyConstraintViolation`)
|
||||
|
||||
delete:
|
||||
summary: Delete a meeting outcome
|
||||
operationId: delete_meeting_outcome
|
||||
tags:
|
||||
- Meetings
|
||||
description: Deletes the outcome.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Agenda item identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: agenda_item_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Outcome identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'204':
|
||||
description: Returned if the outcome was successfully deleted
|
||||
'403':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
|
||||
message: You are not authorized to access this resource.
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
**Required permission:** manage outcomes
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the outcome, agenda item, or meeting does not exist.
|
||||
|
||||
@@ -43,76 +43,3 @@ get:
|
||||
Returned if the agenda item or meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
|
||||
**Required permission:** view meetings
|
||||
|
||||
post:
|
||||
summary: Create meeting outcome
|
||||
operationId: create_meeting_outcome
|
||||
tags:
|
||||
- Meetings
|
||||
description: Creates a new outcome for the given meeting agenda item.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Agenda item identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: agenda_item_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_outcome_write_model.yml"
|
||||
responses:
|
||||
'201':
|
||||
description: Created
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_outcome_model.yml"
|
||||
'400':
|
||||
$ref: "../components/responses/invalid_request_body.yml"
|
||||
'403':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
|
||||
message: You are not authorized to access this resource.
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
**Required permission:** manage outcomes
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the agenda item or meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
'406':
|
||||
$ref: "../components/responses/missing_content_type.yml"
|
||||
'415':
|
||||
$ref: "../components/responses/unsupported_media_type.yml"
|
||||
'422':
|
||||
description: |-
|
||||
Returned if:
|
||||
|
||||
* a constraint for a property was violated (`PropertyConstraintViolation`)
|
||||
|
||||
@@ -1,56 +1,11 @@
|
||||
# /api/v3/meetings/{id}/agenda_items
|
||||
# /api/v3/meeting_agenda_items
|
||||
---
|
||||
get:
|
||||
summary: List meeting agenda items
|
||||
operationId: list_meeting_agenda_items
|
||||
tags:
|
||||
- Meetings
|
||||
description: Lists all agenda items for the given meeting.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_agenda_item_collection_model.yml"
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
|
||||
**Required permission:** view meetings
|
||||
|
||||
post:
|
||||
summary: Create meeting agenda item
|
||||
operationId: create_meeting_agenda_item
|
||||
tags:
|
||||
- Meetings
|
||||
description: Creates a new agenda item for the given meeting.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: Creates a new agenda item. The request body must link the meeting.
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
@@ -92,7 +47,7 @@ post:
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
Returned if the linked meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
'406':
|
||||
$ref: "../components/responses/missing_content_type.yml"
|
||||
'415':
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# /api/v3/meetings/{id}/agenda_items
|
||||
---
|
||||
get:
|
||||
summary: List meeting agenda items
|
||||
operationId: list_meeting_agenda_items
|
||||
tags:
|
||||
- Meetings
|
||||
description: Lists all agenda items for the given meeting.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_agenda_item_collection_model.yml"
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
|
||||
**Required permission:** view meetings
|
||||
@@ -0,0 +1,124 @@
|
||||
# /api/v3/meeting_outcomes/{id}
|
||||
---
|
||||
get:
|
||||
summary: Get a meeting outcome
|
||||
operationId: get_meeting_outcome
|
||||
tags:
|
||||
- Meetings
|
||||
description: Retrieve an individual meeting outcome.
|
||||
parameters:
|
||||
- description: Outcome identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_outcome_model.yml"
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the outcome does not exist or the client does not have sufficient permissions.
|
||||
|
||||
patch:
|
||||
summary: Update a meeting outcome
|
||||
operationId: update_meeting_outcome
|
||||
tags:
|
||||
- Meetings
|
||||
description: Updates the given meeting outcome.
|
||||
parameters:
|
||||
- description: Outcome identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_outcome_write_model.yml"
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_outcome_model.yml"
|
||||
'400':
|
||||
$ref: "../components/responses/invalid_request_body.yml"
|
||||
'403':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
**Required permission:** manage outcomes
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
description: |-
|
||||
Returned if the outcome does not exist or the client does not have sufficient permissions.
|
||||
'406':
|
||||
$ref: "../components/responses/missing_content_type.yml"
|
||||
'415':
|
||||
$ref: "../components/responses/unsupported_media_type.yml"
|
||||
'422':
|
||||
description: |-
|
||||
Returned if:
|
||||
|
||||
* a constraint for a property was violated (`PropertyConstraintViolation`)
|
||||
|
||||
delete:
|
||||
summary: Delete a meeting outcome
|
||||
operationId: delete_meeting_outcome
|
||||
tags:
|
||||
- Meetings
|
||||
description: Deletes the outcome.
|
||||
parameters:
|
||||
- description: Outcome identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'204':
|
||||
description: Returned if the outcome was successfully deleted
|
||||
'403':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
**Required permission:** manage outcomes
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
description: |-
|
||||
Returned if the outcome does not exist or the client does not have sufficient permissions.
|
||||
@@ -0,0 +1,59 @@
|
||||
# /api/v3/meeting_outcomes
|
||||
---
|
||||
post:
|
||||
summary: Create meeting outcome
|
||||
operationId: create_meeting_outcome
|
||||
tags:
|
||||
- Meetings
|
||||
description: Creates a new meeting outcome. The request body must link the agenda item.
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_outcome_write_model.yml"
|
||||
responses:
|
||||
'201':
|
||||
description: Created
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_outcome_model.yml"
|
||||
'400':
|
||||
$ref: "../components/responses/invalid_request_body.yml"
|
||||
'403':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
|
||||
message: You are not authorized to access this resource.
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
**Required permission:** manage outcomes
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the linked agenda item does not exist or the client does not have sufficient permissions to see it.
|
||||
'406':
|
||||
$ref: "../components/responses/missing_content_type.yml"
|
||||
'415':
|
||||
$ref: "../components/responses/unsupported_media_type.yml"
|
||||
'422':
|
||||
description: |-
|
||||
Returned if:
|
||||
|
||||
* a constraint for a property was violated (`PropertyConstraintViolation`)
|
||||
@@ -1,19 +1,12 @@
|
||||
# /api/v3/meetings/{meeting_id}/sections/{id}
|
||||
# /api/v3/meeting_sections/{id}
|
||||
---
|
||||
get:
|
||||
summary: Get a meeting section
|
||||
operationId: get_meeting_section
|
||||
tags:
|
||||
- Meetings
|
||||
description: Retrieve an individual section of a meeting.
|
||||
description: Retrieve an individual meeting section.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Section identifier
|
||||
example: 1
|
||||
in: path
|
||||
@@ -33,29 +26,16 @@ get:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the section or meeting does not exist or the client does not have sufficient permissions.
|
||||
Returned if the section does not exist or the client does not have sufficient permissions.
|
||||
|
||||
patch:
|
||||
summary: Update a meeting section
|
||||
operationId: update_meeting_section
|
||||
tags:
|
||||
- Meetings
|
||||
description: Updates the given section.
|
||||
description: Updates the given meeting section.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Section identifier
|
||||
example: 1
|
||||
in: path
|
||||
@@ -82,12 +62,6 @@ patch:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
|
||||
message: You are not authorized to access this resource.
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
@@ -97,14 +71,8 @@ patch:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the section or meeting does not exist.
|
||||
Returned if the section does not exist or the client does not have sufficient permissions.
|
||||
'406':
|
||||
$ref: "../components/responses/missing_content_type.yml"
|
||||
'415':
|
||||
@@ -120,15 +88,8 @@ delete:
|
||||
operationId: delete_meeting_section
|
||||
tags:
|
||||
- Meetings
|
||||
description: Deletes the section and all its agenda items.
|
||||
description: Deletes the meeting section.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Section identifier
|
||||
example: 1
|
||||
in: path
|
||||
@@ -144,12 +105,6 @@ delete:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:MissingPermission
|
||||
message: You are not authorized to access this resource.
|
||||
description: |-
|
||||
Returned if the client does not have sufficient permissions.
|
||||
|
||||
@@ -159,11 +114,5 @@ delete:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the section or meeting does not exist.
|
||||
Returned if the section does not exist or the client does not have sufficient permissions.
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# /api/v3/meetings/{meeting_id}/sections/{id}
|
||||
---
|
||||
get:
|
||||
summary: Get a meeting section
|
||||
operationId: get_meeting_section_by_meeting
|
||||
tags:
|
||||
- Meetings
|
||||
description: Retrieve an individual section of a meeting.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: meeting_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- description: Section identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_section_model.yml"
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the section or meeting does not exist or the client does not have sufficient permissions.
|
||||
@@ -1,56 +1,11 @@
|
||||
# /api/v3/meetings/{id}/sections
|
||||
# /api/v3/meeting_sections
|
||||
---
|
||||
get:
|
||||
summary: List meeting sections
|
||||
operationId: list_meeting_sections
|
||||
tags:
|
||||
- Meetings
|
||||
description: Lists all sections for the given meeting.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_section_collection_model.yml"
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
|
||||
**Required permission:** view meetings
|
||||
|
||||
post:
|
||||
summary: Create meeting section
|
||||
operationId: create_meeting_section
|
||||
tags:
|
||||
- Meetings
|
||||
description: Creates a new section for the given meeting.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
description: Creates a new section. The request body must link the meeting.
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
@@ -92,7 +47,7 @@ post:
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
Returned if the linked meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
'406':
|
||||
$ref: "../components/responses/missing_content_type.yml"
|
||||
'415':
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# /api/v3/meetings/{id}/sections
|
||||
---
|
||||
get:
|
||||
summary: List meeting sections
|
||||
operationId: list_meeting_sections
|
||||
tags:
|
||||
- Meetings
|
||||
description: Lists all sections for the given meeting.
|
||||
parameters:
|
||||
- description: Meeting identifier
|
||||
example: 1
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/meeting_section_collection_model.yml"
|
||||
'404':
|
||||
content:
|
||||
application/hal+json:
|
||||
schema:
|
||||
$ref: "../components/schemas/error_response.yml"
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
_type: Error
|
||||
errorIdentifier: urn:openproject-org:api:v3:errors:NotFound
|
||||
message: The requested resource could not be found.
|
||||
description: |-
|
||||
Returned if the meeting does not exist or the client does not have sufficient permissions to see it.
|
||||
|
||||
**Required permission:** view meetings
|
||||
@@ -34,6 +34,18 @@ OPENPROJECT_SSRF_PROTECTION_IP_ALLOWLIST=2001:db8:100::/48
|
||||
|
||||
The list accepts one or multiple IP addresses or ranges (in CIDR notation) that shall be exempt from SSRF filtering.
|
||||
|
||||
### Meeting API structure changes
|
||||
|
||||
17.6. introduces new endpoints for meeting outcomes,
|
||||
and changes the self link for all meeting related resources to be flat:
|
||||
|
||||
That means, some of the responses have changed:
|
||||
|
||||
POST/PATCH/DELETE `/api/v3/meetings/:id/agenda_items)` is no longer available,
|
||||
they have been moved to the `/api/v3/meeting_agendas/` respectively. The same is true for outcomes and sections.
|
||||
|
||||
This follows the APIv3 standards, and also fixes a bug related to the self link.
|
||||
|
||||
<!-- BEGIN SECURITY FIXES AUTOMATED SECTION -->
|
||||
|
||||
<!-- END SECURITY FIXES AUTOMATED SECTION -->
|
||||
|
||||
@@ -36,17 +36,10 @@ module API
|
||||
get do
|
||||
items = @meeting.agenda_items.includes(:author, :presenter, :work_package, :meeting_section)
|
||||
MeetingAgendaItemCollectionRepresenter.new(items,
|
||||
self_link: api_v3_paths.meeting_agenda_items(@meeting.id),
|
||||
self_link: api_v3_paths.meeting_agenda_items(meeting_id: @meeting.id),
|
||||
current_user:)
|
||||
end
|
||||
|
||||
post(&::API::V3::Utilities::Endpoints::Create
|
||||
.new(model: MeetingAgendaItem,
|
||||
params_modifier: ->(params) {
|
||||
params.except(:meeting, :meeting_id).merge(meeting: @meeting)
|
||||
})
|
||||
.mount)
|
||||
|
||||
route_param :agenda_item_id, type: Integer, desc: "Agenda item ID" do
|
||||
after_validation do
|
||||
@meeting_agenda_item = @meeting.agenda_items.find(declared_params[:agenda_item_id])
|
||||
@@ -54,10 +47,6 @@ module API
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingAgendaItem).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingAgendaItem).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingAgendaItem).mount
|
||||
|
||||
mount ::API::V3::MeetingOutcomes::OutcomesByAgendaItemAPI
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,8 +42,7 @@ module API
|
||||
{ outcomes: %i[author work_package] }
|
||||
]
|
||||
|
||||
self_link id_attribute: ->(*) { [represented.meeting_id, represented.id] },
|
||||
title_getter: ->(*) { represented.title }
|
||||
self_link title_getter: ->(*) { represented.title }
|
||||
|
||||
property :id
|
||||
|
||||
@@ -88,7 +87,7 @@ module API
|
||||
next if represented.meeting_section_id.nil?
|
||||
|
||||
{
|
||||
href: api_v3_paths.meeting_section(represented.meeting_id, represented.meeting_section_id),
|
||||
href: api_v3_paths.meeting_section(represented.meeting_section_id),
|
||||
title: represented.meeting_section&.title
|
||||
}
|
||||
}
|
||||
@@ -102,8 +101,7 @@ module API
|
||||
link: ->(*) {
|
||||
represented.outcomes.map do |outcome|
|
||||
{
|
||||
href: api_v3_paths
|
||||
.meeting_agenda_item_outcome(represented.meeting_id, represented.id, outcome.id),
|
||||
href: api_v3_paths.meeting_outcome(outcome.id),
|
||||
title: outcome.id.to_s
|
||||
}
|
||||
end
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
module API
|
||||
module V3
|
||||
module MeetingAgendaItems
|
||||
class MeetingAgendaItemsAPI < ::API::OpenProjectAPI
|
||||
resources :meeting_agenda_items do
|
||||
post &::API::V3::Utilities::Endpoints::Create.new(model: MeetingAgendaItem).mount
|
||||
|
||||
route_param :id, type: Integer, desc: "Agenda item ID" do
|
||||
after_validation do
|
||||
@meeting_agenda_item = MeetingAgendaItem
|
||||
.joins(meeting: :project)
|
||||
.merge(Meeting.visible)
|
||||
.find(declared_params[:id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingAgendaItem).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingAgendaItem).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingAgendaItem).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -39,10 +39,7 @@ module API
|
||||
|
||||
self.to_eager_load = [{ meeting_agenda_item: :meeting }, :author, :work_package]
|
||||
|
||||
self_link path: :meeting_agenda_item_outcome,
|
||||
id_attribute: ->(*) {
|
||||
[represented.meeting_agenda_item.meeting_id, represented.meeting_agenda_item_id, represented.id]
|
||||
},
|
||||
self_link path: :meeting_outcome,
|
||||
title_getter: ->(*) { represented.id.to_s }
|
||||
|
||||
property :id
|
||||
@@ -56,13 +53,16 @@ module API
|
||||
representer: ::API::V3::Users::UserRepresenter,
|
||||
skip_render: ->(*) { represented.author_id.nil? }
|
||||
|
||||
link :agendaItem do
|
||||
{
|
||||
href: api_v3_paths.meeting_agenda_item(represented.meeting_agenda_item.meeting_id,
|
||||
represented.meeting_agenda_item_id),
|
||||
title: represented.meeting_agenda_item.title
|
||||
}
|
||||
end
|
||||
associated_resource :meeting_agenda_item,
|
||||
as: :agendaItem,
|
||||
link: ->(*) {
|
||||
next if represented.meeting_agenda_item_id.nil?
|
||||
|
||||
{
|
||||
href: api_v3_paths.meeting_agenda_item(represented.meeting_agenda_item_id),
|
||||
title: represented.meeting_agenda_item.title
|
||||
}
|
||||
}
|
||||
|
||||
associated_visible_resource :work_package
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
module API
|
||||
module V3
|
||||
module MeetingOutcomes
|
||||
class MeetingOutcomesAPI < ::API::OpenProjectAPI
|
||||
resources :meeting_outcomes do
|
||||
post &::API::V3::Utilities::Endpoints::Create.new(model: MeetingOutcome).mount
|
||||
|
||||
route_param :id, type: Integer, desc: "Outcome ID" do
|
||||
after_validation do
|
||||
@meeting_outcome = MeetingOutcome
|
||||
.joins(meeting_agenda_item: { meeting: :project })
|
||||
.merge(Meeting.visible)
|
||||
.find(declared_params[:id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingOutcome).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingOutcome).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingOutcome).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -38,29 +38,17 @@ module API
|
||||
|
||||
MeetingOutcomeCollectionRepresenter.new(outcomes,
|
||||
self_link: api_v3_paths
|
||||
.meeting_agenda_item_outcomes(@meeting.id, @meeting_agenda_item.id),
|
||||
.meeting_agenda_item_outcomes(@meeting_agenda_item.id,
|
||||
meeting_id: @meeting.id),
|
||||
current_user:)
|
||||
end
|
||||
|
||||
post(&::API::V3::Utilities::Endpoints::Create
|
||||
.new(model: MeetingOutcome,
|
||||
params_modifier: ->(params) {
|
||||
params
|
||||
.except(:meeting_agenda_item, :meeting_agenda_item_id)
|
||||
.merge(meeting_agenda_item: @meeting_agenda_item)
|
||||
})
|
||||
.mount)
|
||||
|
||||
route_param :outcome_id, type: Integer, desc: "Outcome ID" do
|
||||
after_validation do
|
||||
@meeting_outcome = @meeting_agenda_item.outcomes.find(declared_params[:outcome_id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingOutcome).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingOutcome).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingOutcome).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,8 +38,7 @@ module API
|
||||
|
||||
self.to_eager_load = [:meeting]
|
||||
|
||||
self_link id_attribute: ->(*) { [represented.meeting_id, represented.id] },
|
||||
title_getter: ->(*) { represented.title }
|
||||
self_link title_getter: ->(*) { represented.title }
|
||||
|
||||
property :id
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
module API
|
||||
module V3
|
||||
module MeetingSections
|
||||
class MeetingSectionsAPI < ::API::OpenProjectAPI
|
||||
resources :meeting_sections do
|
||||
post &::API::V3::Utilities::Endpoints::Create.new(model: MeetingSection).mount
|
||||
|
||||
route_param :id, type: Integer, desc: "Section ID" do
|
||||
after_validation do
|
||||
@meeting_section = MeetingSection
|
||||
.joins(meeting: :project)
|
||||
.merge(Meeting.visible)
|
||||
.find(declared_params[:id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingSection).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingSection).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingSection).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -36,27 +36,16 @@ module API
|
||||
get do
|
||||
sections = @meeting.sections
|
||||
MeetingSectionCollectionRepresenter.new(sections,
|
||||
self_link: api_v3_paths.meeting_sections(@meeting.id),
|
||||
self_link: api_v3_paths.meeting_sections(meeting_id: @meeting.id),
|
||||
current_user:)
|
||||
end
|
||||
|
||||
post(&::API::V3::Utilities::Endpoints::Create
|
||||
.new(model: MeetingSection,
|
||||
params_modifier: ->(params) {
|
||||
params.except(:meeting, :meeting_id).merge(meeting: @meeting)
|
||||
})
|
||||
.mount)
|
||||
|
||||
route_param :section_id, type: Integer, desc: "Section ID" do
|
||||
after_validation do
|
||||
@meeting_section = @meeting.sections.find(declared_params[:section_id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingSection).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingSection).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingSection).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,13 +76,13 @@ module API
|
||||
|
||||
link :agendaItems do
|
||||
{
|
||||
href: api_v3_paths.meeting_agenda_items(represented.id)
|
||||
href: api_v3_paths.meeting_agenda_items(meeting_id: represented.id)
|
||||
}
|
||||
end
|
||||
|
||||
link :sections do
|
||||
{
|
||||
href: api_v3_paths.meeting_sections(represented.id)
|
||||
href: api_v3_paths.meeting_sections(meeting_id: represented.id)
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -58,6 +59,10 @@ module API
|
||||
mount ::API::V3::MeetingSections::SectionsByMeetingAPI
|
||||
end
|
||||
end
|
||||
|
||||
mount ::API::V3::MeetingAgendaItems::MeetingAgendaItemsAPI
|
||||
mount ::API::V3::MeetingSections::MeetingSectionsAPI
|
||||
mount ::API::V3::MeetingOutcomes::MeetingOutcomesAPI
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -241,28 +241,52 @@ module OpenProject::Meeting
|
||||
"#{root}/meetings/#{id}/form"
|
||||
end
|
||||
|
||||
add_api_path :meeting_agenda_items do |meeting_id|
|
||||
"#{meeting(meeting_id)}/agenda_items"
|
||||
add_api_path :meeting_agenda_items do |meeting_id: nil|
|
||||
if meeting_id
|
||||
"#{meeting(meeting_id)}/agenda_items"
|
||||
else
|
||||
"#{root}/meeting_agenda_items"
|
||||
end
|
||||
end
|
||||
|
||||
add_api_path :meeting_agenda_item do |meeting_id, id|
|
||||
"#{meeting(meeting_id)}/agenda_items/#{id}"
|
||||
add_api_path :meeting_agenda_item do |id, meeting_id: nil|
|
||||
if meeting_id
|
||||
"#{meeting(meeting_id)}/agenda_items/#{id}"
|
||||
else
|
||||
"#{root}/meeting_agenda_items/#{id}"
|
||||
end
|
||||
end
|
||||
|
||||
add_api_path :meeting_agenda_item_outcomes do |meeting_id, agenda_item_id|
|
||||
"#{meeting_agenda_item(meeting_id, agenda_item_id)}/outcomes"
|
||||
add_api_path :meeting_agenda_item_outcomes do |agenda_item_id, meeting_id: nil|
|
||||
"#{meeting_agenda_item(agenda_item_id, meeting_id:)}/outcomes"
|
||||
end
|
||||
|
||||
add_api_path :meeting_agenda_item_outcome do |meeting_id, agenda_item_id, id|
|
||||
"#{meeting_agenda_item_outcomes(meeting_id, agenda_item_id)}/#{id}"
|
||||
add_api_path :meeting_outcomes do
|
||||
"#{root}/meeting_outcomes"
|
||||
end
|
||||
|
||||
add_api_path :meeting_sections do |meeting_id|
|
||||
"#{meeting(meeting_id)}/sections"
|
||||
add_api_path :meeting_outcome do |id|
|
||||
"#{root}/meeting_outcomes/#{id}"
|
||||
end
|
||||
|
||||
add_api_path :meeting_section do |meeting_id, id|
|
||||
"#{meeting(meeting_id)}/sections/#{id}"
|
||||
add_api_path :meeting_agenda_item_outcome do |id, agenda_item_id:, meeting_id: nil|
|
||||
"#{meeting_agenda_item_outcomes(agenda_item_id, meeting_id:)}/#{id}"
|
||||
end
|
||||
|
||||
add_api_path :meeting_sections do |meeting_id: nil|
|
||||
if meeting_id
|
||||
"#{meeting(meeting_id)}/sections"
|
||||
else
|
||||
"#{root}/meeting_sections"
|
||||
end
|
||||
end
|
||||
|
||||
add_api_path :meeting_section do |id, meeting_id: nil|
|
||||
if meeting_id
|
||||
"#{meeting(meeting_id)}/sections/#{id}"
|
||||
else
|
||||
"#{root}/meeting_sections/#{id}"
|
||||
end
|
||||
end
|
||||
|
||||
add_api_path :recurring_meetings do
|
||||
|
||||
@@ -35,6 +35,7 @@ RSpec.describe MeetingSections::CreateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:other_project) { create(:project) }
|
||||
let(:meeting) { create(:meeting, project:) }
|
||||
let(:section) { build(:meeting_section, meeting:) }
|
||||
let(:contract) { described_class.new(section, user) }
|
||||
@@ -79,6 +80,14 @@ RSpec.describe MeetingSections::CreateContract do
|
||||
it_behaves_like "contract is invalid", base: :does_not_exist
|
||||
end
|
||||
|
||||
context "with permission in another project" do
|
||||
let(:user) do
|
||||
create(:user, member_with_permissions: { other_project => %i[view_meetings manage_agendas] })
|
||||
end
|
||||
|
||||
it_behaves_like "contract is invalid", base: :does_not_exist
|
||||
end
|
||||
|
||||
include_examples "contract reuses the model errors" do
|
||||
let(:user) { build_stubbed(:user) }
|
||||
end
|
||||
|
||||
@@ -35,6 +35,7 @@ RSpec.describe MeetingSections::DeleteContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:other_project) { create(:project) }
|
||||
shared_let(:meeting) { create(:meeting, project:) }
|
||||
let(:section) { create(:meeting_section, meeting:) }
|
||||
let(:contract) { described_class.new(section, user) }
|
||||
@@ -69,6 +70,14 @@ RSpec.describe MeetingSections::DeleteContract do
|
||||
it_behaves_like "contract is invalid", base: :error_unauthorized
|
||||
end
|
||||
|
||||
context "with permission in another project" do
|
||||
let(:user) do
|
||||
create(:user, member_with_permissions: { other_project => %i[view_meetings manage_agendas] })
|
||||
end
|
||||
|
||||
it_behaves_like "contract is invalid", base: :error_unauthorized
|
||||
end
|
||||
|
||||
include_examples "contract reuses the model errors" do
|
||||
let(:user) { build_stubbed(:user) }
|
||||
end
|
||||
|
||||
@@ -35,6 +35,7 @@ RSpec.describe MeetingSections::UpdateContract do
|
||||
include_context "ModelContract shared context"
|
||||
|
||||
shared_let(:project) { create(:project) }
|
||||
shared_let(:other_project) { create(:project) }
|
||||
shared_let(:meeting) { create(:meeting, project:) }
|
||||
shared_let(:section) { create(:meeting_section, meeting:) }
|
||||
let(:contract) { described_class.new(section, user) }
|
||||
@@ -61,6 +62,14 @@ RSpec.describe MeetingSections::UpdateContract do
|
||||
it_behaves_like "contract is invalid", base: :error_unauthorized
|
||||
end
|
||||
|
||||
context "with permission in another project" do
|
||||
let(:user) do
|
||||
create(:user, member_with_permissions: { other_project => %i[view_meetings manage_agendas] })
|
||||
end
|
||||
|
||||
it_behaves_like "contract is invalid", base: :error_unauthorized
|
||||
end
|
||||
|
||||
include_examples "contract reuses the model errors" do
|
||||
let(:user) { build_stubbed(:user) }
|
||||
end
|
||||
|
||||
+128
-11
@@ -51,7 +51,7 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/agenda_items" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_items(meeting.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_items(meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -69,6 +69,18 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
expect(last_response.body)
|
||||
.to have_json_size(1)
|
||||
.at_path("_embedded/elements/0/_embedded/outcomes")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_outcome(outcome.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/outcomes/0/href")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_agenda_item(agenda_item.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/self/href")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_section(section.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/section/href")
|
||||
end
|
||||
|
||||
context "without view_meetings permission" do
|
||||
@@ -80,11 +92,16 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v3/meetings/:meeting_id/agenda_items" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_items(meeting.id) }
|
||||
describe "POST /api/v3/meeting_agenda_items" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_items }
|
||||
let(:body) do
|
||||
{
|
||||
title: "New agenda item"
|
||||
title: "New agenda item",
|
||||
_links: {
|
||||
meeting: {
|
||||
href: api_v3_paths.meeting(meeting.id)
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
@@ -109,6 +126,44 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
.at_path("title")
|
||||
end
|
||||
|
||||
context "with a section href returned by the section collection" do
|
||||
let!(:target_section) { create(:meeting_section, meeting:) }
|
||||
let(:target_section_href) do
|
||||
get api_v3_paths.meeting_sections(meeting_id: meeting.id)
|
||||
|
||||
JSON
|
||||
.parse(last_response.body)
|
||||
.dig("_embedded", "elements")
|
||||
.find { |item| item["id"] == target_section.id }
|
||||
.dig("_links", "self", "href")
|
||||
end
|
||||
let(:body) do
|
||||
{
|
||||
title: "New agenda item in target section",
|
||||
_links: {
|
||||
meeting: {
|
||||
href: api_v3_paths.meeting(meeting.id)
|
||||
},
|
||||
section: {
|
||||
href: target_section_href
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
it "responds with 201" do
|
||||
expect(target_section_href).to eq(api_v3_paths.meeting_section(target_section.id))
|
||||
expect(response).to have_http_status(:created)
|
||||
end
|
||||
|
||||
it "creates the agenda item in that section" do
|
||||
response
|
||||
|
||||
expect(meeting.agenda_items.find_by(title: "New agenda item in target section").meeting_section)
|
||||
.to eq(target_section)
|
||||
end
|
||||
end
|
||||
|
||||
context "without manage_agendas permission" do
|
||||
let(:permissions) { %i[view_meetings] }
|
||||
|
||||
@@ -119,7 +174,7 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(meeting.id, agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id, meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -141,7 +196,7 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
|
||||
context "with an item from another meeting" do
|
||||
let(:other_meeting) { create(:meeting, project:, author: current_user) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(other_meeting.id, agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id, meeting_id: other_meeting.id) }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
@@ -155,7 +210,7 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
create(:wp_meeting_agenda_item, meeting:, meeting_section: section, work_package: private_work_package,
|
||||
author: current_user)
|
||||
end
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(meeting.id, wp_agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(wp_agenda_item.id, meeting_id: meeting.id) }
|
||||
|
||||
it "returns 200" do
|
||||
expect(last_response).to have_http_status(:ok)
|
||||
@@ -173,8 +228,34 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meetings/:meeting_id/agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(meeting.id, agenda_item.id) }
|
||||
describe "GET /api/v3/meeting_agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
it "returns 200 and the agenda item" do
|
||||
expect(last_response).to have_http_status(:ok)
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql("MeetingAgendaItem".to_json)
|
||||
.at_path("_type")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_agenda_item(agenda_item.id).to_json)
|
||||
.at_path("_links/self/href")
|
||||
end
|
||||
|
||||
context "without view_meetings permission" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meeting_agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id) }
|
||||
let(:body) do
|
||||
{
|
||||
title: "Updated title",
|
||||
@@ -193,6 +274,42 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
expect(agenda_item.reload.title).to eq("Updated title")
|
||||
end
|
||||
|
||||
context "with a section href returned by the agenda item collection" do
|
||||
let(:target_section) { create(:meeting_section, meeting:) }
|
||||
let!(:target_agenda_item) do
|
||||
create(:meeting_agenda_item, meeting:, meeting_section: target_section, author: current_user)
|
||||
end
|
||||
let(:target_section_href) do
|
||||
get api_v3_paths.meeting_agenda_items(meeting_id: meeting.id)
|
||||
|
||||
JSON
|
||||
.parse(last_response.body)
|
||||
.dig("_embedded", "elements")
|
||||
.find { |item| item["id"] == target_agenda_item.id }
|
||||
.dig("_links", "section", "href")
|
||||
end
|
||||
let(:body) do
|
||||
{
|
||||
lockVersion: agenda_item.lock_version,
|
||||
_links: {
|
||||
section: {
|
||||
href: target_section_href
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
it "responds with 200" do
|
||||
expect(target_section_href).to eq(api_v3_paths.meeting_section(target_section.id))
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
|
||||
it "moves the agenda item to that section" do
|
||||
response
|
||||
expect(agenda_item.reload.meeting_section).to eq(target_section)
|
||||
end
|
||||
end
|
||||
|
||||
context "without manage_agendas permission" do
|
||||
let(:permissions) { %i[view_meetings] }
|
||||
|
||||
@@ -202,8 +319,8 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/v3/meetings/:meeting_id/agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(meeting.id, agenda_item.id) }
|
||||
describe "DELETE /api/v3/meeting_agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id) }
|
||||
|
||||
before { delete path }
|
||||
|
||||
|
||||
+68
-12
@@ -51,7 +51,7 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(meeting.id, agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(agenda_item.id, meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -65,11 +65,19 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
expect(last_response.body)
|
||||
.to have_json_size(1)
|
||||
.at_path("_embedded/elements")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_outcome(outcome.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/self/href")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_agenda_item(agenda_item.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/agendaItem/href")
|
||||
end
|
||||
|
||||
context "with an agenda item from another meeting" do
|
||||
let(:other_meeting) { create(:meeting, project:, author: current_user) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(other_meeting.id, agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(agenda_item.id, meeting_id: other_meeting.id) }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
@@ -108,12 +116,17 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(meeting.id, agenda_item.id) }
|
||||
describe "POST /api/v3/meeting_outcomes" do
|
||||
let(:path) { api_v3_paths.meeting_outcomes }
|
||||
let(:body) do
|
||||
{
|
||||
kind: "information",
|
||||
notes: { raw: "Outcome created via API" }
|
||||
notes: { raw: "Outcome created via API" },
|
||||
_links: {
|
||||
agendaItem: {
|
||||
href: api_v3_paths.meeting_agenda_item(agenda_item.id)
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
@@ -153,6 +166,9 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
{
|
||||
kind: "work_package",
|
||||
_links: {
|
||||
agendaItem: {
|
||||
href: api_v3_paths.meeting_agenda_item(agenda_item.id)
|
||||
},
|
||||
workPackage: {
|
||||
href: api_v3_paths.work_package(work_package.id)
|
||||
}
|
||||
@@ -182,6 +198,9 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
{
|
||||
kind: "work_package",
|
||||
_links: {
|
||||
agendaItem: {
|
||||
href: api_v3_paths.meeting_agenda_item(agenda_item.id)
|
||||
},
|
||||
workPackage: {
|
||||
href: api_v3_paths.work_package(private_work_package.id)
|
||||
}
|
||||
@@ -197,7 +216,11 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcome(meeting.id, agenda_item.id, outcome.id) }
|
||||
let(:path) do
|
||||
api_v3_paths.meeting_agenda_item_outcome(outcome.id,
|
||||
agenda_item_id: agenda_item.id,
|
||||
meeting_id: meeting.id)
|
||||
end
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -211,11 +234,19 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(outcome.id.to_json)
|
||||
.at_path("id")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_outcome(outcome.id).to_json)
|
||||
.at_path("_links/self/href")
|
||||
end
|
||||
|
||||
context "with an outcome from another agenda item" do
|
||||
let(:other_agenda_item) { create(:meeting_agenda_item, meeting:, meeting_section: section, author: current_user) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcome(meeting.id, other_agenda_item.id, outcome.id) }
|
||||
let(:path) do
|
||||
api_v3_paths.meeting_agenda_item_outcome(outcome.id,
|
||||
agenda_item_id: other_agenda_item.id,
|
||||
meeting_id: meeting.id)
|
||||
end
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
@@ -242,13 +273,38 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
.at_path("_links/workPackage/href")
|
||||
|
||||
expect(last_response.body).not_to have_json_path("_embedded/workPackage")
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcome(meeting.id, agenda_item.id, outcome.id) }
|
||||
describe "GET /api/v3/meeting_outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_outcome(outcome.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
it "returns 200 and the outcome" do
|
||||
expect(last_response).to have_http_status(:ok)
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql("MeetingOutcome".to_json)
|
||||
.at_path("_type")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_outcome(outcome.id).to_json)
|
||||
.at_path("_links/self/href")
|
||||
end
|
||||
|
||||
context "without view_meetings permission" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meeting_outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_outcome(outcome.id) }
|
||||
let(:body) do
|
||||
{
|
||||
notes: { raw: "Updated outcome" }
|
||||
@@ -271,8 +327,8 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcome(meeting.id, agenda_item.id, outcome.id) }
|
||||
describe "DELETE /api/v3/meeting_outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_outcome(outcome.id) }
|
||||
|
||||
before { delete path }
|
||||
|
||||
|
||||
+126
-19
@@ -36,20 +36,42 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
include API::V3::Utilities::PathHelper
|
||||
|
||||
shared_let(:project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
shared_let(:other_project) { create(:project, enabled_module_names: %w[meetings]) }
|
||||
shared_let(:author) { create(:user) }
|
||||
|
||||
let(:permissions) { %i[view_meetings manage_agendas] }
|
||||
let(:current_user) do
|
||||
create(:user, member_with_permissions: { project => permissions })
|
||||
end
|
||||
let(:meeting) { create(:meeting, project:, author: current_user) }
|
||||
let(:meeting) { create(:meeting, project:, author:) }
|
||||
let!(:section) { create(:meeting_section, meeting:, title: "First Section") }
|
||||
|
||||
before do
|
||||
login_as current_user
|
||||
end
|
||||
|
||||
shared_examples "not found without meeting visibility" do
|
||||
context "without view_meetings permission" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context "with view_meetings permission in another project" do
|
||||
let(:current_user) do
|
||||
create(:user, member_with_permissions: { other_project => %i[view_meetings manage_agendas] })
|
||||
end
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/sections" do
|
||||
let(:path) { api_v3_paths.meeting_sections(meeting.id) }
|
||||
let(:path) { api_v3_paths.meeting_sections(meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -59,22 +81,25 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
expect(last_response.body)
|
||||
.to be_json_eql("Collection".to_json)
|
||||
.at_path("_type")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_section(section.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/self/href")
|
||||
end
|
||||
|
||||
context "without view_meetings permission" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
it_behaves_like "not found without meeting visibility"
|
||||
end
|
||||
|
||||
describe "POST /api/v3/meetings/:meeting_id/sections" do
|
||||
let(:path) { api_v3_paths.meeting_sections(meeting.id) }
|
||||
describe "POST /api/v3/meeting_sections" do
|
||||
let(:path) { api_v3_paths.meeting_sections }
|
||||
let(:body) do
|
||||
{
|
||||
title: "New Section"
|
||||
title: "New Section",
|
||||
_links: {
|
||||
meeting: {
|
||||
href: api_v3_paths.meeting(meeting.id)
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
@@ -106,10 +131,30 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
context "without any permissions" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 422 and does not create a section" do
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(meeting.sections.find_by(title: "New Section")).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "with manage_agendas permission in another project" do
|
||||
let(:current_user) do
|
||||
create(:user, member_with_permissions: { other_project => %i[view_meetings manage_agendas] })
|
||||
end
|
||||
|
||||
it "returns 422 and does not create a section" do
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(meeting.sections.find_by(title: "New Section")).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(meeting.id, section.id) }
|
||||
let(:path) { api_v3_paths.meeting_section(section.id, meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -126,17 +171,39 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
end
|
||||
|
||||
context "with a section from another meeting" do
|
||||
let(:other_meeting) { create(:meeting, project:, author: current_user) }
|
||||
let(:path) { api_v3_paths.meeting_section(other_meeting.id, section.id) }
|
||||
let(:other_meeting) { create(:meeting, project:, author:) }
|
||||
let(:path) { api_v3_paths.meeting_section(section.id, meeting_id: other_meeting.id) }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like "not found without meeting visibility"
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meetings/:meeting_id/sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(meeting.id, section.id) }
|
||||
describe "GET /api/v3/meeting_sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(section.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
it "returns 200 and the section" do
|
||||
expect(last_response).to have_http_status(:ok)
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql("MeetingSection".to_json)
|
||||
.at_path("_type")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_section(section.id).to_json)
|
||||
.at_path("_links/self/href")
|
||||
end
|
||||
|
||||
it_behaves_like "not found without meeting visibility"
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meeting_sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(section.id) }
|
||||
let(:body) do
|
||||
{
|
||||
title: "Updated Section Title"
|
||||
@@ -161,10 +228,30 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
context "without any permissions" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 404 and does not update the section" do
|
||||
expect(response).to have_http_status(:not_found)
|
||||
expect(section.reload.title).to eq("First Section")
|
||||
end
|
||||
end
|
||||
|
||||
context "with manage_agendas permission in another project" do
|
||||
let(:current_user) do
|
||||
create(:user, member_with_permissions: { other_project => %i[view_meetings manage_agendas] })
|
||||
end
|
||||
|
||||
it "returns 404 and does not update the section" do
|
||||
expect(response).to have_http_status(:not_found)
|
||||
expect(section.reload.title).to eq("First Section")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/v3/meetings/:meeting_id/sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(meeting.id, section.id) }
|
||||
describe "DELETE /api/v3/meeting_sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(section.id) }
|
||||
|
||||
before { delete path }
|
||||
|
||||
@@ -185,5 +272,25 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
|
||||
it_behaves_like "unauthorized access"
|
||||
end
|
||||
|
||||
context "without any permissions" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 404 and does not delete the section" do
|
||||
expect(subject).to have_http_status(:not_found)
|
||||
expect(MeetingSection).to exist(section.id)
|
||||
end
|
||||
end
|
||||
|
||||
context "with manage_agendas permission in another project" do
|
||||
let(:current_user) do
|
||||
create(:user, member_with_permissions: { other_project => %i[view_meetings manage_agendas] })
|
||||
end
|
||||
|
||||
it "returns 404 and does not delete the section" do
|
||||
expect(subject).to have_http_status(:not_found)
|
||||
expect(MeetingSection).to exist(section.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user