SQL API call through sp_OAMethod causing error - sql

I'm looking to add an item to our systems through an API call to the supplier's site on given conditions. We have a replicated database and I want the process to be automated.
The supplier's, surprisingly, require you to login on one address then navigate to another to call the SEND but I don't think that the session is being persisted.
The code below is the SP I'm trying to create, which would allow me to use it for a variety of updates, not just this specific type.
The code I have so far is:
CREATE PROCEDURE [dbo].[CallAPI]
(
#Address nvarchar(MAX)
,#Message nvarchar(MAX)
)
AS
DECLARE #url_login nvarchar(MAX) = 'https://credentials'
DECLARE #Login nvarchar(MAX) = '{"username": "uSeR","password": "pAsS"}'
DECLARE #obj int
DECLARE #hResult int
DECLARE #statusText varchar(1000)
DECLARE #status varchar(1000) = 200
---------------------------------------------------------------------------------------------------
EXEC #hResult = sp_OACreate 'MSXML2.ServerXMLHttp', #obj OUT
---------------------------------------------------------------------------------------------------
--Log in
EXEC #hResult = sp_OAMethod #obj, 'Open', NULL, 'post', #url_login, false
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'Content-Type', 'application/json'
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'api-key', 'APIKey'
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'connection', 'keep - alive'
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'cookie', 'monster'
EXEC #hResult = sp_OAMethod #obj, 'send', NULL, #Login
EXEC sp_OAGetProperty #obj, 'StatusText', #statusText out
EXEC sp_OAGetProperty #obj, 'Status', #status out
IF #status = 200
BEGIN
print 'Successful log-in'
-------------------------------------------------------------------------------------------
--Navigate to required address
EXEC #hResult = sp_OAMethod #obj, 'Open', NULL, 'post', #Address, false
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'cookie', 'monster'
EXEC sp_OAGetProperty #obj, 'StatusText', #statusText out
EXEC sp_OAGetProperty #obj, 'Status', #status out
IF #status = 200
BEGIN
-----------------------------------------------------------------------------------
--Post message
print 'Successful navigate'
EXEC #hResult = sp_OAMethod #obj, 'send', NULL, #Message
EXEC sp_OAGetProperty #obj, 'StatusText', #statusText out
EXEC sp_OAGetProperty #obj, 'Status', #status out
IF #status = 200
print 'Successful posting'
END
END
IF #status <> 200
SELECT #status, #statusText
EXEC sp_OADestroy #obj

Related

Post Request API with SQL Server

I wanted to create a stored procedure in SQL Server to complete a POST request. The request would take two parameters.
Curl that I've used for Postman:
curl -X 'POST' \
'https://link' \
-H 'accept: application/json' \
-H 'Authorization: Bearer somepassword' \
-H 'Content-Type: application/json' \
-d '{
"userName": "username",
"password": "password"
}'
I've tried writing the code below, but it doesn't seem to work...
DECLARE #token INT;
DECLARE #ret INT;
DECLARE #url NVARCHAR(MAX);
DECLARE #apiKey NVARCHAR(32);
DECLARE #json AS TABLE(Json_Table NVARCHAR(MAX))
DECLARE #userName varchar(max)
DECLARE #password varchar(max)
DECLARE #body varchar(max)
SET #url = 'https://link'
SET #userName = 'username'
SET #password = 'password'
SET #body = '
{
"userName": "'+#username+'",
"password": "'+#password+'"
}
'
EXEC #ret = sp_OACreate 'MSXML2.XMLHTTP', #token OUT;
IF #ret <> 0
RAISERROR('Unable to open HTTP connection.', 10, 1);
-- This calls the necessary methods.
EXEC #ret = sp_OAMethod #token, 'open', NULL, 'GET', #url, 'false';
EXEC #ret = sp_OAMethod #token, 'send', null, #body
-- Grab the responseText property, and insert the JSON string into a table temporarily. This is very important, if you don't do this step you'll run into problems.
INSERT INTO #json (Json_Table)
EXEC sp_OAGetProperty #token, 'responseText'
-- This is all I have to add to insert into a non-existing table.
SELECT *
FROM OPENJSON((SELECT * FROM #json))
I recommend against using the legacy, hard-to-use OA procedures. Instead, this is a task for a .NET library via SQLCLR. For years I have used this library to handle API calls from the database.

how to use SqlAzureDacpacDeployment#1 task result in the next task

i need to query database in an azure pipeline to find out when was the last login to an environment and if it is more than 2 weeks destroy the environment. to do that i used the below task. but i dont know how can i store the variable to use in the next task. can someone please help me?
- task: SqlAzureDacpacDeployment#1
inputs:
azureSubscription: ' A Service Connection'
AuthenticationType: 'servicePrincipal'
ServerName: 'myserver.database.windows.net'
DatabaseName: 'mydb'
deployType: 'InlineSqlTask'
SqlInline: |
DECLARE #LastLoginDate AS NVARCHAR(50)
SELECT #LastLoginDate = [LastLoginDate]
FROM [dbo].[AspNetUsers]
WHERE UserName <> 'system'
PRINT #LAstLoginDate
IpDetectionMethod: 'AutoDetect'
SQLInlineTask meant for execution of SQL Script on database.
Setting Variables in Pipeline Tasks available with either Bash or PowerShell.
PowerShell Script Task
$query = "DECLARE #LastLoginDate AS NVARCHAR(50)
SELECT #LastLoginDate = [LastLoginDate]
FROM [dbo].[AspNetUsers]
WHERE UserName <> 'system'
PRINT #LAstLoginDate"
# If ARM Connection used with service connection, ignore getting access token
$clientid = "<client id>" # Store in Variable Groups
$tenantid = "<tenant id>" # Store in Variable Groups
$secret = "<client secret>" # Store in Variable Groups
$request = Invoke-RestMethod -Method POST -Uri "https://login.microsoftonline.com/$tenantid/oauth2/token"
-Body #{ resource="https://database.windows.net/"; grant_type="client_credentials"; client_id=$clientid; client_secret=$secret }
-ContentType "application/x-www-form-urlencoded"
$access_token = $request.access_token
# If ARM connection used with service connection, ignore AccessToken Parameter
$sqlOutput = Invoke-Sqlcmd -ServerInstance $.database.windows.net -Database db$ -AccessToken $access_token -query $query
Write-Host "##vso[task.setvariable variable=<variable name>;]$sqlOutput"
Bash
echo "##vso[task.setvariable variable=<variable name>;isOutput=true]<variable value>"
Within same job and different tasks, access it using $(<variable name>)
In Different job, access it using $[ dependencies.<firstjob name>.outputs['mystep.<variable name>'] ]
References:
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-variables-scripts?view=azure-devops&tabs=bash
https://medium.com/microsoftazure/how-to-pass-variables-in-azure-pipelines-yaml-tasks-5c81c5d31763
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
$LoginDate=(Sqlcmd myserver -U $(Username) -P $(Password) -d mydatabase -q "SET NOCOUNT ON; SELECT LastLoginDate=min(LastLoginDate) FROM mytable WHERE UserName<>'system';")
$Last=$LoginDate[2].trimstart()
Write-host $Last
Write-host "##vso[task.setvariable variable=LastLoginDate]$Last"

Oracle Apex exception: Unauthorized URL

I have an Oracle Apex application and I'm trying to make a REST request but I'm receiving the error Unauthorized URL.
Here is my code :
declare
l_clob clob;
begin
l_clob := APEX_WEB_SERVICE.make_rest_request(
p_url => 'http://oracle-base.com/webservices/add-numbers.php',
p_http_method => 'GET',
p_parm_name => APEX_UTIL.string_to_table('p_int_1:p_int_2'),
p_parm_value => APEX_UTIL.string_to_table(1 || ':' || 2)
) ;
return l_clob;
end;
The Error :
Unauthorized URL: http://oracle-base.com/webservices/add-numbers.php
Contact your application administrator.
Does anyone know how the reason of that please ?
Thanks.
You need a network ACL
If you are using Oracle Database 11g or higher, you will need an ACL to allow access to external network services.
Here is an 11g example of creating an ACL to allow the MY_USER user to access "oracle-base.com":
CONN / AS SYSDBA
BEGIN
DBMS_NETWORK_ACL_ADMIN.create_acl (
acl => 'oracle_base_acl.xml',
description => 'An ACL for the oracle-base.com website',
principal => 'MY_USER',
is_grant => TRUE,
privilege => 'connect',
start_date => SYSTIMESTAMP,
end_date => NULL);
DBMS_NETWORK_ACL_ADMIN.assign_acl (
acl => 'oracle_base_acl.xml',
host => 'oracle-base.com',
lower_port => 80,
upper_port => 80);
COMMIT;
END;
/
Instead, if you are using 12c:
CONN / AS SYSDBA
BEGIN
DBMS_NETWORK_ACL_ADMIN.append_host_ace (
host => 'oracle-base.com',
lower_port => 80,
upper_port => 80,
ace => xs$ace_type(privilege_list => xs$name_list('http'),
principal_name => 'MY_USER',
principal_type => xs_acl.ptype_db));
END;
/
Regards

Send mail in rails 3.2 using mandrill on Heroku

I have Mandrill set up to send SMTP email on Heroku. My app is a rails app. When a user signs up, it sends the email as expected. However, I have also set up an "invitation" action that lets users invite other users by email. This is not getting sent, though the logs suggest it is and no error is thrown. I have:
config.action_mailer.raise_delivery_errors = true
Here are the relevant logs:
2014-07-17T07:23:06.739778+00:00 app[web.1]: Started POST "/courses/collaborate" for 88.112.253.45 at 2014-07-17 07:23:06 +0000
2014-07-17T07:23:06.885997+00:00 app[web.1]:
2014-07-17T07:23:06.886001+00:00 app[web.1]: Sent mail to *********#gmail.com (87ms)
2014-07-17T07:23:06.886794+00:00 app[web.1]: Redirected to http://**********.herokuapp.com/courses/*
2014-07-17T07:23:06.978772+00:00 app[web.1]: Started GET "/courses/*" for 88.112.253.45 at 2014-07-17 07:23:06 +0000
2014-07-17T07:23:06.742954+00:00 app[web.1]: Processing by CoursesController#collaborate as HTML
2014-07-17T07:23:06.742984+00:00 app[web.1]: Parameters: {"utf8"=>"✓", "authenticity_token"=>"*********", "user"=>"******", "email"=>"**********#gmail.com", "title"=>"************* Vocab", "course"=>"*", "key"=>"", "commit"=>"Send Invitation"}
2014-07-17T07:23:06.886962+00:00 app[web.1]: Completed 302 Found in 96ms (ActiveRecord: 0.0ms)
2014-07-17T07:23:06.981777+00:00 app[web.1]: Processing by CoursesController#show as HTML
2014-07-17T07:23:06.797782+00:00 app[web.1]: Rendered user_mailer/collaborate.text.erb (0.1ms)
It seems that the mail is getting sent before the user_mailer is rendered but I don't know why. I've done it like this:
1) A form sends the params you see above to the collaborate action in the controller.
2) This action looks like this:
def collaborate
#user = params[:user]
#title = params[:title]
#course = params[:course]
#email = params[:email]
#key = params[:key]
UserMailer.collaborate(#user, #title, #course, #email, #key).deliver
redirect_to course_path(#course), notice: 'Invitation sent!'
end
3) The UserMailer.collaborate looks like this:
def collaborate(user, title, course, email, key)
#user = user
#title = title
#course = course
#email = email
#key = key
mail from: #user, to: #email, subject: "Please join me creating a course!"
end
4) collaborate.text.erb is just a message that uses the instance variables I set up.
The solution is that the form was automatically generating a :put and not a :get request. For some reason this wasn't a problem on the local server but pushed to production it was preventing the mail getting sent out. The key is to override the default form_tag :put request with a :get request.

LiquiBase: exec DBMS_UTILITY.compile_schema(schema => 'ECA', compile_all => false);

I'm using liquibase to execute oracle scripts. This oracle script, need to execute this function:
exec DBMS_UTILITY.compile_schema(schema => 'ECA', compile_all => false);
I saw that some people call this function using call statment instate of exec, and it works for me but with one parameter:
call DBMS_UTILITY.compile_schema(schema => 'ECA');
But if I add the second parameter:
call DBMS_UTILITY.compile_schema(schema => 'ECA', compile_all => false);
I get the following error:
call DBMS_UTILITY.compile_schema(schema => 'ECA', compile_all => false): ORA-06576: not a valid function or procedure name
Also I tried with exec:
exec DBMS_UTILITY.compile_schema(schema => 'ECA', compile_all => false);
And I get this error:
Reason: liquibase.exception.DatabaseException: Error executing SQL exec DBMS_UTILITY.compile_schema(schema => 'ECA', compile_all => false): ORA-00900: invalid SQL statement
Althought if i execute in a sql console works fine.
Any idea about how to avoid this problem and be able to execute this function ?
Thanks in advance
Try this:
<sql splitStatements="false">
begin
DBMS_UTILITY.compile_schema(schema => 'ECA', compile_all => false);
end;
</sql>