GoogleCalendarAPI to insert events giving Rails--[API Error]: --{:error=>["Excon::Error::Forbidden", "Expected([200]) <=> Actual(403 Forbidden)\n"]} - ruby-on-rails-5

I have been using Google calendar API to insert events in user's calendar. I have written a code which takes csv(with approx 1000 rows) as an input with minimum required parameters to create events such as event_title, event_description, event_date (since its a full day event) and recipient email id..The code runs in background using sidekiq.
Out of 1000 rows , only some events are inserted in user's calendar. Most of them are giving Rails -- [API Error]: -- {:error=>["Excon::Error::Forbidden", "Expected([200]) <=> Actual(403 Forbidden)\n"]} error.
I have been using excon client (gem) to hit the urls to refresh token and inserting an event.
Token is refreshed
Loop (
Hitting API to insert events
)
rescue error
end
I couldnt figure out what's going wrong ?..Any help is appreciated. While registering my app in Google developer console , I have given the full scope of calendar api auth/calendar.
I tried setting Excon.defaults[:ssl_verify_peer] = false.
Implementing such api first time.

The 403 would indicate that the permissions are not valid in some way. My guesses would be that either the token is expiring, you are hitting some kind of rate limit, or something is different about the parameters for the failing request such that the particular event is not allowed.
Do you think any of those is more likely than the others? If it is the token expiring, you could try to catch the 403 error, refresh the token, and retry. If it's one of the others it might take a bit more digging to see why the ones that are failing are different from the ones that succeed.

Related

Unable to POST NZ employee openingBalances to Xero?

I am attempting to create a single opening balances record against an existing employee but keep getting a 400 Bad Request response with this detail...
At least one NZ opening balance item is required in the request
I am following the instructions as per this documentation...
https://developer.xero.com/documentation/api/payrollnz/employeeopeningbalances#post-opening-balances
URL : {DestinationID} is properly replaced with the employee GUIDhttps://api.xero.com/payroll.xro/2.0/employees/{DestinationID}/openingBalances
JSON Body[{"periodEndDate":"2011-01-30T00:00:00","daysPaid":5.00,"unpaidWeeks":0.00,"grossEarnings":1442.31}]
The Xero forums and support is pretty unreliable so I'm posting here in the hopes for a better response.
After some trial and error using the API Explorer that Xero provides I was able to get it working using their example....
I eventually learned that daysPaid and unpaidWeeks must both be integer whole numbers or else it fails.... The error message provided is misleading but this resolves the problem.

How to internationalization errors returned by API?

I'm wondering how to manage error in an API with multiple language.
I know there are multiple way to do that. I found 3.
Send a statusCode to front (with optionnal some data to manage dynamics values like : "you can manage only X users")
Send errors for all language ex :
{
en:"error is....",
fr:"l'erreur est...",
...
}
send just one error in the correct language
{
en:"error is...."
}
All of this have pro and cons...
the first :
+ API just manage statusCode and front(s) can manage error how it want
- API must manage dynamics error and send extra data
- Front must reformat the error (error + extra data)
others ?
the second :
+ error message can just be displayed on front without update it (but need to get the good one for the language client)
- back must manage error message for all language (if there are 10-50 or more language it's a little bit annoying)
- back end must take care of displaying message interstanding for a user (I think it's not is role)
others ?
the third :
+ error message can just be displayed on front without update it
- back end must take care of displaying message interstanding for a user (I think it's not is role)
- front must send the user's language at the session's begining and update this information if user change it
others ?
I think the third is the better but I don't know.
someone could say me what is the best solution and why ?
Thanks in advance :)

Maintain Session when logged in across all Pages, End session after set time (OWA_COOKIE)

I need to maintain a session for session credentials throughout the web pages I have made. I have next to no experience using OWA_COOKIE and am unsure how to go about it.
I just need it to maintain the session, Finish session if
inactive for 15 mins OR 2. they log out
I have had a whirl at it and this what I have but it doesn't work and am at a lose, can someone help or point me in the right direction?
FUNCTION maintain_session_cookie
AS
TYPE vc_arr IS TABLE OF varchar2(4000)
INDEX BY BINARY_INTEGER.
TYPE cookie IS RECORD (
NAME varchar2(4000),
vals vc_arr,
num_vals integer);
BEGIN
owa_util.mime_header('', FALSE);
owa_cookie.send(
NAME=>'Session_Cookie',
VALUE=>LOWER(),
expires => SYSDATE + 365);
-- Set the cookie and redirect to another page
owa_util.redirect_url();
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
I have been just fiddling to see how it works and provide the functionality that I need.
First of all, it is a quite awkward way to set session lifetime by cookies. You can setup the parameter timeout-secs in either web.xml or weblogic.xml (see Oracle docs).
Your both requirements should be processed by the HTTP server, that's my point of view.
Now, let's say you still want to use cookies (maybe you do not use WebLogic or another reason, whatever). You will face following problems:
You will need to specify these cookies on every page you will display to the user, and not only pages, every ajax call should also have the cookies. So, everything which shows user activity should have this cookie.
Expires parameter should, obviously, be sysdate + interval '15' minute, then your cookie will work exactly for 15 minutes and if you do like it is written in point 1 the cookie will be lost only if there is no activity.
You will have to close the session by yourself if the cookie is not more presented in HTTP request, this is an additional problem.
The thing I want to say is: do it with server configuration and not with cookies. This will save your time and nerves.

I am trying to use Yodlee/executeUserSearchRequest as a RESTful request and need an answer on how to call

I am working with the Yodlee services in c# and using the RESTful api. So far I have successfully connected and logged in with my CobrandSession and UserSessionToken in the development environment. I used the sample apps provided in c# and with some advice from shreyans i got an app working. What I got working was
1) Get YodleeAuthentication
2) Get UserAuthentication
3) Get ItemSummaries
I am now trying to get the full transaction details for each of the Items (i.e. collections of accounts that are an Item)
reading the Docs here https://developer.yodlee.com/Indy_FinApp/Aggregation_Services_Guide/REST_API_Reference/executeUserSearchRequest it states that I need to call executeUserSearchRequest and then paginate through the results using the getUserTransactions. So I am stuck at this point. I dont really want a search which has parameters I just want ALL transactions for this account that I can see.
However, I am using the variables as defined in that page :-
var request = new RestRequest("/jsonsdk/TransactionSearchService/executeUserSearchRequest", Method.POST);
request.AddParameter("cobSessionToken", param.CobSessionToken);
request.AddParameter("userSessionToken", param.UserSessionToken);
request.AddParameter("transactionSearchRequest.containerType", param.ContainerType);
request.AddParameter("transactionSearchRequest.higherFetchLimit", param.HigherFetchLimit);
request.AddParameter("transactionSearchRequest.lowerFetchLimit", param.LowerFetchLimit);
request.AddParameter("transactionSearchRequest.resultRange.endNumber", param.EndNumber);
request.AddParameter("transactionSearchRequest.resultRange.startNumber", param.StartNumber);
request.AddParameter("transactionSearchRequest.searchFilter.currencyCode", param.CurrencyCode);
request.AddParameter("transactionSearchRequest.searchFilter.postDateRange.fromDate", param.FromDate);
request.AddParameter("transactionSearchRequest.searchFilter.postDateRange.toDate", param.ToDate);
request.AddParameter("transactionSearchRequest.searchFilter.transactionSplitType.splitType", param.SplitType);
request.AddParameter("transactionSearchRequest.ignoreUserInput", param.IgnoreUserInput);
request.AddParameter("transactionSearchRequest.searchFilter.itemAcctId", param.ItemAcctId);
var response = RestClientUtil.GetBase().Execute(request);
var content = response.Content;
return new YodleeServiceResultDto(content);
As per the response from shreyans in this posting Getting Error "Any one of [**] of transactionSearchFilter cannot be NULL OR Invalid Values I am not putting in the ClientId and the ClientName
The documentation doesn't specify the format of the dates but the example seems to tell me that its american date format. And specifies a parameter saying IgnoreUserinput, but doesnt have a parameter for user input so this is confusing
When I make a call using this format I get an error response
var getSearchResult = yodleeExecuteUserSearchRequest.Go(yodleeExecuteUserSearchRequestDto);
getSearchResult.Result="
{"errorOccured":"true","exceptionType":"Exception Occured","refrenceCode":"_60ecb1d7-a4c4-4914-b3cd-49182518ca5d"}"
But I get no error message in this and I have no idea what I have done wrong or where to look up this error, can somebody who has used Yodlee REST Api point me in the right direction as I need to get this researched quickly....
thanks your your help, advice, corrections and pointers....
Here is the list of parameters which you can try
1) For a specific ItemAccountId all transactions
transactionSearchRequest.containerType=all
transactionSearchRequest.higherFetchLimit=500
transactionSearchRequest.lowerFetchLimit=1
transactionSearchRequest.resultRange.startNumber=1
transactionSearchRequest.resultRange.endNumber=500
transactionSearchRequest.searchClients.clientId=1
transactionSearchRequest.searchClients.clientName=DataSearchService
transactionSearchRequest.searchFilter.currencyCode=USD
transactionSearchRequest.searchClients=DEFAULT_SERVICE_CLIENT
transactionSearchRequest.ignoreUserInput=true
transactionSearchRequest.ignoreManualTransactions=false
transactionSearchRequest.searchFilter.transactionSplitType=ALL_TRANSACTION
transactionSearchRequest.searchFilter.itemAccountId.identifier=10000353
2) For a Specific account (itemAccountId) with start and end dates
transactionSearchRequest.containerType=all
transactionSearchRequest.higherFetchLimit=500
transactionSearchRequest.lowerFetchLimit=1
transactionSearchRequest.resultRange.startNumber=1
transactionSearchRequest.resultRange.endNumber=500
transactionSearchRequest.searchClients.clientId=1
transactionSearchRequest.searchClients.clientName=DataSearchService
transactionSearchRequest.searchFilter.currencyCode=USD
transactionSearchRequest.searchClients=DEFAULT_SERVICE_CLIENT
transactionSearchRequest.ignoreUserInput=true
transactionSearchRequest.ignoreManualTransactions=false
transactionSearchRequest.searchFilter.transactionSplitType=ALL_TRANSACTION
transactionSearchRequest.searchFilter.itemAccountId.identifier=10000353
transactionSearchRequest.searchFilter.postDateRange.fromDate=08-01-2013
transactionSearchRequest.searchFilter.postDateRange.toDate=10-31-2013

ActiveRecord (Rails 3.0.1): API Can't Handle Too Many Requests?

I have an API that services a web-based plugin for processing email. The API is responsible for two things:
Creating SessionIDs so the plugin can setup a dynamic link; and
Once an email is sent, for receiving that SessionID, the email recipients and subject line, to store the information into a new session.
Imagine the scenario where the plugin sends a request to the API:
PUT http://server.com/api/email/update/<SessionID> -d "to=<address1,address2>&subject=<subject>"
In testing this works fine: the data is saved normally. However, the plugin can't help but send that request several times a second, bombarding my server with identical requests. The result is that I get my EmailSession object saving multiple copies of the recipients.
In terms of my database schema, I have an EmailSession model, which has_many EmailRecipients.
Here's the relevant part of the update method in my API's controller:
#email_session = EmailSession.find_or_create_by_session_id(:session_id => params[:id], :user_id => #user.id)
if opts[:params][:cm_to].blank? == false
self.email_recipients.destroy_all
unless opts[:params][:cm_to].blank?
opts[:params][:cm_to].strip.split(",").each do |t|
self.email_recipients << EmailRecipient.create(:recipient_email => t)
end
end
end
Admittedly, the "find_or_create" dynamic method is new to me, and I wonder if there's something about that screwing up the works.
The symptoms I'm seeing include:
ActiveRecord errors complaining about attempts to save a non-unique key into the database (I have an index on the SessionId)
Duplicate recipients ending up in the EmailRecipients collection
In the case of multiple users employing the plugin, I get recipients from other emails ending up in the wrong email session collections.
I've attempted to employ delayed_job to attempt to serialize these requests somehow. I haven't had much luck with it thanks to various bugs in the current release. But I'm wondering if there's a more fundamental problem with my approach to this solution? Any help would be appreciated.
I'm still not sure I understand what you're doing, but here's my advice.
First off I don't think you are using find_or_create_by properly. This method has slightly confusing semantics (which is why 3.2 introduces some clearer alternatives) but as it stands it isn't using the user_id to find the record (although it is setting user_id if a record is created). I don't think this is what you wanted. Instead use find_or_create_by_session_id_and_user_id
This can still raise a duplicate key error since in between find_or_create checking and it creating the record there is time for someone else to create the record. If you weren't doing anything other than creating email session rows the  rescuing this duplicate key error and then retrying should take of that: on the retry you'll find the row that blocked your insert.
However when you then go on to add recipients you still have a potential issue because 2 things could be trying to remove recipients and add them to the same email session at the same time. This might be a good usecase for pessimistic locking. 
begin
EmailSession.transaction do
session = EmailSession.lock(true).find_or_create_by_bla_bla(...)
# use the session object here, add recipients etc.
end
rescue ActiveRecord::StatementInvalid => e
end
What is happening here is that when the email session is retrieved from the db, the row is locked (even if it doesn't exist yet - effectively you can lock the gap where the record would go). This means that anyone else wanting to add recipients or do any other manipulation has to wait for the lock to be released. Locks last as long as the transaction in which they occur lasts  so all your work should happen in here (even if in the second part you are not actually changing the email session object any more).
You may end up with deadlocks - I don't know what else is going on in your app but you should be prepared for them if you are using transactions. That's what the rescue block is for: if the error message looks like a deadlock then you should probably retry some limited number of times.
Locks are (at least on MySQL) row level locks: as long as you have an index on session_id,user_id then just because one of your instance has one email session object locked doesn't stop another instance from using another one.