Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
54 lines
2.9 KiB
JavaScript
54 lines
2.9 KiB
JavaScript
// Shared authorization for platform adapters. Identity comes from the host, never the request.
|
|
export function authorizePlatform(app, operation, params = {}) {
|
|
const permissions = app.manifest.permissions || {};
|
|
const writeMedia = (type) =>
|
|
['pictures', 'music', 'videos'].includes(type) &&
|
|
permissions['device-storage:' + type]?.access?.includes('write');
|
|
const allowed = {
|
|
capabilities: true,
|
|
notificationEvent: app.id === 'system',
|
|
systemReady: app.id === 'system',
|
|
power: app.id === 'system',
|
|
callScreenClosed: app.id === 'callscreen',
|
|
settings: ['settings', 'system', 'costcontrol'].includes(app.id),
|
|
snapshot: ['settings', 'system', 'costcontrol'].includes(app.id),
|
|
wifi: ['settings', 'system'].includes(app.id),
|
|
notification: !!permissions['desktop-notification'],
|
|
capture: app.id === 'camera' && writeMedia('pictures'),
|
|
cameraPreview: app.id === 'camera' && writeMedia('pictures'),
|
|
pick: writeMedia(params.type),
|
|
contact: !!permissions.contacts?.access?.includes('write'),
|
|
dial: app.id === 'communications',
|
|
calls: ['system', 'communications', 'callscreen'].includes(app.id),
|
|
callHistory: app.id === 'communications',
|
|
ackCallHistory: app.id === 'communications',
|
|
hangup: ['system', 'communications', 'callscreen'].includes(app.id),
|
|
answer: ['system', 'communications', 'callscreen'].includes(app.id),
|
|
sms: app.id === 'sms',
|
|
callAudio: ['system','callscreen'].includes(app.id),
|
|
alarms: app.id === 'clock',
|
|
};
|
|
if (!Object.hasOwn(allowed, operation)) throw Error('METHOD_NOT_SUPPORTED');
|
|
if (!allowed[operation]) throw Error('PERMISSION_DENIED');
|
|
if (operation === 'cameraPreview' &&
|
|
(!['start', 'frame', 'stop', 'focus', 'zoom', 'picture'].includes(params.action) ||
|
|
(params.action === 'start' && !['back', 'front'].includes(params.camera))))
|
|
throw Error('INVALID_VALUE');
|
|
if (operation === 'cameraPreview') {
|
|
if (params.action === 'zoom' && (!Number.isFinite(params.zoom) || params.zoom<1 || params.zoom>100))
|
|
throw Error('INVALID_VALUE');
|
|
if (params.action === 'focus' && params.area != null) {
|
|
const a=params.area;
|
|
if (!['left','right','top','bottom'].every(k=>Number.isInteger(a[k]) && Math.abs(a[k])<=1000) ||
|
|
a.left>=a.right || a.top>=a.bottom) throw Error('INVALID_VALUE');
|
|
}
|
|
if (params.action === 'picture' && params.size != null &&
|
|
!['width','height'].every(k=>Number.isInteger(params.size[k]) && params.size[k]>0 && params.size[k]<=20000))
|
|
throw Error('INVALID_VALUE');
|
|
}
|
|
if (operation === 'ackCallHistory' && (!Array.isArray(params.ids) || params.ids.length > 500 || params.ids.some(id => typeof id !== 'string' || !/^\d{1,20}$/.test(id)))) throw Error('INVALID_VALUE');
|
|
if (operation === 'wifi' && JSON.stringify(params).length > 4096)
|
|
throw Error('QuotaExceededError');
|
|
if (operation === 'notification' && JSON.stringify(params).length > 65536)
|
|
throw Error('QuotaExceededError');
|
|
}
|