Getting restrictions from Confluence page - powershell

I'm not very savvy with web API calls, but I've been using the following powershell code (this site in this example is one I found that has some public data... my site is internal and requires I pass the credential, which has been working for me without issue):
If(-not (Get-InstalledModule -Name 'ConfluencePS')){Install-Module ConfluencePS}
Import-Module ConfluencePS
Set-ConfluenceInfo -BaseUri "https://wiki.opnfv.org"
$space = Get-confluencepage -Spacekey ds
ForEach($item in $space)
{
$splatParams = #{
Uri = "https://wiki.opnfv.org/rest/api/content/$($item.ID)/restriction"
ContentType = 'application/json'
method = 'GET'
}
#reference https://developer.atlassian.com/cloud/confluence/rest/#api-api-content-id-restriction-get
Invoke-RestMethod #splatParams
}
The documentation for the ConfluencePS shows that restrictions is still an open feature request but I need to get this working for a project.
I put a breakpoint in on line 982 from ConfluencePS.psm1 and was able to see the various calls and how the params are structured but when I try to mimic it (and change the URI based on the confluence documentation) I get an error "HTTP error 405 - MethodNotAllowed". Anyone have suggestions on how I can get this working? I'm trying to return back the permissions applied for all pages in a specific space.

Get Restrictions by Content ID
As you found out by yourself, it is required to add "byOperation".
I was able to get the restrictions of a specific page with the following code:
# for testing purposes ONLY, I've specified the URL and ID
$wikiUrl = "https://wiki.opnfv.org"
$itemId = "6820746"
$splatParams = #{
Uri = "$wikiUrl/rest/api/content/$itemId/restriction/byOperation"
ContentType = 'application/json'
method = 'GET'
}
$result = Invoke-RestMethod #splatParams
Tested on version 6.0.4 and 6.15.9
Filter by user name
If you like to filter the result by a specific username, you can use the following URI:
"$wikiUrl/rest/api/content/$itemId/restriction/byOperation/.../user?userName=".
Bt, there's an open bug on this way of action:
restriction returns ambiguous responses

Related

Differentiate invoke-WebRequest status codes

I am attempting to validate URLs prior to downloading those files, and I want to differentiate between things like a path that requires credentials vs a bad path.
I have this at the moment
function Get-UrlStatusCode([string] $Url) {
try {
return (Invoke-WebRequest -Uri $Url -UseBasicParsing -DisableKeepAlive -Method:head).StatusCode
} catch [Net.WebException] {
return "$([Int]$_.Exception.Response.StatusCode) $($_.Exception.Response.statusDescription)"
}
}
(Get-UrlStatusCode 'http://AWSBUCKETPATH/Test_Public.xml')
(Get-UrlStatusCode 'http://AWSBUCKETPATH/Test_Private.xml')
(Get-UrlStatusCode 'http://AWSBUCKETPATH/Test_Missing.xml')
For the public path I am getting the expected StatusCode of 200, but both the private and the missing examples are returning 403 Forbidden. Is this a failure in my code, or something that needs to be configured at AWS to provide a 404 Not Found for the bad path, or is this just not something that is possible despite the existence of 404 as a code?

Teams Webhook error: Invoke-RestMethod: Bad payload received by generic incoming webhook

I'm using configured Teams webhook in my Powershell script and keep encountering the mentioned error message. What's strange, is that this exact method of configuring Webhook worked a few months ago on a different script.
Here's what I'm trying to do:
#Set URI of the Teams channel Webhook
$URI = 'https:....'
#Define Rest Method Parameters for the Teams Webhook sending
$RestMethodParameters = #{
"URI" = $URI
"Method" = 'POST'
"Body" = $null
"ContentType" = 'application/json'
}
$JSONBody = #{
"#type" = "MessageCard"
"#context" = "http://schema.org/extensions"
"themeColor" = '0078D7'
}
#Adding text to title and body
$JSONBody += #{
"title" = "'costReport-func' Function for connecting AzAccount has failed"
"text" = "Function failed at connection to AzAccount step."
}
#Sending the message to Teams
($RestMethodParameters).Body += ConvertTo-Json $JSONBody
Invoke-RestMethod #RestMethodParameters
And with this I'm getting "Bad payload received by generic incoming webhook." error message. What is causing the issue here?
Update: Microsoft has released a preview version (2.1.0) of the Teams PowerShell module which works properly with modern authentication. It’s likely that this version will be pushed through to general availability quite quickly.
Please go through this link for more information.

Publishing release notes to TFS/VSTS Wiki during Release

My mission is to generate and publish release notes on WIKI automatically when ever the release triggered, for this I am following this Blog, its very handy blog, but my bad luck still not able to create wiki page with release template. (using both Azure DevOps and TFS)
Template:
**Build Number** : $($build.buildnumber)
**Build started** : $("{0:dd/MM/yy HH:mm:ss}" -f [datetime]$build.startTime)
**Source Branch** : $($build.sourceBranch)
###Associated work items
##WILOOP##
* #$($widetail.id)
##WILOOP##
###Associated change sets/commits
##CSLOOP##
* **ID $($csdetail.changesetid)$($csdetail.commitid)**
>$($csdetail.comment)
##CSLOOP##
PowerShell Script
$content = [IO.File]::ReadAllText("$(System.DefaultWorkingDirectory)\releasenotes.md")
$data = #{content=$content;} | ConvertTo-Json;
$params = #{uri = '$(WikiPath)';
Method = 'PUT';
Headers = #{Authorization = "Bearer $(System.AccessToken)" };
ContentType = "application/json";
Body = $data;
}
Invoke-WebRequest #params
Please guide me what I am doing wrong
After testing, we find that the PowerShell script in your mentioned blog uses this Rest API: Pages - Create Or Update, thus the wikipath is the requested url like below format:
https://dev.azure.com/{organization}/{project}/_apis/wiki/wikis/{wikiIdentifier}/pages?path={path}&api-version=6.0
For example, we create a project wiki named scrum-test.wiki, and want to create a new wiki page named Release notes, the url would like below
https://dev.azure.com/{organization}/{project}/_apis/wiki/wikis/scrum-test.wiki/pages?path=Release notes&api-version=6.0
If we now want to create a child wiki page named 0.1.0 under Release notes page, the url would be like below
https://dev.azure.com/{organization}/{project}/_apis/wiki/wikis/scrum-test.wiki/pages?path=Release notes/0.1.0&api-version=6.0
In addition, using AccessToken we always get error which says that "The wiki page operation failed with message : User does not have write permissions for this wiki." even we grant full wiki permissions for identity: {project name} Build Service ({organization name}), so we use PAT authentication with full access and it works fine with below PowerShell script.
$content = [IO.File]::ReadAllText("$(System.DefaultWorkingDirectory)\releasenotes.md")
$data = #{content=$content;} | ConvertTo-Json;
$connectionToken="PAT here"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$params = #{uri = '$(WikiPath)';
Method = 'PUT';
Headers = #{Authorization = "Basic $base64AuthInfo" };
ContentType = "application/json";
Body = $data;
}
Invoke-WebRequest #params
Check access to System.AccessToken on the job level: https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=classic
Additionally, check permissions on your wiki

Test a Symfony REST API using Behat / Mink : prb with POST request

My challenge here is to find the best way to test a Symfony (3.4) API application using Behat/Mink for functionnal test, in my CICD platform.
Because my testing processes must be called in a shell script, all the tests must be very linear. I have no way to start a standalone webserver like Apache or the PHP/Symfony webserver. Also, Docker is not an option.
For the moment, I can successfully test the GET verbs of the API using the Mink syntax :
-- file test.feature
#function1
Scenario Outline: Test my api
When I go to "/api/v1/hello"
Then the response is JSON
The "I go to" instruction is implemented by Mink (http://docs.behat.org/en/v2.5/cookbook/behat_and_mink.html) and it emulates a GET request only. When this instruction is called by BeHat, the app Symfony kernel is "spawned" and the "api/v1/hello" method is called internally : there is no network trafic, no TCP connection, there is no need for a dedicated webserver (apache, or the symfony standalone server). It looks like Behat is emulating a webserver and start by itself the Symfony app it its own user space.
Now I want to test the POST verbs of my API, with a json payload, but unfortunally Mink do not have other verbs than GET.
I have read some articles over the web (keyword : behat test post api) but all I have seen is based on a Guzzl/Curl client. So a real client-to-server connection is made to http://localhost and a real webserver have to respond to the request.
I want the Symfony API to be called internally without using an other webserver.
Is there a way to do that ? How to test a Symfony REST API and specially the POST verb without needing a standalone server to reply ?
Thank you.
Here is how I do a functional test of a POST API, with BeHat, without a local running webserver :
test.feature :
#function1
Scenario Outline: Test my api
Given I have the payload
"""
{ "data":"object"}
"""
When I request "POST /api/v1/post"
Then the response is JSON
The featureContext file implement two functions :
"I Have The Payload" : See here https://github.com/philsturgeon/build-apis-you-wont-hate/blob/master/chapter8/app/tests/behat/features/bootstrap/FeatureContext.php
"I request" : based on code provided by philsturgeon just above, I modify it to have something like that :
/**
* #When /^I request "(GET|PUT|POST|DELETE|PATCH) ([^"]*)"$/
*/
public function iRequest($httpMethod, $resource)
{
$this->lastResponse = $this->lastRequest = null;
$this->iAmOnHomepage();
$method = strtoupper($httpMethod);
$components = parse_url($this->getSession()->getCurrentUrl());
$baseUrl = $components['scheme'].'://'.$components['host'];
$this->requestUrl = $baseUrl.$resource;
$formParams = json_decode($this->requestPayload, true);
$formParamsList = [];
foreach($formParams as $param => $value) {
$formParamsList[$param] = json_encode($value);
}
// Construct request
$headers = [
'Accept'=>'application/json',
'Content-Type'=>'application/x-www-form-urlencoded'
];
try {
// Magic is here : allow to simulate any HTTP verb
$client = $this->getSession()->getDriver()->getClient();
$client->request(
$method,
$this->requestUrl,
$formParamsList,
[],
$headers,
null);
} catch (BadResponseException $e) {
$response = $e->getResponse();
// Sometimes the request will fail, at which point we have
// no response at all. Let Guzzle give an error here, it's
// pretty self-explanatory.
if (null === $response) {
throw $e;
}
$this->lastResponse = $e->getResponse();
throw new \Exception('Bad response.');
}
}
If you use Mink then it is quite easy
class FeatureContext extends RawMinkContext
{
/**
* #When make POST request to some Uri
*/
public function makePostRequestToSomeUri(): void
{
$uri = '/some-end-point';
/** #var \Symfony\Component\BrowserKit\Client $client */
$client = $this->getSession()->getDriver()->getClient();
$postParams = [];
$files = [];
$serverParams = [];
$rawContent = '';
$client->request(
\Symfony\Component\HttpFoundation\Request::METHOD_POST,
$uri,
$postParams,
$files,
$serverParams,
$rawContent
);
/** #var \Symfony\Component\HttpFoundation\Response $response */
$response = $client->getResponse();
//...
}
}

Using Soap in magento

I'm trying to follow the information about how to use soap in magento, but always get same message in error.log
If any one experience something similar, that could give me some tip, it will be welcome.
"PHP Fatal error: SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://www.site.com/index.php/api/?wsdl' : failed to load external entity "http://www.site.com/index.php/api/?wsdl"\n in /var/www/test.php on line 1"
$client = new SoapClient('http://www.site.com/api/?wsdl');
$session = $client->login('apiUser', 'apiKey');
$result = $client->call($session, 'somestuff.method');
$result = $client->call($session, 'somestuff.method', 'arg1');
$result = $client->call($session, 'somestuff.method', array('arg1', 'arg2', 'arg3'));
$result = $client->multiCall($session, array(
array('somestuff.method'),
array('somestuff.method', 'arg1'),
array('somestuff.method', array('arg1', 'arg2'))
));
// If you don't need the session anymore
$client->endSession($session);
where you have www.site.com in your SOAP code, replace it with localhost or whatever the correct URL is for your server. You'll also need to replace somestuff.method with real objects and methods as per the Magento documentation