Catching error with Usermanager.getUser() in Google Apps Script - google-api

I am working withing Google Spreadsheet creating a script file that has to deal with obtaining user information on my Google Apps Domain. I have admin rights and the Provisioning API is enabled. In my code, I am trying to catch the error when looking up a specific user on a Google Apps Domain (user not found) and instead display a message and continuing on with the rest of the program. The try-catch statement I have here works when there is no error on the user. However, when there is an error on retrieving the user, I get the error: "Unexpected exception upon serializing continuation". Here is my code:
function testOfDomainAccess() {
var i=0;
var anArray= ["johhn.smith", "susan.que]; //john smith misspelled
var user;
for (i=0; i < anArray.length; ++i)
{
Logger.log("\nThe current user being processed is " + anArray[i]);
try
{
user = UserManager.getUser (anArray [i]);
}
catch (error)
{
Browser.msgBox("Error: " + error.name + "\n Check your spreadsheet for misspellings of " + anArray[i] + " and We will continue to the next user.");
user = null;
}
if (user != null) {
//Perform tasks
}
else
Logger.log("User not found in domain. Moving on the next item in the array.");
}
If anyone can help with this problem I would greatly appreciate it. I am new to Google Apps Script and Provisioning API. Thanks!

It looks like the same bug reported at http://code.google.com/p/google-apps-script-issues/issues/detail?id=980.
The workaround is to replace the Browser.msgBox() call with Logger.log() and your script should run as expected.

Related

Deluge- how to prevent a user who is already signed in from signing in again

I have written a simple deluge script for a Sign In app.
Is there a way to prevent a user who is already signed in from signing in again?
Likewise, is there a way to prevent a user who is already signed out from signing out again?
What I have below populates the Staus with either Sign In or Sign Out but the user can manually override this is and sign In/Out twice
var = Sign_in_out[UserName == input.UserName] sort by Added_Time Desc;
if(var.Status == "Sign In")
{
Status.select("Sign Out");
}
else if(var.Status == "Sign Out")
{
Status.select("Sign In");
}
else
{
Status.select("Sign In");
}
In Zoho-Creator, the login state of a user can be checked with either zoho.loginuser or zoho.loginuserid. If either of these is null then the user is logged out. If they are not-null, then the user is logged in.
Deluge probably has the same behavior in other Zoho tools, but give it a try in-order to verify the behavior.
Example:
if (zoho.loginuserid == null)
{
info "Login-Status: Signed-Out:[" + zoho.loginuserid + "]";
}
else
{
info "Login-Status: Signed-In:[" + zoho.loginuserid + "]";
}
10-26-2022, Additional note after comments:
Try automatically refreshing the page. Here is a few example methods. These methods should work for Pages, Forms and Reports.
Example:
// Refresh a page using a full path url
openUrl("https://<zoho-url-path/#Page:<page-name>", "same window");
// Refresh a form with Zoho short path
openUrl("#Form:<login-form-name>", "same window");

How to properly handle Google SDK errors in Google App Script

I am writing a google web app which uses the Admin Directory a lot. However I was wondering how the error handling should be done since I do not get a proper error object back when a request to the api fails.
Example: I want to check if a custom schema exists and if not I want to do something else:
try{
var resp = AdminDirectory.Schemas.get("129898rgv", "someCustomSchema");
}catch(err){
// if schema does not exist do this
schemaNotExistFunction();
Logger.log(err);
}
Unfortunately I do not even get the http status code back from the err. Is there another way to handle errors in Google Apps Script?
Instead of
Logger.log(error)
use
Logger.log('%s, %s',error.message, error.stack);
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error for a complete list of Error instance properties
The above because Logger.log parses the parameter as string. When you pass an error object error.name is logged, by the other hand by using
Example
Running the following code in an standalone project using the new runtime (V8) will log a couple of messages.
function myFunction() {
try{
SpreadsheetApp.getUi();
} catch (error) {
Logger.log(error);
Logger.log('%s, %s', error.message, error.stack);
}
}
Another alternative is to use console.log instead of Logger.log
function myFunction() {
try{
SpreadsheetApp.getUi();
} catch (error) {
console.log(error);
console.log('%s, %s', error.message, error.stack);
}
}

Configure an Access point using SNMP

Currently I am developing an C# console application using .NET 4.5 to set some configuration values of the access point. This access point is in my local network. Further I am using SnmpSharpNet library to make SNMP requests. To make the SNMP requests I used SNMP version 2.
The problem is that I can't do SET request to the access point and it always responds with "no-access" (error code 6). But I can do GET request without a problem. I checked the MIB file as well and the variable which I am going to change also has read-write access.
This is the code I wrote.
private static LogFile log;
private static SnmpV2Packet response;
private static UdpTarget target;
static void Main(string[] args)
{
try
{
log = new LogFile(args[0]);
target = new UdpTarget((IPAddress)new IpAddress("<host address>"));
Pdu pdu = new Pdu();
pdu.Type = PduType.Set;
pdu.VbList.Add(new Oid("1.3.6.1.4.1.2356.11.2.88.2.0"), new Integer32(1111));
AgentParameters aparam = new AgentParameters(SnmpVersion.Ver2, new OctetString("public"));
response = (SnmpV2Packet)target.Request(pdu, aparam);
}
catch (Exception ex)
{
log.LogError("Request failed with the exception " + ex, "Main");
target.Close();
return;
}
if (response == null)
{
log.LogError("Error in SNMP request", "Main");
}
else
{
//If an incorrect response
if (response.Pdu.ErrorStatus != 0)
{
log.LogError("SNMP agent returned error status " + response.Pdu.ErrorStatus, "Main");
}
//If a successful response
else
{
log.LogInfo("Value of the " + response.Pdu[0].Oid.ToString() + "changed to " + response.Pdu[0].Value.ToString(), "Main");
}
}
target.Close();
log.CloseLogFile();
}
This is the part related to the variable in the MIB file
-- {SCALAR} 1.3.6.1.4.1.2356.11.2.88.2
lcsSetupWirelessEpaperPort OBJECT-TYPE
SYNTAX Integer32 (0..65535)
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"-- empty --"
::= { lcsSetupWirelessEpaper 2 }
I tired same using Net-SNMP on the command line also. but the result was same.
Can someone please tell me what would be the issue and what I is the point I am missing here.
Thank you.
A "no-access" (SNMP error code 6) could also indicate that SNMP community you are using ( I'm guessing it's "public" ) does not have write access. A monitoring system, for instance, should be able to read (GET) certain values, but not write (SET) them. From a security point-of-view, it is desirable to use a SNMP community that only has read access in this case.
Check the SNMP community configuration of your AP, to make sure it has write access. I would suggest adding a new community with write access, rather than changing access for "public".

Facebook sdk for Unity: error

As facebook just released it's new sdk for Unity. I m trying to use FB.API method and getting a lot of troubles with it. Like this is code I have written in UnityScript in my Unity project.
function LoginCallback() {
Debug.Log("User id is"+ FB.UserId);
FB.API("/me?fields=id,first_name,friends.limit(100).fields(first_name,id)", Facebook.HttpMethod.GET, LogCallback, null);
FBUtil.Log(FB.UserId); // Use this to sync progress, etc.
}
function LogCallback(response:String) {
// Debug.Log(response);
var profile = FBUtil.DeserializeJSONProfile(response);
var friends = FBUtil.DeserializeJSONFriends(response);
}
I am getting this error in Unity Log
BCE0005: Unknown identifier: 'FBUtil'.
And if I comment out the FBUtil part and just try to print the json string by writing this
function LoginCallback() {
Debug.Log("User id is"+ FB.UserId);
FB.API("/me?fields=id,first_name,friends.limit(100).fields(first_name,id)", Facebook.HttpMethod.GET, LogCallback, null);
}
function LogCallback(response:String) {
Debug.Log(response);
}
I am able to get Fb.UserId but I am not getting the response with the following details like first_name, friends. The error in DDMS Log is this
"09-04 21:35:04.534: E/Unity(23893): (Filename: ./Runtime/ExportGenerated/AndroidManaged/UnityEngineDebug.cpp Line: 54)
"
Someone help me out.

Google+ insert moment using google-api-dotnet-client

I am trying to write an activity in Google+ using the dotnet-client. The issue is that I can't seem to get the configuration of my client app correctly. According to the Google+ Sign-In configuration and this SO question we need to add the requestvisibleactions parameter. I did that but it did not work. I am using the scope https://www.googleapis.com/auth/plus.login and I even added the scope https://www.googleapis.com/auth/plus.moments.write but the insert still did not work.
This is what my request url looks like:
https://accounts.google.com/ServiceLogin?service=lso&passive=1209600&continue=https://accounts.google.com/o/oauth2/auth?scope%3Dhttps://www.googleapis.com/auth/plus.login%2Bhttps://www.googleapis.com/auth/plus.moments.write%26response_type%3Dcode%26redirect_uri%3Dhttp://localhost/%26state%3D%26requestvisibleactions%3Dhttp://schemas.google.com/AddActivity%26client_id%3D000.apps.googleusercontent.com%26request_visible_actions%3Dhttp://schemas.google.com/AddActivity%26hl%3Den%26from_login%3D1%26as%3D-1fbe06f1c6120f4d&ltmpl=popup&shdf=Cm4LEhF0aGlyZFBhcnR5TG9nb1VybBoADAsSFXRoaXJkUGFydHlEaXNwbGF5TmFtZRoHQ2hpa3V0bwwLEgZkb21haW4aB0NoaWt1dG8MCxIVdGhpcmRQYXJ0eURpc3BsYXlUeXBlGgdERUZBVUxUDBIDbHNvIhTeWybcoJ9pXSeN2t-k8A4SUbfhsygBMhQivAmfNSs_LkjXXZ7bPxilXgjMsQ&scc=1
As you can see from there that there is a request_visible_actions and I even added one that has no underscore in case I got the parameter wrong (requestvisibleactions).
Let me say that my app is being authenticated successfully by the API. I can get the user's profile after being authenticated and it is on the "insert moment" part that my app fails. My insert code:
var body = new Moment();
var target = new ItemScope();
target.Id = referenceId;
target.Image = image;
target.Type = "http://schemas.google.com/AddActivity";
target.Description = description;
target.Name = caption;
body.Target = target;
body.Type = "http://schemas.google.com/AddActivity";
var insert =
new MomentsResource.InsertRequest(
// this is a valid service instance as I am using this to query the user's profile
_plusService,
body,
id,
MomentsResource.Collection.Vault);
Moment result = null;
try
{
result = insert.Fetch();
}
catch (ThreadAbortException)
{
// User was not yet authenticated and is being forwarded to the authorization page.
throw;
}
catch (Google.GoogleApiRequestException requestEx)
{
// here I get a 401 Unauthorized error
}
catch (Exception ex)
{
} `
For the OAuth flow, there are two issues with your request:
request_visible_actions is what is passed to the OAuth v2 server (don't pass requestvisibleactions)
plus.moments.write is a deprecated scope, you only need to pass in plus.login
Make sure your project references the latest version of the Google+ .NET client library from here:
https://developers.google.com/resources/api-libraries/download/stable/plus/v1/csharp
I have created a project on GitHub showing a full server-side flow here:
https://github.com/gguuss/gplus_csharp_ssflow
As Brettj said, you should be using the Google+ Sign-in Button as demonstrated in the latest Google+ samples from here:
https://github.com/googleplus/gplus-quickstart-csharp
First, ensure you are requesting all of the activity types you're writing. You will know this is working because the authorization dialog will show "Make your app activity available via Google, visible to you and: [...]" below the text that starts with "This app would like to". I know you checked this but I'm 90% sure this is why you are getting the 401 error code. The following markup shows how to render the Google+ Sign-In button requesting access to Add activities.
<div id="gConnect">
<button class="g-signin"
data-scope="https://www.googleapis.com/auth/plus.login"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-clientId="YOUR_CLIENT_ID"
data-accesstype="offline"
data-callback="onSignInCallback"
data-theme="dark"
data-cookiepolicy="single_host_origin">
</button>
Assuming you have a PlusService object with the correct activity type set in data-requestvisibleactions, the following code, which you should be able to copy/paste to see it work, concisely demonstrates writing moments using the .NET client and has been tested to work:
Moment body = new Moment();
ItemScope target = new ItemScope();
target.Id = "replacewithuniqueforaddtarget";
target.Image = "http://www.google.com/s2/static/images/GoogleyEyes.png";
target.Type = "";
target.Description = "The description for the activity";
target.Name = "An example of add activity";
body.Target = target;
body.Type = "http://schemas.google.com/AddActivity";
MomentsResource.InsertRequest insert =
new MomentsResource.InsertRequest(
_plusService,
body,
"me",
MomentsResource.Collection.Vault);
Moment wrote = insert.Fetch();
Note, I'm including Google.Apis.Plus.v1.Data for convenience.
Ah it's that simple! Maybe not? I am answering my own question and consequently accept it as the answer (after a few days of course) so others having the same issue may be guided. But I will definitely up-vote Gus' answer for it led me to the fix for my code.
So according to #class answer written above and as explained on his blog the key to successfully creating a moment is adding the request_visible_actions parameter. I did that but my request still failed and it is because I was missing an important thing. You need to add one more parameter and that is the access_type and it should be set to offline. The OAuth request, at a minimum, should look like: https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/plus.login&response_type=code&redirect_uri=http://localhost/&request_visible_actions=http://schemas.google.com/AddActivity&access_type=offline.
For the complete and correct client code you can get Gus' example here or download the entire dotnet client library including the source and sample and add what I added below. The most important thing that you should remember is modifying your AuthorizationServerDescription for the Google API. Here's my version of the authenticator:
public static OAuth2Authenticator<WebServerClient> CreateAuthenticator(
string clientId, string clientSecret)
{
if (string.IsNullOrWhiteSpace(clientId))
throw new ArgumentException("clientId cannot be empty");
if (string.IsNullOrWhiteSpace(clientSecret))
throw new ArgumentException("clientSecret cannot be empty");
var description = GoogleAuthenticationServer.Description;
var uri = description.AuthorizationEndpoint.AbsoluteUri;
// This is the one that has been documented on Gus' blog site
// and over at Google's (https://developers.google.com/+/web/signin/)
// This is not in the dotnetclient sample by the way
// and you need to understand how OAuth and DNOA works.
// I had this already, see my original post,
// I thought it will make my day.
if (uri.IndexOf("request_visible_actions") < 1)
{
var param = (uri.IndexOf('?') > 0) ? "&" : "?";
description.AuthorizationEndpoint = new Uri(
uri + param +
"request_visible_actions=http://schemas.google.com/AddActivity");
}
// This is what I have been missing!
// They forgot to tell us about this or did I just miss this somewhere?
uri = description.AuthorizationEndpoint.AbsoluteUri;
if (uri.IndexOf("offline") < 1)
{
var param = (uri.IndexOf('?') > 0) ? "&" : "?";
description.AuthorizationEndpoint =
new Uri(uri + param + "access_type=offline");
}
// Register the authenticator.
var provider = new WebServerClient(description)
{
ClientIdentifier = clientId,
ClientSecret = clientSecret,
};
var authenticator =
new OAuth2Authenticator<WebServerClient>(provider, GetAuthorization)
{ NoCaching = true };
return authenticator;
}
Without the access_type=offline my code never worked and it will never work. Now I wonder why? It would be good to have some explanation.

Resources