How to load JavaScript file after launching Google Web App - google-apps-script

I have two questions:
I have a Google web app (created with google app script) in my G-Suite account. Permissions are set to Execute the app as: Me / Who has access to the app: Anyone
In addition to Code.gs the app has three files
"Form.html" (html interface)
"JSfile1.html" (Javascript routines)
"JSfile2.html" (Javascript routines)
The loading of the third file ("JSfile2.html") is optional depending upon the user (which is determined after the app is launched). Executing doGet(e){} I am loading the first two files and depending upon the user I would like to either load or skip "JSfile2.html". Is there a way to append
HTMLOutput after the app is launched. I am using the following code.
function doGet(e) {
var template = HtmlService.createTemplateFromFile('Form');
var js1 = include('JSfile1')
HTMLOutput.append(js1);
HTMLOutput.append(template.evaluate().getContent());
return HTMLOutput
.setTitle('BCAS, App')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function include(file) {
return HtmlService.createHtmlOutputFromFile(file).getContent();
};
Is there a way to retrieve information from users browser local storage before the web app is launched and make it available while executing doGet()

No to both questions. The proper way to do this is by using google.script.run. Call server functions from client side and adjust the DOM accordingly.
Reference:
Client server communication

Related

How to convert my google sheet script to web app?

I have created a Google Sheet to process a Sales and send mail from it. But I have found a limitation, it works only on PC and cannot be used on an android phone using the Sheets app. Is there a way to convert my code to a web app, use Sheets as my database and use the interface from my phone?
Create a deployment of the project as a web-app. you'll probably want to use the Test Deployment for developing and you will need the doGet(e) function to get the page up and running.
function doGet(e)
{
var html = HtmlService.createHtmlOutputFromFile("your_HTML_file_here");
return html;
}
The function above creates the webpage but the rest of the code will end up in the html file that contains the web page.
To interact with google and its services you can use
google.script.run
This allows the user to run google script code from an html page.
Not sure what you mean by "convert". You can publish your project as web app (for that you need doGet() function and some kind of UI) and then access it on mobile via URL.

Can I deploy google app script project locally or from another platform?

I am creating a web application using a google app script. In this application I integrated google sign in as a feature. When I deploy the app through the google app script IDE, everything is fine until I press the button "sign in with google" and it gives me an error which is saying mismatch with the JavaScript origin. When I try to add the JavaScript origin it will not accept it and says either it is invalid or it is forbidden. When I try to do that locally it works perfectly (I added the JavaScript origin as my localhost) but the rest of the functionalities like adding data to a spreadsheet does not work. I know that there is no solution for the first bit (to use the sign in button when I deploy the app through Google App Script IDE) because I have done exhaustive research about it. So, I was wondering if there is another way. like another platform that can support the deployment of my project, meaning there is no problem with the google sign in and the interaction with the google spreadsheet.
For security reasons, Google Apps Script sandboxes your HTML Service (see restrictions documentation). In the case of Content Services, it redirects to a different domain every time it’s executed (see documentation). Because of this, you have two options: use Google Apps Script to execute as the visiting user and to get a static site hosting.
1. Using Google Apps Script
Instead of running the calls to the APIs in the front end, you can make functions in Google Apps Script and then call them using google.script.run in the frontend. It will also simplify your code as all the OAuth is handled by Google Apps Script.
// Google Apps Script side
function doSomething() {
const ss = SpreadsheetApp.openByUrl('…')
// […]
return result
}
And to call it I’d use something like:
// Client side
function doWork() {
google.script.run
.withSuccessHandler(successCallback)
.doSomething() // Function name in the backend
}
Make sure to deploy the application with the option Execute as: with the value User accessing the web app so it’s not executed as you.
With this setup the user will be asked to give the required permissions before opening the page.
2. Use a web hosting
The second solution is to find a web hosting provider. Because you don’t seem to have a backend it can be for static pages (some are free). This will give you a stable URL and should work exactly the same as in your localhost.
References
HTML Service: Restrictions (Google Developers)
Content Service Redirects (Google Developers)
google.script.run (Google Developers)

HTTP Request to a function in Google Scripts

Since I'm not experienced at all with HTTP Request and Google Scripts, I'm having trouble wraping my head around it.
So, my problem is the following:
I'm currently trying to get information in my lua script and send it to a google Spreadsheet. However, the way the google spreadsheet should save the info would be dependent on which function on the Google Script I'm calling and passing information.
SO, my question is: How would my lua script (that only gives me access to HTTP Requests at this time) connect to a specific function like the one bellow?
function callName(name) {
// Get the last Row and add the name provided
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(sheet.getLastRow() + 1,1).setValue([name]);
}
Also, I think my script is wrong as well, but I'm more worried about how to actually make the connection.
Answer:
You can publish your script as a Web Application and use URL parameters to pass the script the information you need.
More Information:
From the Google documentation about web apps:
If you build a user interface for a script, you can publish the script as a web app. For example, a script that lets users schedule appointments with members of a support team would best be presented as a web app so that users can access it directly from their browsers.
However, even without building a user interface, you can use this functionality to run scripts on your sheet by utilising HTTP requests.
Modifying your Script:
In order to allow your script to accept URL parameters, you must first modify your code so that processing is done on a HTTP GET request. You can do this with the Apps Script doGet() function and the event parameter e:
function doGet(e) {
callName(e.parameter.name);
}
function callName(name) {
// Get the last Row and add the name provided
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(sheet.getLastRow() + 1,1).setValue([name]);
}
Setting up the Web App:
From the Apps Script user interface, follow the Publish > Deploy as web app... menu item, and in the newly-opened modal window, you'll want to select the following settings:
Project version: New
Execute the app as: Me (your-email#address.here)
Who has access to the app: Anyone, even anonymous
And click Deploy. Here, you will be given a URL in a new, smaller modal in the following form:
https://script.google.com/a/your-domain.com/macros/s/some-script-id/exec
Making the request:
The rest of this is now trivial - you can make your HTTP request to the script URL in the previous step, but providing the URL parameter that you need in order to give te app the information of the value you wish to set.
For example, if you want to set the value to the number 20, make your get request as so:
GET https://script.google.com/a/your-domain.com/macros/s/some-script-id/exec?name=20
Note the ?name=20 at the end gives the Web App the parameter name with a value of 20. The doGet(e) function reads this from e.parameter.name and sends it to your callName(name) function for processing and execution.
References:
Web Apps | Apps Script | Google Developers
Request Parameters

Using UrlFetchApp in a container-bound script to run code in a web app as effective user

In a little over my head. Trying to use UrlFetchApp.fetch(url, options) from a container-bound script to run code in a web app.
The problem: Container-bound doc script can only run as the activeUser. doc script creates a new doc by copying a template. I would like the doc newly created from the template to be stored in a centralized folder owned by the developer. I see two solutions.
I give all domain users view/edit access to the developer's folder.
I create a web app from a standalone script which runs as the effectiveUser (developer) who has access to the folder. In this case the doc script calls the web app using UrlFetchApp passing in the parameters (folder, doc). However, to quite able to figure out how to do this, if possible.
var unitId = DocumentApp.getActiveDocument().getId();
var unit = DriveApp.getFileById(unitId);
var folderId = unit.getDescription() //FoldId for unit is stored in description
var folder = DriveApp.getFolderById(folderId);
var lesson = DriveApp.getFileById(UNIT.LESSON_TEMPLATE_ID).makeCopy('Lesson - ' + result.getResponseText());
folder.addFile(lesson);//Currently I have the folder shared/edit with domain users.
//I would prefer to share/view. However, since the
//container-bound doc script runs only as active user, no
//can do. Is it possible to build a small web app which
//runs as effective user and saves lesson to folder.
showLessonSidebar(folderId);
Any hints out there?
Yes, it is possible to create a web app that runs as effective user.If the developer - effective user has access to folder and template file.
You could pass the folderId and Name of the file to be copied to the WebApp, rather than passing folder and Doc object (passing the folder Object and Doc object as URL parameter may be quite tricky and if content is too large may not be even possible as there are constraints on the possible length of URL)
1) Write a Apps Script
function doGet(e) {
var folderId = e.parameters.folderId;
var copyFileName = e.parameters.name;
var userEmail = e.parameters.email;
var folder = DriveApp.getFolderById(folderId);
var lesson = DriveApp.getFileById(UNIT.LESSON_TEMPLATE_ID).makeCopy(copyFileName);
folder.addFile(lesson);
//share file to domain or share folder with domain - folder.setSharing(....);
file.setSharing(DriveApp.Access.DOMAIN, DriveApp.Permission.VIEW);
}
2) While deploying the Web App, developer can set Execute as me(developer#...) and set "Who has access to Web App" as Anyone.
3) Make sure developer has authorized the web App.
4) Share the Web App Script file with all your domain users.
Also, if you want to pass the content of file for some reason from container-script to Web App, you may consider implementing the logic in doPost() as you would have the ability to pass large data using POST in UrlFetch.
As far as I understand, the only way to use UrlFetch in a bound script, is using an installed trigger. (UrlFetch is not authorized to run when used in a bound script's simple triggers: https://developers.google.com/apps-script/add-ons/lifecycle#authorization_modes.)
An installed trigger always "runs with the authorization of the user who created the trigger, even if another user with edit access opens the spreadsheet". Thus, simply use installed triggers:
function setupTrigger(){
var doc = DocumentApp.getActiveDocument();
ScriptApp.newTrigger('open').forDocument(doc).onOpen().create();
}
This sample code creates an installable trigger for opening the document bound to the script.

google script Session.getActiveUser().getEmail() not working

I've developed a web app with google script and code this in my gs.
var email = Session.getActiveUser().getEmail();
Logger.log(email);
// then do something to render the Email address on the page
After publishing the script, I log in with another account and execute the script.
Then the page display this:
This application was created by another user, not by Google.
This application has access to the following personal information: email address.
But still nothing in Log and the page display nothing.
I just don't get it...
Although it's not stated explicitly in the reference documentation for Session.GetActiveUser(), my testing confirmed that your web app needs to execute as the user accessing the web app to have access to getActiveUser(). I used the code below and the logging library described here.
Depending on the use case of your application, perhaps you could create a library containing a centralized ScriptDB instance to capture the active user email. Then, create another project that works with your private spreadsheet and the same scriptDB library.
var LOG_FILENAME = 'your-log-doc'
var LOG_PATH = 'folder/subfolder/third-folder'
function doGet() {
//Change variable above to a good path and filename for you
var x = LogLibrary.InitializeLogging(LOG_PATH, LOG_FILENAME)
Logger.log(x)
var email = Session.getActiveUser().getEmail();
Logger.log("Start email logging")
Logger.log(email);
LogLibrary.fnSaveLog() //Write the save and flush the logger content
// then do something to render the Email address on the page
var HTMLToOutput = '<html><h1>A header</h1><p>' + email + '</p></html>';
return HtmlService.createHtmlOutput(HTMLToOutput);
}
I've made some tests because I am looking for a solution about the same problem,and I conclude that :
so that function can works, the web app should be executed as "user accessing the web app", and for that, the web app should be configured so that can be executed as user accessing the web app
Note that : the user will be asked to authorise the script to access, edit and
manage it's drive also receiving and sending mails (which is not evident !! for all most of users of corse").
In the end that it depend of what you will use it for.
And in google documentation nothing is mentioned about this issue!!
For a simple function that returns the email address as a text to use as script or in google html forms.. etc :
function onOpen(){
var emailName = Session.getActiveUser().getEmail();
var optionsHtml = emailName.toString().split(",");
return optionsHtml;
}
Look in the gas issues forum (google). It hax been addressed many times. Basically you need to set it as run as user accessing the app if u expect users from outside your domain. Changing that setting will qlikely break your app depending on the permissions it needs
If your app is from before the 25th of June 2013, and you are using getEffectiveUser() or getUser() methods you will need to re-authorize the script because of the new authorization experience.
You can see the documentation here.
https://developers.google.com/apps-script/scripts_google_accounts#understandingPermissions
And do not forget to execute the script before deploying.
If you want to access the user's email, make sure you have added the "https://www.googleapis.com/auth/userinfo.email" email access policy in the appsscript .json
You can see the documentation here.
https://developers.google.com/apps-script/reference/base/session#authorization