Edit VSTS Wiki page via VSTS API - api

I am trying to edit a VSTS wiki page via powershell and VSTS API and I am using this documentation as a reference.
When I try to edit an existing page, I get the following error:
Invoke-RestMethod : {"$id":"1","innerException":null,"message":"The page '<PAGE That I CREATED ALREADY>' specified in the add operation already exists in the wiki. Please specify a new page path.","typeName":"Microsoft.TeamFoundation.Wiki.Server.WikiPageAlreadyExistsException, Microsoft.TeamFoundation.Wiki.Server","typeKey":"WikiPageAlreadyExistsException","errorCode":0,"eventId":3000}
At line:32 char:11
+ $result = Invoke-RestMethod -Uri $uri -Method Put -ContentType "appli ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I can create a new page with the content there, but I am stumped as how would I update an existing wiki page. Please help.
Snippet of My Code:
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
# updates wiki page
$uri = "https://$($vstsAccount).visualstudio.com/$($projectName)/_apis/wiki/wikis/$($wikiIdentifier)/pages?path=/$($existingPage)&api-version=4.1"
$body = #"
{
"content": "Hello"
}
"#
$result = Invoke-RestMethod -Uri $uri -Method Put -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $body -Verbose

As the post Update wiki page REST API can not working in developer community, please make sure If-Match is contained in request header.

May I suggest a different approach?
The storage for a VSTS Wiki is a Git repo (see here). So you can clone the repo, change the files and push your changes back.
You can even use a VSTS build for this: the clone is implicit and there are many extensions to implement the push.

Make sure that the page version is included in the request header. Refer to this link for details: Pages - Create Or Update.
Version of the page on which the change is to be made. Mandatory for
Edit scenario. To be populated in the If-Match header of the request.

Related

Mailtrap API - Cannot send emails - "Unauthorized" API error

I am using Mailtrap's SMTP to send my development/test e-mails to a fake inbox.
Their SMTP server feature works well, but I'm now trying to implement their API v2 instead.
Every time I hit the https://send.api.mailtrap.io/api/send endpoint, I keep getting the following error:
{"errors":["Unauthorized"]}
More info
I have a Paid account and generated an API Token which has full Admin rights
Only the send.api.mailtrap.io/api/send endpoint fails, other endpoints such as mailtrap.io/accounts are working
I am getting the same error whether I use their API Doc Request testing tool or my code
I am getting the same error message with their API v1
cURL request used (from their API docs)
curl -X POST "https://send.api.mailtrap.io/api/send" \
-H "Accept: application/json" \
-H "Api-Token: xxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"to":[{"email":"john_doe#example.com","name":"John Doe"}],"from":{"email":"sales#example.com","name":"Example Sales Team"},"subject":"Your Example Order Confirmation","html":"<p>Congratulations on your order no. <strong>1234</strong>.</p>"}'
Similar cURL request via PHP (same error message)
<?php
$post = [];
$post['to'] = 'test#test.com';
$post['from'] = ['name' => 'Test', 'email' => 'test#test.com'];
$post['subject'] = 'Test';
$post['html'] = '<h2>This is a test</h2><p>It works!</p>';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://send.api.mailtrap.io/api/send');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Api-Token: xxxxxxxxxxxxxxxxxxxxxxxxx']);
$result = curl_exec($ch);
print_r($result);
echo "\n";
I finally found the answer, here are my conclusions:
As of Today (Sep 2022), Mailtrap's Sending API cannot be used to send e-mails to your Mailtrap Sandbox (i.e. Fake Inbox). It can only be used to send real/production e-mails, to real users.
If your Mailtrap account is older than a year, you will most likely be missing the "Send API" section in your account and only see the "API" section. The only solution to address that was to create a new account.
If you still plan to use Mailtrap's Sending API (to send production e-mails), you will need to reach out to Support for some pre-configuration (This is not mentioned in the documentation) otherwise you will receive "Forbidden" from the API, without any additional details.
Does it mean we needs to write separate logic for dev/staging (using SMTP) and for prod (using API) in our apps? Sounds really strange.
I've looked into this and I have found the solution to your problem.
When looking at the send documentation, it states that you must also include an inbox id in your url and also use the sandbox url.
So, if you change your url from https://send.api.mailtrap.io/api/send to https://sandbox.api.mailtrap.io/api/send/1234567 then it should work - At least it did for me!
You can get the inbox id by going to the specific inbox in the webinterface and copy it from the url.

Cannot retrieve access tocken

I am experimenting with this https://forge-digital-twin.autodesk.io/# using the gitlab code. I can display it locally (without the engine or dataflow) but I can not gain an access token.
I am using the VSCode extension and I get the code 401 (Unauthorized) error if I try to create buckets etc (hence why I am trying to get an access code). However, when I request one using this:
curl -i -X POST 'https://developer.api.autodesk.com/authentication/v1/authenticate' -H 'Content-Type: application/x-www-form-urlencoded' -d 'client_id=-----' -d 'client_secret= ----' -d 'grant_type=client_credentials' -d 'scope=data:write data:read bucket:create bucket:delete'
I get this error:
Invoke-WebRequest : Cannot bind parameter 'Headers'. Cannot convert the "Content-Type:
application/x-www-form-urlencoded" value of type "System.String" to type
"System.Collections.IDictionary".
At line:1 char:90
... ticate' -H 'Content-Type: application/x-www-form-urlencoded' -d 'cl ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidArgument: (:) [Invoke-WebRequest], ParameterBindingException
FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.InvokeWebRe
questCommand
I have no idea where I am going wrong and have tried everything I can think of.
Hope you can help, thanks :)
If you're seeing 401 issues when working with the Forge extension for Visual Studio Code, make sure that you have at least one "environment" configured with your Forge client ID and secret. When you activate the extension for the first time, it should ask you for the credentials automatically, but you can also add or edit the environments at any point by going to the Visual Studio Code preferences, and looking for "forge":
And then, in the Autodesk > Forge: Environments section, hit the Edit in settings.json link and edit the environments directly as JSON, creating a new object (with title, clientId, and clientSecret properties set) if needed:
Btw. VSCode provides intelli-sense support when editing the settings.json file, so you'll see exactly which properties are expected/available in each environment.
It defaults to Invoke-WebRequest.
Try to use Invoke-RestMethod like this:
$Body = #{
grant_type = "client_credentials"
client_id = ""
client_secret = ""
scope = "data:write data:read bucket:create bucket:delete"
}
$Headers = #{
'Content-Type' = 'application/x-www-form-urlencoded'
}
$response = Invoke-RestMethod -Method Post -Uri https://developer.api.autodesk.com/authentication/v1/authenticate' -Headers $Headers -Body $Body

How do I post data to an external endpoint from Apache Module?

I'm coding an Apache Module. In the same I'm able to read the request parameters and make some params by processing the request. Now I want to post this data to the external endpoint. How do I do that?
Say I have a data
char* data = "{clientid:2433211456}"; and I want to post it to a URL example.com/getPostedData in async mode, how do I do that?
NOTE : Currently I'm working with plan Apache libs and APXS tool. If I can have some modules on which I can Build the same, please do suggest.
I have solved this issue as follows :
I used curl to post the request.
Installed libcurl-devel
In the handler method :
char* postData="hello=hie";
CURL *curl;
curl = curl_easy_init();
ap_rprintf(r,"Intialized Curl!<br>");
if(curl) {
ap_rprintf(r,"Curl Request Posting Started!<br>");
curl_easy_setopt(curl, CURLOPT_URL,"http://google.com/search");
//curl_easy_setopt(curl, CURLOPT_POST,1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,postData);
ap_rprintf(r,"%d",curl_easy_perform(curl));
curl_easy_cleanup(curl);
}
Compiled it as : apxs -i -a -c mod_example.c -lcurl
Done!!
For more reference on libcurl : http://curl.haxx.se/libcurl
Find my sample module code on github here.

Using Powershell to create user in RabbitMQ via API

I'm trying to create a powershell script that setups user "George" after installing RabbitMQ on a new machine.
I can't figure out why this script doesn't work.
The last step gives me a 404 {"error":"Object Not Found","reason":"\"Not Found\"\n"}
$secpasswd = ConvertTo-SecureString 'guest' -AsPlainText -Force
$credGuest = New-Object System.Management.Automation.PSCredential ('guest', $secpasswd)
$secpasswd2 = ConvertTo-SecureString 'george' -AsPlainText -Force
$credAdmin2 = New-Object System.Management.Automation.PSCredential ('george', $secpasswd2)
$body = #{
'password' = 'george'
'tags' = 'administrator'
} | ConvertTo-Json
$vhosts1 = ''
$vhosts1 = Invoke-RestMethod 'http://localhost:15672/api/users/george' -credential $credGuest -Method Put -ContentType "application/json" -Body $body
write '1:' $vhosts1
$vhosts2 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/' -Method get -credential $credAdmin2
write '2:' $vhosts2
$body2 = #{
'username' = 'george'
'vhost' = '/'
'configure' = '.*'
'write' = '.*'
'read' = '.*'
} | ConvertTo-Json
write '3:' $body2
$vhosts3 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/george' -credential $credGuest -Method Put -ContentType "application/json" -Body $body2
write '4:' $vhosts3
I've also tried formatting the last step like this:
http://localhost:15672/api/permissions/george
Same 404 error.
I've tried about 20,000 different ways of sending the command in. From matching other examples perfectly to trying some abstract art and voodoo magic. While watching the managment tool for RabbitMQ I can see George is created. And he has an empty vhost. So the first 3 steps work perfectly.
Alright man, you know that I love you, because I'd never heard of RabbitMQ before tonight. In the last hour, I've installed it on my Windows machine, and now have used this awesome guide here to the API and kind of learned about how it works.
So, when I run your same process step by step , I see everything happen as you state:
George gets created:
Since your second step is listing the current permissions of the user running the API call, I next see output of the guest account, which has full perms. Then onto step 3, which builds the target permissions for George.
username : george
write : .*
read : .*
configure : .*
vhost : /
From here, Step 4. When I run this step manually after the previous step...it works! However, if I run this too quickly, if I run the whole script at once, I will get a 404 error. It seems that behind the scenes in RabbitMQ a slight pause is needed for the files to be updated with the new user. When I deleted the user and tried the whole script again too quickly, I got 404's for every step, pretty much.
However, if I add a little Start-Sleep 5 to pause 5 seconds...
The whole process completed. The key place to add a pause is after Step 1 and it seems to need about four or five seconds.
Making it pretty
Now of course, I couldn't stop there, so I decided to add a few more minor pauses to improve output readability and also ensure that each operation completes. I added some purty looking "OK" messages after the step completes, and then added a finishing confirmation of permissions by doing one last API call for the current user.
Here's the completed output
Completed Script
$secpasswd = ConvertTo-SecureString 'guest' -AsPlainText -Force
$credGuest = New-Object System.Management.Automation.PSCredential ('guest', $secpasswd)
$secpasswd2 = ConvertTo-SecureString 'stephen' -AsPlainText -Force
$credAdmin2 = New-Object System.Management.Automation.PSCredential ('stephen', $secpasswd2)
$body = #{
'password' = 'stephen'
'tags' = 'administrator'
} | ConvertTo-Json
Write-host "About to create new user $(($body | ConvertFrom-Json).Password)..." -NoNewline
$vhosts1 = Invoke-RestMethod 'http://localhost:15672/api/users/stephen' -credential $credGuest -Method Put -ContentType "application/json" -Body $body
start-sleep 5
Write-host "OK" -ForegroundColor Green
Start-Sleep -Milliseconds 400
Write-Host '1: Results:' $vhosts1
$body2 = #{
'username' = 'stephen'
'vhost' = '/'
'configure' = '.*'
'write' = '.*'
'read' = '.*'
} | ConvertTo-Json
Write-Output "Desired perms for new user $(($body | ConvertFrom-Json).Password)" $body2
Write-host "Setting perms for new user..." -NoNewline
$vhosts3 = Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/stephen' -credential $credGuest -Method Put -ContentType "application/json" -Body $body2
Start-sleep 5
Write-host "OK" -ForegroundColor Green
Start-Sleep -Milliseconds 400
write '4:' $vhosts3
'Retrieiving perms for new user to confirm...'
Invoke-RestMethod 'http://localhost:15672/api/permissions/%2f/stephen' -Method get -credential $credAdmin2
Now I just hope I'll get a chance to use RabbitMQ ever again...
finally stumpled upon a powershell library someone else wrote for interacting with the RabbitMQ api.
https://github.com/mariuszwojcik/RabbitMQTools/blob/master/en-US/about_UnEsapingDotsAndSlashes.help.txt
I found out that certain versions of powershell replace %2f with the / before sending it to rabbit. If you use this guys functions found here:
https://github.com/mariuszwojcik/RabbitMQTools
Everything runs beautifully. Really great library he put together.
I'm late to this question. I love Powershell too, but I used a .bat file to run the native RabbitMQ commands as shown below. I needed to add a user, a vhost, and hook those two up. I wanted a script so any new developer could run it.
cd /D c:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.14\sbin
echo cd completed
call rabbitmqctl add_user bts mypass
call rabbitmqctl set_user_tags bts administrator
call rabbitmqctl add_vhost base
call rabbitmqctl set_permissions -p base bts ".*" ".*" ".*"
Echo ----List Command to confirm results --------
call rabbitmqctl list_vhosts
call rabbitmqctl list_user_permissions bts
I suppose you could call these from Powershell too. I guess downside of this is that you have to be on the machine running RabbitMQ.

Call WCF Service from bat file

is it possible to call a Methode of a WCF Service in a bat file. We want to test if the WCF Service works correct after the Server was restartet.
There are no commands within the BAT file universe that will allow you to contact a WCF service directly, however you could use a BAT file to run an existing console program that can connect and interact with a WCF service. So the answer is both yes and no; not directly, but through a separate program yes.
If you need some simple, clickable way of accessing a WCF service, I'd go with a Powershell or VB script (assuming you're in a windows environment).
Maybe you will be able to use PowerShell? It would be easier then. Create script with content:
$url = 'http://yoursite.url/example.svc'
$action = "`"http://some.namespace/method`""
$SOAPRequest = [xml]#'heregoesxmlmessage'#
write-host "Sending SOAP Request To Server: $url"
$soapWebRequest = [System.Net.WebRequest]::Create($url)
$soapWebRequest.Headers.Add("SOAPAction", $action)
$soapWebRequest.ContentType = "text/xml;charset=`"utf-8`""
$soapWebRequest.Accept = "text/xml"
$soapWebRequest.Method = "POST"
write-host "Initiating Send."
$requestStream = $soapWebRequest.GetRequestStream()
$SOAPRequest.Save($requestStream)
$requestStream.Close()
write-host "Send Complete, Waiting For Response."
$resp = $soapWebRequest.GetResponse()
$responseStream = $resp.GetResponseStream()
$soapReader = [System.IO.StreamReader]($responseStream)
$ReturnXml = [Xml] $soapReader.ReadToEnd()
$responseStream.Close()
write-host "Response Received."
$ReturnXml.OuterXml | out-file ".\test.xml"
write-host $ReturnXml.OuterXml
As mentioned in the other answers Powershell is probably the best way to go using the New-WebServiceProxy cmdlet.
http://technet.microsoft.com/library/hh849841.aspx
Example from the link above:
PS C:\> $URI = "http://www.webservicex.net/uszip.asmx?WSDL"
PS C:\>$zip = New-WebServiceProxy -Uri $URI -Namespace WebServiceProxy -Class USZip
PS C:\> $zip.getinfobyzip(20500).table
CITY : Washington
STATE : DC
ZIP : 20500
AREA_CODE : 202
TIME_ZONE : E