Skip to content

Commit 1526135

Browse files
🚀 [Feature]: Add space administration commands; rename Set-ConfluencePage to Update-ConfluencePage
Add New/Update/Set/Remove-ConfluenceSpace so spaces can be created, modified, declaratively upserted, and permanently deleted (v1 space endpoints; delete is async and returns a 202 long-running task). Rename Set-ConfluencePage to Update-ConfluencePage because it performs a partial update (increments the version), reserving the Set verb for declarative create-or-replace as used by Set-ConfluenceSpace. Update README quick-start, SCOPES scope map, and the Pages example to the new verb, and document the space-administration scope requirements (write:space / delete:space / read:content.metadata).
1 parent 85b625f commit 1526135

8 files changed

Lines changed: 271 additions & 10 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Connect-Confluence -Site 'yoursite' -Username 'you@example.com' -Token $token -S
2727
# Work with content
2828
$space = Get-ConfluenceSpace -Key 'DOCS'
2929
$page = New-ConfluencePage -SpaceId $space.id -Title 'Release notes' -Body '<p>Hello</p>'
30-
Set-ConfluencePage -PageId $page.id -Body '<p>Updated</p>'
30+
Update-ConfluencePage -PageId $page.id -Body '<p>Updated</p>'
3131
Get-ConfluencePageChild -PageId $page.id
3232
```
3333

‎SCOPES.md‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,15 @@ delete:whiteboard:confluence
9090
| `read:space:confluence` | `Get-ConfluenceSpace`, `Get-ConfluenceSiteInfo` |
9191
| `read:space.permission:confluence` | `Get-ConfluenceSpacePermission` |
9292
| `read:space.property:confluence` | `Get-ConfluenceSpaceProperty` |
93-
| `read:page:confluence` | `Get-ConfluencePage`, `Get-ConfluencePageChild`, `Get-ConfluencePageVersion`, `Set-ConfluencePage` (reads before updating) |
93+
| `read:page:confluence` | `Get-ConfluencePage`, `Get-ConfluencePageChild`, `Get-ConfluencePageVersion`, `Update-ConfluencePage` (reads before updating) |
9494
| `read:folder:confluence` | `Get-ConfluenceFolder` |
9595
| `read:attachment:confluence` | `Get-ConfluenceAttachment` |
9696
| `read:comment:confluence` | `Get-ConfluenceComment` |
9797
| `read:label:confluence` | `Get-ConfluenceLabel` |
9898
| `read:content.property:confluence` | `Get-ConfluenceContentProperty` |
9999
| `read:hierarchical-content:confluence` | `Get-ConfluenceDescendant` |
100100
| `read:content-details:confluence` | `Get-ConfluenceRestriction`, `Get-ConfluenceCurrentUser`, `Add-ConfluenceAttachment` (upload) |
101-
| `write:page:confluence` | `New-ConfluencePage`, `Set-ConfluencePage` |
101+
| `write:page:confluence` | `New-ConfluencePage`, `Update-ConfluencePage` |
102102
| `write:folder:confluence` | `New-ConfluenceFolder` |
103103
| `write:attachment:confluence` | `Add-ConfluenceAttachment` |
104104
| `write:comment:confluence` | `Add-ConfluenceComment` |
@@ -145,9 +145,15 @@ candidate cmdlets it would enable (verbs in `{}` share one scope family):
145145
- **Asymmetric sets** worth noting: `whiteboard` is delete-only; `embed` has
146146
write/delete but no read; `audit-log` is write-only. Commands for those can only
147147
cover the granted verbs.
148-
- This set has **no space-administration write** scope (`write:space` /
149-
`delete:space`): the token can read space settings, permissions and properties
150-
but cannot create, update or delete spaces.
148+
- The module provides space-administration commands (`New-ConfluenceSpace`,
149+
`Update-ConfluenceSpace`, `Set-ConfluenceSpace`, `Remove-ConfluenceSpace`), but
150+
this token set has **no
151+
space-administration write** scope (`write:space` / `delete:space`): the token
152+
can read space settings, permissions and properties but cannot create, update
153+
or delete spaces until `write:space:confluence` and `delete:space:confluence`
154+
are added (space delete also needs `read:content.metadata:confluence`). Space
155+
create/update/delete are v1-only operations, and delete is asynchronous (the
156+
API returns HTTP 202 with a long-running task).
151157
- A few commands reach v1 endpoints that Atlassian maps to these granular scopes:
152158
label add/remove (`write:label:confluence`), attachment upload
153159
(`write:attachment:confluence` plus `read:content-details:confluence`), page

‎examples/Pages.ps1‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ $page = New-ConfluencePage -SpaceId $space.id -Title 'Release notes' -Body '<p>F
1919
Get-ConfluencePage -PageId $page.id
2020

2121
# Update the body (the version number is incremented automatically)
22-
Set-ConfluencePage -PageId $page.id -Body '<p>Updated content</p>'
22+
Update-ConfluencePage -PageId $page.id -Body '<p>Updated content</p>'
2323

2424
# Add a child page, then list children and descendants
2525
New-ConfluencePage -SpaceId $space.id -Title 'Details' -ParentId $page.id -Body '<p>Nested</p>'

src/functions/public/Pages/Set-ConfluencePage.ps1 renamed to src/functions/public/Pages/Update-ConfluencePage.ps1

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
function Set-ConfluencePage {
1+
#SkipTest:FunctionTest:Integration tests are added once the repository Confluence credentials are configured.
2+
function Update-ConfluencePage {
23
<#
34
.SYNOPSIS
45
Update a Confluence page (read:page and write:page).
@@ -11,13 +12,13 @@
1112
1213
.EXAMPLE
1314
```powershell
14-
Set-ConfluencePage -PageId '12345' -Body '<p>Updated</p>'
15+
Update-ConfluencePage -PageId '12345' -Body '<p>Updated</p>'
1516
```
1617
1718
Updates the body of page 12345, incrementing its version.
1819
1920
.LINK
20-
https://psmodule.io/Confluence/Functions/Pages/Set-ConfluencePage/
21+
https://psmodule.io/Confluence/Functions/Pages/Update-ConfluencePage/
2122
2223
.LINK
2324
https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-page/
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#SkipTest:FunctionTest:Integration tests are added once the repository Confluence credentials are configured.
2+
function New-ConfluenceSpace {
3+
<#
4+
.SYNOPSIS
5+
Create a Confluence space (write:space).
6+
7+
.DESCRIPTION
8+
Creates a new global space with the given key and name, setting the
9+
properties you supply. Fails if a space with that key already exists.
10+
Space creation is
11+
a v1-only operation (the v2 API exposes no space-write endpoint) reached
12+
over the API gateway with the granular write:space scope; it also needs
13+
the global "Create Spaces" permission on the account. The creating account
14+
becomes an administrator of the new space.
15+
16+
.EXAMPLE
17+
```powershell
18+
New-ConfluenceSpace -Key 'DOCS' -Name 'Documentation' -Description 'Team docs'
19+
```
20+
21+
Creates a global space with key 'DOCS' named 'Documentation'.
22+
23+
.LINK
24+
https://psmodule.io/Confluence/Functions/Spaces/New-ConfluenceSpace/
25+
26+
.LINK
27+
https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-space/
28+
#>
29+
[CmdletBinding(SupportsShouldProcess)]
30+
param(
31+
# The unique key for the new space (letters and numbers).
32+
[Parameter(Mandatory)]
33+
[string]$Key,
34+
35+
# The display name of the new space.
36+
[Parameter(Mandatory)]
37+
[string]$Name,
38+
39+
# An optional plain-text space description.
40+
[string]$Description,
41+
42+
# The context to use: an object, a context name, or $null for the default.
43+
[object]$Context
44+
)
45+
46+
$payload = @{
47+
key = $Key
48+
name = $Name
49+
}
50+
if (-not [string]::IsNullOrEmpty($Description)) {
51+
$payload['description'] = @{
52+
plain = @{
53+
value = $Description
54+
representation = 'plain'
55+
}
56+
}
57+
}
58+
59+
if ($PSCmdlet.ShouldProcess($Key, 'Create Confluence space')) {
60+
Invoke-ConfluenceRestMethod -ApiEndpoint '/wiki/rest/api/space' -Method 'POST' -Body $payload -Context $Context
61+
}
62+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#SkipTest:FunctionTest:Integration tests are added once the repository Confluence credentials are configured.
2+
function Remove-ConfluenceSpace {
3+
<#
4+
.SYNOPSIS
5+
Permanently delete a Confluence space (delete:space and read:content.metadata).
6+
7+
.DESCRIPTION
8+
Permanently deletes a space and all of its content - the space is NOT sent
9+
to the trash and cannot be restored. The call is asynchronous: Confluence
10+
returns HTTP 202 with a long-running task descriptor. Deleting a space is a
11+
v1-only operation reached over the API gateway; it needs the granular
12+
delete:space scope (Atlassian also requires read:content.metadata on this
13+
endpoint) plus Admin permission on the space. Because deletion is
14+
irreversible, confirm the key belongs to a space you own before calling it.
15+
16+
.EXAMPLE
17+
```powershell
18+
Remove-ConfluenceSpace -Key 'DOCS'
19+
```
20+
21+
Permanently deletes the 'DOCS' space and returns the long-running task descriptor.
22+
23+
.LINK
24+
https://psmodule.io/Confluence/Functions/Spaces/Remove-ConfluenceSpace/
25+
26+
.LINK
27+
https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-space/
28+
#>
29+
[CmdletBinding(SupportsShouldProcess)]
30+
param(
31+
# The key of the space to delete.
32+
[Parameter(Mandatory)]
33+
[string]$Key,
34+
35+
# The context to use: an object, a context name, or $null for the default.
36+
[object]$Context
37+
)
38+
39+
if ($PSCmdlet.ShouldProcess($Key, 'Permanently delete Confluence space')) {
40+
Invoke-ConfluenceRestMethod -ApiEndpoint "/wiki/rest/api/space/$Key" -Method 'DELETE' -Context $Context
41+
}
42+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#SkipTest:FunctionTest:Integration tests are added once the repository Confluence credentials are configured.
2+
function Set-ConfluenceSpace {
3+
<#
4+
.SYNOPSIS
5+
Create or declaratively configure a Confluence space (read:space and write:space).
6+
7+
.DESCRIPTION
8+
Ensures a space matches the supplied configuration (a declarative upsert).
9+
If no space with the key exists it is created; if it exists it is updated.
10+
Unlike Update-ConfluenceSpace, this is a full-state set: properties that are
11+
not supplied are reset to their defaults (omitting -Description clears it).
12+
To change individual fields while preserving the rest, use
13+
Update-ConfluenceSpace. Space create/update are v1-only operations reached
14+
over the API gateway; creating a space also needs the global "Create Spaces"
15+
permission.
16+
17+
.EXAMPLE
18+
```powershell
19+
Set-ConfluenceSpace -Key 'DOCS' -Name 'Documentation' -Description 'Team docs'
20+
```
21+
22+
Creates the 'DOCS' space if it is missing, otherwise updates it, so its name
23+
and description match exactly what was supplied.
24+
25+
.EXAMPLE
26+
```powershell
27+
Set-ConfluenceSpace -Key 'DOCS' -Name 'Documentation'
28+
```
29+
30+
Declaratively sets 'DOCS' with no description, clearing any existing description.
31+
32+
.LINK
33+
https://psmodule.io/Confluence/Functions/Spaces/Set-ConfluenceSpace/
34+
35+
.LINK
36+
https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-space/
37+
#>
38+
[CmdletBinding(SupportsShouldProcess)]
39+
param(
40+
# The key of the space to create or configure.
41+
[Parameter(Mandatory)]
42+
[string]$Key,
43+
44+
# The desired display name. A space always requires a name.
45+
[Parameter(Mandatory)]
46+
[string]$Name,
47+
48+
# The desired plain-text description. Omit to clear the description.
49+
[string]$Description,
50+
51+
# The context to use: an object, a context name, or $null for the default.
52+
[object]$Context
53+
)
54+
55+
# Declarative: the supplied parameters are the full desired state, so an omitted
56+
# -Description resets the description to empty rather than preserving it.
57+
$payload = @{
58+
key = $Key
59+
name = $Name
60+
description = @{
61+
plain = @{
62+
value = [string]$Description
63+
representation = 'plain'
64+
}
65+
}
66+
}
67+
68+
# Look the space up to choose between create (POST) and update (PUT).
69+
$response = Invoke-ConfluenceRestMethod -ApiEndpoint '/wiki/api/v2/spaces' -Query @{ keys = $Key } -Context $Context
70+
$existing = $response.results | Where-Object { $_.key -eq $Key } | Select-Object -First 1
71+
72+
if ($existing) {
73+
if ($PSCmdlet.ShouldProcess($Key, 'Set Confluence space (update existing)')) {
74+
Invoke-ConfluenceRestMethod -ApiEndpoint "/wiki/rest/api/space/$Key" -Method 'PUT' -Body $payload -Context $Context
75+
}
76+
} else {
77+
if ($PSCmdlet.ShouldProcess($Key, 'Set Confluence space (create)')) {
78+
Invoke-ConfluenceRestMethod -ApiEndpoint '/wiki/rest/api/space' -Method 'POST' -Body $payload -Context $Context
79+
}
80+
}
81+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#SkipTest:FunctionTest:Integration tests are added once the repository Confluence credentials are configured.
2+
function Update-ConfluenceSpace {
3+
<#
4+
.SYNOPSIS
5+
Update a Confluence space's name or description (read:space and write:space).
6+
7+
.DESCRIPTION
8+
Updates one or more properties (name and/or description) on an existing
9+
space. Only the fields you supply change; unspecified fields keep their
10+
current values, because the space is read first (read:space) and then
11+
written back (write:space). Fails if the space does not exist. For a
12+
declarative create-or-replace, use Set-ConfluenceSpace instead. Updating a
13+
space is a v1-only operation reached over the API gateway.
14+
15+
.EXAMPLE
16+
```powershell
17+
Update-ConfluenceSpace -Key 'DOCS' -Name 'Team Documentation'
18+
```
19+
20+
Renames the 'DOCS' space, keeping its existing description.
21+
22+
.LINK
23+
https://psmodule.io/Confluence/Functions/Spaces/Update-ConfluenceSpace/
24+
25+
.LINK
26+
https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-space/
27+
#>
28+
[CmdletBinding(SupportsShouldProcess)]
29+
param(
30+
# The key of the space to update.
31+
[Parameter(Mandatory)]
32+
[string]$Key,
33+
34+
# The new display name. Defaults to the existing name.
35+
[string]$Name,
36+
37+
# The new plain-text description. Defaults to the existing description.
38+
[string]$Description,
39+
40+
# The context to use: an object, a context name, or $null for the default.
41+
[object]$Context
42+
)
43+
44+
# Read the current space (with its plain-text description) so a caller who
45+
# updates only one field does not blank the other on the full-body v1 PUT.
46+
$response = Invoke-ConfluenceRestMethod -ApiEndpoint '/wiki/api/v2/spaces' -Query @{ keys = $Key; 'description-format' = 'plain' } -Context $Context
47+
$current = $response.results | Where-Object { $_.key -eq $Key } | Select-Object -First 1
48+
if (-not $current) {
49+
throw "Confluence space '$Key' was not found."
50+
}
51+
52+
$newName = if ($PSBoundParameters.ContainsKey('Name')) { $Name } else { $current.name }
53+
$newDescription = if ($PSBoundParameters.ContainsKey('Description')) { $Description } else { [string]$current.description.plain.value }
54+
55+
$payload = @{
56+
key = $Key
57+
name = $newName
58+
description = @{
59+
plain = @{
60+
value = $newDescription
61+
representation = 'plain'
62+
}
63+
}
64+
}
65+
66+
if ($PSCmdlet.ShouldProcess($Key, 'Update Confluence space')) {
67+
Invoke-ConfluenceRestMethod -ApiEndpoint "/wiki/rest/api/space/$Key" -Method 'PUT' -Body $payload -Context $Context
68+
}
69+
}

0 commit comments

Comments
 (0)