Un recorrido por la API de permisos de JavaScript

Si alguna vez ha creado una aplicación web que requiere funciones diferentes (como notificaciones push, acceso a cámara web, acceso midi), probablemente haya notado que sus API se ven muy diferentes.
// for the geolocation API you need to call getCurrentPosition to check if geolocation is accessiblenavigator.geolocation.getCurrentPosition(gotLocation, didNotGetLocation);// for notifications we can directly check on the Notification objectif (Notification.permission == 'granted') // do notification stuffif (Notification.permission == 'denied') // ask for notification access ....
Esto no es muy útil.
La API de permisos nos permite tener una visión general de los permisos disponibles en nuestras páginas. Lo que queremos decir con "permiso" es si podemos acceder a una función específica con nuestro código. Las funciones que requieren permiso para acceder a ellas con código se denominan funciones potentes. La cámara, el midi, las notificaciones y la geolocalización son todas funciones potentes.
Todas las API de las funciones potentes son un poco diferentes. Por lo tanto, puede resultar complicado averiguar cuál es el estado de los permisos de cada función. Con la API de permisos, administramos todos los estados de los permisos con una única interfaz.
Conceptos básicos de la API de permisos
La API de permisos es muy experimental en esta etapa y debe usarse con cuidado. Solo debe usarla si es fundamental para la misión y puede mantenerse al día con los cambios futuros. Por ejemplo, algunos navegadores solían admitirla, navigator.permissions.revoke
pero ahora está obsoleta.
Al momento de escribir esto, query
es la única propiedad a la que podemos acceder desde la permissions
interfaz. query
toma un objeto como argumento llamadoPermisoDescriptorEl descriptor de permiso tiene un campo llamado name
, que es el nombre del permiso al que desea acceder.
// This query will give us information about the permissions attached to the cameranavigator.permissions.query({name: 'camera'})
La consulta devuelve una promesa que se resuelve en un PermissionStatus
. PermissionStatus tiene dos campos: state
y onchange
.
navigator.permissions.query({name: 'camera'}).then( permissionStatus = { console.log(permissionStatus) // in my browser on this page it logs: //{ // status: "prompt", // onchange: null, // }})
state
tiene 3 estados posibles: “concedido”, “denegado” y “solicitar permiso”. “concedido” significa que tenemos acceso a la función. “denegado” significa que no podremos acceder a la función. “solicitar permiso” significa que el agente de usuario (es decir, el navegador) le pedirá permiso al usuario si intentamos acceder a esa función.
Algunos PermissionDescriptor
tienen campos adicionales y puedes leer más sobre ellos aquí. Por ejemplo, camera
PermissionDescriptor de tiene un campo adicional llamado deviceId
si quieres apuntar a una cámara específica. Tu consulta podría verse así: .query({name: 'camera', deviceId: "my-device-id"})
.
onchange
es un detector de eventos que se activa siempre que cambian los permisos de la función consultada.
navigator.permissions.query({name:'camera'}).then(res = { res.onchange = ((e)={ // detecting if the event is a change if (e.type === 'change'){ // checking what the new permissionStatus state is const newState = e.target.state if (newState === 'denied') { console.log('why did you decide to block us?') } else if (newState === 'granted') { console.log('We will be together forever!') } else { console.log('Thanks for reverting things back to normal') } } })})
API de todos los permisos
Hay muchos permisos diferentes y potentes y la compatibilidad de los navegadores es muy desigual. En el siguiente script, puede ver todos los permisos descritos por el borrador del editor de W3C en la permissionsName
variable. La getAllPermissions
función devuelve una matriz con los diferentes permisos disponibles y su estado. Tenga en cuenta que el resultado cambiará según su navegador, la preferencia del usuario y, por supuesto, la configuración del sitio web.
const permissionsNames = [ "geolocation", "notifications", "push", "midi", "camera", "microphone", "speaker", "device-info", "background-fetch", "background-sync", "bluetooth", "persistent-storage", "ambient-light-sensor", "accelerometer", "gyroscope", "magnetometer", "clipboard", "display-capture", "nfc"]const getAllPermissions = async () = { const allPermissions = [] // We use Promise.all to wait until all the permission queries are resolved await Promise.all( permissionsNames.map(async permissionName = { try { let permission switch (permissionName) { case 'push': // Not necessary but right now Chrome only supports push messages with notifications permission = await navigator.permissions.query({name: permissionName, userVisibleOnly: true}) break default: permission = await navigator.permissions.query({name: permissionName}) } console.log(permission) allPermissions.push({permissionName, state: permission.state}) } catch(e){ allPermissions.push({permissionName, state: 'error', errorMessage: e.toString()}) } }) ) return allPermissions}
Si luego ejecuto el siguiente código en mi consola de desarrollador en Alligator.io:
(async function () { const allPermissions = await getAllPermissions() console.log(allPermissions)})()
Aquí hay una captura de pantalla de lo que obtengo en la consola:
Permisos en Trabajadores
Hasta ahora solo hemos utilizado la navigator.permissions
API porque es mucho más fácil escribir ejemplos concisos. La API de permisos también está disponible dentro de los trabajadores. WorkerNavigator.permissions
Nos permite comprobar los permisos dentro de nuestros trabajadores.
Esperamos que ahora tengas una mejor idea de cómo usar la API de permisos. No es muy complicada ni esencial, pero nos facilita mucho la gestión de permisos en nuestras aplicaciones basadas en JavaScript. Probablemente habrá algunas características y cambios nuevos en la API y te mantendremos informado.
Deja una respuesta