Progressively asking the user for extra permissions is a pattern we want to establish and standardize for most fission-powered apps and it has been a much requested feature.
However, it’s actually already possible with the webnative building blocks there are today! (Webnative version 0.23.2 that is)
Unfortunately, it’s still quite invovled, which is why not everyone is doing it. We’ll improve the API in the future, but in the mean time, here’s a tutorial for how to progressively ask for permissions with webnative:
import * as webnative from "webnative"
// We use lodash/merge for merging permission JSON objects
import lodashMerge from "lodash/merge"
// The permission baseline is the minimum permissions we need for running the app
// I.e. what we want to *always* have access to, if webnative.initialise successfully authenticated
const permissionBaseline = {
app: {
creator: "matheus23",
name: "progressive-permissions",
},
}
// Let's make working with localStorage easier for us
function lookupLocalStorage(key) {
const saved = localStorage.getItem(key)
try {
return JSON.parse(saved)
} catch (_) {
return null
}
}
function saveLocalStorage(key, json) {
localStorage.setItem(key, JSON.stringify(json, null, 2))
}
// We have two things we possibly store in localStorage:
// * permissions confirmed: Permissions we're pretty sure we already have
// * permissions wanted: Permissions we _just_ asked for in the auth lobby before
const permissionsConfirmedKey = "permissions-confirmed-v1"
const lookupPermissionsConfirmed = () => lookupLocalStorage(permissionsConfirmedKey)
const savePermissionsConfirmed = json => saveLocalStorage(permissionsConfirmedKey, json)
const permissionsWantedKey = "permissions-wanted-v1"
const lookupPermissionsWanted = () => lookupLocalStorage(permissionsWantedKey)
const savePermissionsWanted = json => saveLocalStorage(permissionsWantedKey, json)
// If the user denied the request for more permissions, we reset the wanted permissions
const url = new URL(window.location.href)
if (url.searchParams.get("cancelled") != null) {
savePermissionsWanted(null)
}
const permissionsConfirmed = lookupPermissionsConfirmed() || {}
const permissionsWanted = lookupPermissionsWanted() || {}
// We now merge the baseline with what we know we already should have and what we want to enable additionally.
// This is essentally the heart of it all
const permissions = lodashMerge(permissionBaseline, permissionsConfirmed, permissionsWanted)
// We now know with which permissions to initialise webnative
webnative.initialise({ permissions })
.then(state => {
if (state.authenticated) {
// We now know that this is the permissions we have
// and we'll request the same permissions next time
savePermissionsConfirmed(permissions)
} else {
// We actually don't have the permissions we expect to
// so we reset what we know to zero
savePermissionsConfirmed(null)
// This is also the case we run into if the user hasn't authenticated yet.
// So we do that.
webnative.redirectToLobby(permissionsBaseline)
}
// There should be no further permissions we want to request in the future.
// We either just got them, or we've got them denied. In any case we stop trying.
savePermissionsWanted(null)
// ... Initialise our app
})
// If we ever want more permissions, we call this function:
async function requestAdditionalPermissions(permissions) {
// We make sure that we actually initialise webnative with the
// additional permissions the next time we open the page
// (which is hopefully after the user accepted the permissions)
savePermissionsWanted(permissions)
await webnative.redirectToLobby(permissions)
}
// We can use it like this
await requestAdditionalPermissions({
fs: { privatePaths: ["Images/"] }
})
Feel free to comment your thoughts