29 lines
3.4 KiB
JavaScript
29 lines
3.4 KiB
JavaScript
import {z} from 'zod';
|
|
const id=z.string().min(1).max(80).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/);
|
|
const unique=(schema,max)=>z.array(schema).max(max).refine(a=>new Set(a).size===a.length,'Duplicate values');
|
|
const host=z.string().max(253).regex(/^(\*\.)?[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/i);
|
|
export const UserAccessSchema=z.object({delegatableFeatures:z.object({devTools:z.boolean().default(false)}).strict().prefault({})}).strict().prefault({});
|
|
export const DomainCategorySchema=z.object({id,name:z.string().min(1).max(100),hosts:unique(host,500)}).strict();
|
|
export const UserProfileSchema=z.object({id,name:z.string().min(1).max(100),subjects:unique(z.string().min(1).max(512),10000).default([]),deviceIds:unique(id,10000).default([]),allowedHosts:unique(host,500).default([]),blockedHosts:unique(host,500).default([]),blockedCategoryIds:unique(id,100).default([]),features:z.object({devTools:z.enum(['inherit','allow','deny']).default('inherit'),downloads:z.enum(['inherit','deny']).default('inherit'),ai:z.enum(['inherit','deny']).default('inherit'),agents:z.enum(['inherit','deny']).default('inherit'),agentBackgroundWorkers:z.enum(['inherit','deny']).default('inherit')}).strict().prefault({}),requireDocumentScan:z.boolean().default(false)}).strict();
|
|
export const UserProfileConfigurationSchema=z.object({profiles:z.array(UserProfileSchema).max(100).default([]),categories:z.array(DomainCategorySchema).max(100).default([])}).strict();
|
|
export function profileApplies(profile,device){return profile.deviceIds.includes(device.id)||!!device.verified_subject&&profile.subjects.includes(device.verified_subject);}
|
|
const covers=(a,b)=>a===b||a.startsWith('*.')&&b.endsWith(a.slice(1));
|
|
export function applyUserProfiles(policy,configuration,device){
|
|
const result=structuredClone(policy),config=UserProfileConfigurationSchema.parse(configuration||{}),profiles=config.profiles.filter(p=>profileApplies(p,device)).sort((a,b)=>a.id.localeCompare(b.id));
|
|
const union=(a,b)=>[...new Set([...a,...b])].sort();
|
|
for(const p of profiles){
|
|
result.browser.blockedHosts=union(result.browser.blockedHosts,p.blockedHosts);
|
|
for(const categoryId of p.blockedCategoryIds){const category=config.categories.find(c=>c.id===categoryId);if(!category)throw Error('Unknown domain category');result.browser.blockedHosts=union(result.browser.blockedHosts,category.hosts);}
|
|
if(p.allowedHosts.length){const existing=result.browser.allowedHosts;result.browser.allowedHosts=existing.length?union(existing.filter(a=>p.allowedHosts.some(b=>covers(b,a))),p.allowedHosts.filter(b=>existing.some(a=>covers(a,b)))):p.allowedHosts;if(!result.browser.allowedHosts.length){result.browser.allowedHosts=['denied.invalid'];result.browser.blockedHosts=union(result.browser.blockedHosts,['denied.invalid']);}}
|
|
if(p.features.downloads==='deny')result.browser.allowDownloads=false;
|
|
if(p.features.ai==='deny')result.ai.enabled=false;
|
|
if(p.features.agents==='deny')result.agents.enabled=false;
|
|
if(p.features.agentBackgroundWorkers==='deny')result.browser.allowAgentBackgroundWorkers=false;
|
|
if(p.requireDocumentScan)result.inspection.documentAnalysisEnabled=true;
|
|
}
|
|
if(profiles.some(p=>p.features.devTools==='deny'))result.browser.allowDevTools=false;
|
|
else if(result.userAccess.delegatableFeatures.devTools&&profiles.some(p=>p.features.devTools==='allow'))result.browser.allowDevTools=true;
|
|
result.assignment={deviceId:device.id,groups:[],...(profiles.length?{profiles:profiles.map(p=>p.id)}:{})};
|
|
return result;
|
|
}
|