Skip to content

Commit f86f527

Browse files
🚀 [Feature]: Decompose the Confluence client into the PSModule source layout
Implements the first working version of the module by porting the generalized Confluence REST v2 client and decomposing it into the PSModule one-function-per-file source layout. - 35 public functions grouped by resource area (Auth, Config, API, Spaces, Site, Pages, BlogPosts, Folders, Comments, Labels, ContentProperties, Attachments, Restrictions, Users) - 4 private helpers (Auth, Config); module state in variables/private - Declares a dependency on the Context module via #Requires in header.ps1 (RequiredVersion 8.1.6), following the GitHub module pattern; credentials/config persist in the 'PSModule.Confluence' context vault - Removes the template scaffold placeholders; adds Connecting/Pages examples and a credential-free surface test plus a skipped integration scaffold that reads connection details from environment secrets - No tenant-specific data is included; examples use generic placeholders
1 parent a22038b commit f86f527

52 files changed

Lines changed: 1740 additions & 101 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 24 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
# Confluence
22

3-
A PowerShell module that interacts with Atlassian Confluence
3+
Confluence is a PowerShell module for interacting with the Atlassian Confluence Cloud REST API, both interactively and in automation.
44

5-
## Prerequisites
6-
7-
This uses the following external resources:
8-
- The [PSModule framework](https://github.com/PSModule) for building, testing and publishing the module.
5+
It exposes pages, blog posts, folders, spaces, comments, labels, content properties, attachments, restrictions and more as PowerShell commands.
6+
Every command is a thin wrapper over a single generic REST entry point (`Invoke-ConfluenceRestMethod`). Credentials and module configuration
7+
are stored with the [Context](https://github.com/PSModule/Context) module, so you connect once and reuse the profile across sessions.
98

109
## Installation
1110

12-
To install the module from the PowerShell Gallery, you can use the following command:
11+
Install the module from the PowerShell Gallery:
1312

1413
```powershell
1514
Install-PSResource -Name Confluence
@@ -18,52 +17,33 @@ Import-Module -Name Confluence
1817

1918
## Usage
2019

21-
Here is a list of example that are typical use cases for the module.
22-
23-
### Example 1: Greet an entity
24-
25-
Provide examples for typical commands that a user would like to do with the module.
20+
Connect with a scoped Atlassian API token, then call the resource commands. The token is kept as a `SecureString` in the Context vault.
2621

2722
```powershell
28-
Greet-Entity -Name 'World'
29-
Hello, World!
23+
# Connect and store a reusable, named credential profile
24+
$token = Read-Host -AsSecureString # a scoped Atlassian API token
25+
Connect-Confluence -ApiBaseUri 'https://api.atlassian.com/ex/confluence/<cloudId>' -Username 'you@example.com' -Token $token -SpaceKey 'DOCS'
26+
27+
# Work with content
28+
$space = Get-ConfluenceSpace -Key 'DOCS'
29+
$page = New-ConfluencePage -SpaceId $space.id -Title 'Release notes' -Body '<p>Hello</p>'
30+
Set-ConfluencePage -PageId $page.id -Body '<p>Updated</p>'
31+
Get-ConfluencePageChild -PageId $page.id
3032
```
3133

32-
### Example 2
33-
34-
Provide examples for typical commands that a user would like to do with the module.
35-
36-
```powershell
37-
Import-Module -Name PSModuleTemplate
38-
```
39-
40-
### Find more examples
41-
42-
To find more examples of how to use the module, please refer to the [examples](examples) folder.
43-
44-
Alternatively, you can use the Get-Command -Module 'This module' to find more commands that are available in the module.
45-
To find examples of each of the commands you can use Get-Help -Examples 'CommandName'.
34+
See the [examples](examples) folder for more, including managing contexts and pages.
4635

4736
## Documentation
4837

49-
Link to further documentation if available, or describe where in the repository users can find more detailed documentation about
50-
the module's functions and features.
51-
52-
## Contributing
53-
54-
Coder or not, you can contribute to the project! We welcome all contributions.
55-
56-
### For Users
38+
Documentation is published at [psmodule.io/Confluence](https://psmodule.io/Confluence/).
5739

58-
If you don't code, you still sit on valuable information that can make this project even better. If you experience that the
59-
product does unexpected things, throw errors or is missing functionality, you can help by submitting bugs and feature requests.
60-
Please see the issues tab on this project and submit a new issue that matches your needs.
40+
Use PowerShell help and command discovery for module details:
6141

62-
### For Developers
63-
64-
If you do code, we'd love to have your contributions. Please read the [Contribution guidelines](CONTRIBUTING.md) for more information.
65-
You can either help by picking up an existing issue or submit a new one if you have an idea for a new feature or improvement.
42+
```powershell
43+
Get-Command -Module Confluence
44+
Get-Help New-ConfluencePage -Examples
45+
```
6646

67-
## Acknowledgements
47+
## Contributing
6848

69-
Here is a list of people and projects that helped this project in some way.
49+
Issues and pull requests are welcome. Please use the repository issue tracker to report bugs, request features, or discuss improvements.

‎examples/Connecting.ps1‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<#
2+
.SYNOPSIS
3+
Connect to Confluence and manage credential profiles (contexts).
4+
5+
.DESCRIPTION
6+
Confluence stores each connection as a named context in the Context vault.
7+
The token is kept as a SecureString. One context is the default; any command
8+
can target a specific context with -Context.
9+
#>
10+
11+
# Import the module
12+
Import-Module -Name 'Confluence'
13+
14+
###
15+
### CONNECTING
16+
###
17+
18+
# Connect with a scoped Atlassian API token and store a reusable default profile.
19+
$token = Read-Host -AsSecureString # a scoped Atlassian API token
20+
Connect-Confluence -ApiBaseUri 'https://api.atlassian.com/ex/confluence/<cloudId>' -Username 'you@example.com' -Token $token -SpaceKey 'DOCS'
21+
22+
# Store several sites/accounts under explicit names and select per call.
23+
Connect-Confluence -ApiBaseUri 'https://api.atlassian.com/ex/confluence/<cloudId>' -Username 'you@example.com' -Token $token -Name 'sandbox'
24+
Get-ConfluenceSpace -Key 'DOCS' -Context 'sandbox'
25+
26+
###
27+
### CONTEXTS / PROFILES
28+
###
29+
30+
# The default context
31+
Get-ConfluenceContext
32+
33+
# All stored contexts
34+
Get-ConfluenceContext -ListAvailable
35+
36+
###
37+
### MODULE CONFIGURATION
38+
###
39+
40+
# Read and set module configuration (persisted in the same vault).
41+
Get-ConfluenceConfig
42+
Set-ConfluenceConfig -Name 'PerPage' -Value 50
43+
44+
###
45+
### DISCONNECTING
46+
###
47+
48+
Disconnect-Confluence -Name 'sandbox'

‎examples/General.ps1‎

Lines changed: 0 additions & 19 deletions
This file was deleted.

‎examples/Pages.ps1‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<#
2+
.SYNOPSIS
3+
Create, read, update and remove Confluence pages.
4+
5+
.DESCRIPTION
6+
Assumes a default context is already connected (see Connecting.ps1).
7+
#>
8+
9+
# Import the module
10+
Import-Module -Name 'Confluence'
11+
12+
# Resolve the target space
13+
$space = Get-ConfluenceSpace -Key 'DOCS'
14+
15+
# Create a page
16+
$page = New-ConfluencePage -SpaceId $space.id -Title 'Release notes' -Body '<p>First draft</p>'
17+
18+
# Read it back (storage format by default)
19+
Get-ConfluencePage -PageId $page.id
20+
21+
# Update the body (the version number is incremented automatically)
22+
Set-ConfluencePage -PageId $page.id -Body '<p>Updated content</p>'
23+
24+
# Add a child page, then list children and descendants
25+
$child = New-ConfluencePage -SpaceId $space.id -Title 'Details' -ParentId $page.id -Body '<p>Nested</p>'
26+
Get-ConfluencePageChild -PageId $page.id
27+
Get-ConfluenceDescendant -PageId $page.id
28+
29+
# Labels and comments
30+
Add-ConfluenceLabel -PageId $page.id -Label 'release', 'published'
31+
Add-ConfluenceComment -PageId $page.id -Body '<p>Looks good.</p>'
32+
33+
# Remove the whole subtree (moves the pages to trash)
34+
Remove-ConfluencePage -PageId $page.id -Recurse

‎src/finally.ps1‎

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
function Resolve-ConfluenceContext {
2+
<#
3+
.SYNOPSIS
4+
Resolve a context argument into a usable credential-context object.
5+
.DESCRIPTION
6+
Accepts a context object/hashtable (returned as-is), a context name
7+
(looked up in the vault), or nothing (falls back to the default context
8+
recorded in the module configuration).
9+
#>
10+
[CmdletBinding()]
11+
param(
12+
# A context object, a context name, or $null for the default context.
13+
[object]$Context
14+
)
15+
16+
if ($null -ne $Context -and $Context -isnot [string]) {
17+
return $Context
18+
}
19+
20+
Initialize-ConfluenceConfig
21+
$id = if ([string]::IsNullOrEmpty([string]$Context)) { $script:Confluence.Config['DefaultContext'] } else { [string]$Context }
22+
23+
if ([string]::IsNullOrEmpty($id)) {
24+
throw 'No Confluence context was specified and no default context is set. Run Connect-Confluence first.'
25+
}
26+
27+
$resolved = $null
28+
try {
29+
$resolved = Get-Context -ID $id -Vault $script:Confluence.ContextVault -ErrorAction Stop
30+
} catch {
31+
$resolved = $null
32+
}
33+
34+
if (-not $resolved) {
35+
throw "Confluence context '$id' was not found in vault '$($script:Confluence.ContextVault)'."
36+
}
37+
return $resolved
38+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
function Resolve-ConfluenceToken {
2+
<#
3+
.SYNOPSIS
4+
Return the plain-text API token from a SecureString or string.
5+
.DESCRIPTION
6+
The token is stored as a SecureString in the credential context; this
7+
converts it to the plain text needed to build the Basic auth header.
8+
#>
9+
[CmdletBinding()]
10+
[OutputType([string])]
11+
param(
12+
# The token as a SecureString or a plain string.
13+
[Parameter(Mandatory)]
14+
[object]$Token
15+
)
16+
17+
if ($Token -is [System.Security.SecureString]) {
18+
return [System.Net.NetworkCredential]::new('', $Token).Password
19+
}
20+
return [string]$Token
21+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
function ConvertTo-ConfluenceHashtable {
2+
<#
3+
.SYNOPSIS
4+
Convert a PSCustomObject (or hashtable) into a plain hashtable.
5+
.DESCRIPTION
6+
Used to turn the stored module-configuration context returned by
7+
Get-Context into a mutable hashtable.
8+
#>
9+
[CmdletBinding()]
10+
[OutputType([hashtable])]
11+
param(
12+
# The object to convert.
13+
[Parameter(Mandatory)]
14+
[object]$InputObject
15+
)
16+
17+
if ($InputObject -is [hashtable]) {
18+
# Return a shallow clone so callers can mutate the result without altering
19+
# the source hashtable (e.g. the built-in $script:Confluence.DefaultConfig).
20+
return $InputObject.Clone()
21+
}
22+
23+
$result = @{}
24+
foreach ($property in $InputObject.PSObject.Properties) {
25+
$result[$property.Name] = $property.Value
26+
}
27+
return $result
28+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
function Initialize-ConfluenceConfig {
2+
<#
3+
.SYNOPSIS
4+
Load the module configuration from the context vault into memory.
5+
.DESCRIPTION
6+
Loads the stored 'Module' configuration context, creating it from the
7+
built-in defaults on first use. Missing default keys are backfilled.
8+
#>
9+
[CmdletBinding()]
10+
param(
11+
# Recreate the configuration from the built-in defaults.
12+
[switch]$Force
13+
)
14+
15+
if (-not $Force -and $null -ne $script:Confluence.Config) {
16+
return
17+
}
18+
19+
$vault = $script:Confluence.ContextVault
20+
$id = $script:Confluence.DefaultConfig.ID
21+
22+
$stored = $null
23+
if (-not $Force) {
24+
try {
25+
$stored = Get-Context -ID $id -Vault $vault -ErrorAction Stop
26+
} catch {
27+
$stored = $null
28+
}
29+
}
30+
31+
if ($Force -or -not $stored) {
32+
$config = ConvertTo-ConfluenceHashtable -InputObject $script:Confluence.DefaultConfig
33+
} else {
34+
$config = ConvertTo-ConfluenceHashtable -InputObject $stored
35+
foreach ($key in $script:Confluence.DefaultConfig.Keys) {
36+
if (-not $config.ContainsKey($key)) {
37+
$config[$key] = $script:Confluence.DefaultConfig[$key]
38+
}
39+
}
40+
}
41+
42+
$config['ID'] = $id
43+
$null = Set-Context -ID $id -Context $config -Vault $vault
44+
$script:Confluence.Config = $config
45+
}

0 commit comments

Comments
 (0)