Outlook add-in Storage for settings - javascript

I've been trying to use
Office.context.roamingSettings.set("keyVal", value)
Office.context.roamingSettings.get("keyVal")
To save in storage, but it only work for the current session.
Now I've been trying to the saveAsync. But it doesn't take parameters. So I wanna how it supposed to be used. And also if it keeps the data in all platforms for the user(OWA, mobile, and Desktop)
Office.context.roamingSettings.saveAsync(function (result) {
if (result.status !== Office.AsyncResultStatus.Succeeded) {
console.error(`Action failed with message ${result.error.message}`);
} else {
console.log(`Settings saved with status: ${result.status}`);
}
});

During the lifetime of the session you can just use the set and get methods to work with the in-memory copy of the settings property bag.
When you want to persist the settings so that they are available the next time the add-in is used, use the saveAsync method to save the settings after calling the set method. For an example see this code snippet: https://github.com/OfficeDev/office-js-snippets/blob/main/samples/outlook/10-roaming-settings/roaming-settings.yaml

Related

localStorage not working in other host - javascript

I am developing a firefox addon. i use localStorage to save some data and retrieve.
function to check if it is available or not
if(!localStorage.getItem('font')) {
populateStorage();
}else{
var aValue = localStorage.getItem('font');
alert(aValue);
if not then create
function populateStorage(){
localStorage.setItem('cname', name);
localStorage.setItem('font', 'Helvetica');
localStorage.setItem('image', 'myCat.png');
}
This is perfectly working localhost but if i visit other host like google.com and try to get i am getting error not found
if(!localStorage.getItem('font')) {
alert('Not found !!!!');
}else{
var aValue = localStorage.getItem('font');
alert(aValue);
}
is there any way to fix this issue ? or am i doing it in wrong way ?
LocalStorage is intended to be accessible only from the same host. This allows different websites to have a different scope for their data, and also ensures that one website cannot access data from another website.
From MDN,
The read-only localStorage property allows you to access a Storage object for the Document's origin; the stored data is saved across browser sessions.
From: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
If you need to share data across different domains, you should use server-side persistence.
From what I've undestood local storage is not cross domain solution, so this behavior is correct.
What you need to do is fallow MDN solution. I've found something like this:
// define 2 objects
var monster = {
name: "Kraken",
tentacles: true,
eyeCount: 10
}
var kitten = {
name: "Moggy",
tentacles: false,
eyeCount: 2
}
// store the objects
browser.storage.local.set({kitten, monster})
.then(setItem, onError);
(code copied from MDN > JavaScript APIs > storage )
In this solution data will be pinned to browser/extension, not to domain. But be aware, that data still will be destroyed when user clear browser cache or something like that.

Firebase custom claim how to set?

I'm struggling with firebase custom claims.
I have tested a lot of approaches nothing works. Obviously, I miss something important in the concept itself.
So I'm back to the root. This script from the google example should apply customs rule on a newly created user
exports.processSignUp = functions.auth.user().onCreate(event => {
const user = event.data; // The Firebase user.
const customClaims = {
param: true,
accessLevel: 9
};
// Set custom user claims on this newly created user.
return admin.auth().setCustomUserClaims(user.uid, customClaims)
});
Then on a client, I check the result with
firebase.auth().currentUser.getIdTokenResult()
.then((idTokenResult) => {
// Confirm the user is an Admin.
console.log(idTokenResult.claims)
if (!!idTokenResult.claims.param) {
// Show admin UI.
console.log("param")
} else {
// Show regular user UI.
console.log("no param")
}
})
.catch((error) => {
console.log(error);
});
Everything just a raw copy-paste still doesn't work. I've tested both from the local machine(there could be troubles with cors?) and deployed
This is a race situation. If the Function end first then, you will get the updated data.
The getIdTokenResult method does force refresh but if the custom claim is not ready then, it is pointless.
You need to set another data control structure to trigger the force refresh on the client. By example a real-time listener to the rtd;
root.child(`permissions/${uid}`).on..
And the logic inside the listener would be: if the value for that node exists and is a number greater than some threshold, then trigger the user auth refresh
During that time the ui can reflect a loading state if there is no datasnapshot or the not admin view if the datasnapshot exists but is a lower permission level.
In Functions you have to set the node after the claim is set:
..setCustomUserClaims(..).then(
ref.setValue(9)
);
I have a more detailed example on pastebin
The claims on the client are populated when the client gets an ID token from the server. The ID token is valid for an hour, after which the SDK automatically refreshes it.
By the time the Cloud Functions auth.user().onCreate gets called, the client has already gotten the ID token for the new user. This means that it can take up to an hour before the client sees the updated claims.
If you want the client to get the custom claims before that, you can force it to refresh the token. But in this video our security experts recommend (that you consider) using a different storage mechanism for claims that you want to be applied straight away.

Session cookies not working in Electron

I'm looking at implementing a login system in an Electron[0] application which I'm building but getting stuck on the part of handling the session. Basically I want to store the users session so it is persisted between application restarts (if "Remember me" is enabled).
I have to make use of an existing back-end which works with cookie authentication and I'm not able to change anything there.
From the Electron documentation on the Session object[1] I gathered that I should be using a partition like f.e. persist:someName in order to have a persistent storage, but this is not persisted between application restarts as it seems.
The way I currently set the cookie is as follows:
// main-process/login.js
const session = require('electron').session;
const currentSession = session.fromPartition('persist:someName').cookies;
currentSession.set({
name: 'myCookie',
url: 'https://www.example.com',
value: 'loggedin=1',
expirationDate: 1531036000
}, function(error) {
console.log('Cookie set');
if (error) {
console.dir(error);
}
});
After running this, I see the Cookie set output, but when restarting the app and running the following code:
// main.js
const session = require('electron').session;
const currentSession = session.fromPartition('persist:someName').cookies;
currentSession.get({}, function(error, cookies) {
console.dir(cookies);
if (error) {
console.dir(error);
}
});
The output returned is [].
Any pointers as to what I'm doing wrong or need to do differently would be highly appreciated!
[0] http://electron.atom.io
[1] http://electron.atom.io/docs/api/session/
An alternative might be to take a look at electron-json-storage. Using this plugin, you can write JSON to a system file throughout the user experience and then recall that file on the application load to replace the user "state".

Log client browse website information in backbone.js

I'm using this code to get client information :
$.getJSON("http://www.geoplugin.net/json.gp?jsoncallback=?",function (data) {
console.log(data.geoplugin_request);
console.log(data.geoplugin_countryName);
});
Then I would like to record this information at the first time that client visit the website (session start of the website). My current project are using backbone.js, require.js, underscore.js.
Any suggestions would be appreciated. Thanks.
Assuming that you have application.js file which act as a entry point of the backbone aplication which initializes your router an all stuff, you can set the client details in the browser using localStorage.
// Retrieve the object from storage
var retrievedVar = localStorage.getItem('countryName');
if( retrievedVar == null) {
$.getJSON("http://www.geoplugin.net/json.gp?jsoncallback=?",function (data) {
console.log(data.geoplugin_countryName);
// Put the object into storage
localStorage.seItem('countryName', JSON.stringify(data.geoplugin_countryName)
});
Hence the getJSON will only be fired once when localStorage var is not set.

What's the best way use caching data in js on client side?

My application receives data from the another server, using API with limited number of requests. Data changing rarely, but may be necessary even after refresh page.
What's the best solution this problem, using cookie or HTML5
WebStorage?
And may be have other way to solve this task?
As much as cross browser compatibility matters, cookie is the only choice rather than web storage.
But the question really depends on what kind of data you are caching?
For what you are trying, cookie and web-storage might not be needed at all.
Cookies are used to store configuration related information, rather than actual data itself.
Web storage supports persistent data storage, similar to cookies but with a greatly enhanced capacity and no information stored in the HTTP request header. [1]
I would rather say, it would be stupid to cache the entire page as cookie or web-storage both. For these purposes, server-side caching options might be the better way.
Update:
Quoting:
data about user activity in some social networks (fb, vk, google+)
Detect the web-storage features, using libraries like mordernizr and if does not exists fall back to cookie method. A simple example
if (Modernizr.localstorage) {
// browser supports local storage
// Use this method
} else {
// browser doesn't support local storage
// Use Cookie Method
}
[1]: http://en.wikipedia.org/wiki/Web_storage
I wrote this lib to solve the same problem:
Cache your data with Javascript using cacheJS
Here are some basic usages
// just add new cache using array as key
cacheJS.set({blogId:1,type:'view'},'<h1>Blog 1</h1>');
cacheJS.set({blogId:1,type:'json'}, jsonData);
// remove cache using key
cacheJS.removeByKey({blogId:1,type:'json'});
// add cache with ttl and contextual key
cacheJS.set({blogId:2,type:'view'},'<h1>Blog 2</h1>', 3600, {author:'hoangnd'});
cacheJS.set({blogId:3,type:'view'},'<h1>Blog 3</h1>', 3600, {author:'hoangnd'});
// remove cache with con textual key
// cache for blog 2 and 3 will be removed
cacheJS.removeByContext({author:'hoangnd'})
Here is an example of caching data from JQuery AJAX. So if you only want to make the call when you don't have the data yet, its really simple. just do this (example). Here we first check if we have the load information (keyed on line, location and shipdate), and only if we dont, we make the AJAX call and put that data into our cache:
var dict = [];
function checkCachedLoadLine(line, location, shipDate, callback) {
var ret = 0;
if(!((line+location+shipDate) in dict)) {
productionLineService.getProductionLoadLine(line, location, shipDate, callback);
}
return dict[line+location+shipDate];
}
...then in the call back write the value to the cache
function callback(data) {
if (!data) {
document.getElementById('htmlid').innerHTML = 'N/A';
} else {
document.getElementById('htmlid').innerHTML = data[0];
dict[data[2]+data[3]+data[4]] = data[0];
}
}

Categories