UNPKG

@lanaqi/rsr

Version:
1,475 lines (1,474 loc) 74 kB
import { matchPath, useBlocker, useLocation, useNavigate } from "react-router"; import { createContext, use, useEffect, useState } from "react"; import { jsx } from "react/jsx-runtime"; import { c } from "react/compiler-runtime"; let common_AccessDecision = /*#__PURE__*/ function(AccessDecision) { AccessDecision["notResource"] = "notResource"; AccessDecision["notAuthentication"] = "notAuthentication"; AccessDecision["invalidAuthentication"] = "invalidAuthentication"; AccessDecision["notAuthorization"] = "notAuthorization"; AccessDecision["notSignature"] = "notSignature"; AccessDecision["accessDenied"] = "accessDenied"; AccessDecision["allowAccess"] = "allowAccess"; return AccessDecision; }({}); let common_AccessBehave = /*#__PURE__*/ function(AccessBehave) { AccessBehave["doNothing"] = "doNothing"; AccessBehave["goNavigate"] = "goNavigate"; AccessBehave["reDecision"] = "reDecision"; return AccessBehave; }({}); class SimpleAuthentication { datasheet; authenticated; constructor(datasheet){ this.datasheet = datasheet; this.authenticated = this.datasheet.authenticated ?? false; } isAuthenticated() { return this.authenticated; } setAuthenticated(authenticated) { this.authenticated = authenticated; } getDatasheet() { return this.datasheet; } } class SimpleAuthorization { datasheet; permissions; constructor(datasheet){ this.datasheet = datasheet; this.permissions = new Set(this.datasheet.permissions); } getPermissions() { return this.permissions; } getDatasheet() { return this.datasheet; } } class SimpleUser { datasheet; permissions; authenticated; invalid; constructor(datasheet){ this.datasheet = datasheet; this.permissions = new Set(this.datasheet.permissions); this.authenticated = this.datasheet.authenticated ?? false; this.invalid = this.datasheet.invalid ?? false; } isAuthenticated() { return this.authenticated; } setAuthenticated(authenticated) { this.authenticated = authenticated; } getPermissions() { return this.permissions; } getDatasheet() { return this.datasheet; } isInvalid() { return this.invalid; } setInvalid(invalid) { this.invalid = invalid; } } class SimpleResource { static PERMISSION_ANONYMOUS = '__aqi_rsr_anonymous'; static PERMISSION_AUTHENTICATED = '__aqi_rsr_authenticated'; static PERMISSION_AUTHORIZED = '__aqi_rsr_authorized'; static LABEL_SIGNATURED = '__aqi_rsr_signatured'; static LABEL_ALWAYS_SIGNATURE = '__aqi_rsr_always_signature'; patterns; permissions; labels; anonymous; authenticated; authorized; signatured; alwaysSignature; basename; constructor(patterns, permissions, labels, basename){ this.patterns = new Set(patterns); this.permissions = new Set(permissions); this.labels = new Set(labels); if (0 === this.patterns.size) throw new Error('访问资源模式集合不能为空,请检查!'); if (0 === this.permissions.size) { this.anonymous = true; this.authenticated = false; this.authorized = false; } else { if (this.permissions.has(SimpleResource.PERMISSION_ANONYMOUS)) { this.permissions.clear(); this.anonymous = true; } else this.anonymous = false; if (this.permissions.has(SimpleResource.PERMISSION_AUTHENTICATED)) { this.permissions.clear(); this.authenticated = true; } else this.authenticated = false; if (this.permissions.has(SimpleResource.PERMISSION_AUTHORIZED)) { this.permissions.clear(); this.authorized = true; } else this.authorized = false; } if (0 === this.labels.size) { this.signatured = false; this.alwaysSignature = false; } else { if (this.labels.has(SimpleResource.LABEL_SIGNATURED)) { this.labels.delete(SimpleResource.LABEL_SIGNATURED); this.signatured = true; } else this.signatured = false; if (this.labels.has(SimpleResource.LABEL_ALWAYS_SIGNATURE)) { this.labels.delete(SimpleResource.LABEL_ALWAYS_SIGNATURE); this.signatured = true; this.alwaysSignature = true; } else this.alwaysSignature = false; } this.basename = basename; } getPatterns() { return this.patterns; } getPermissions() { return this.permissions; } getLabels() { return this.labels; } hasPattern(pattern) { return this.patterns.has(pattern); } hasPermission(permission) { return this.permissions.has(permission); } hasLabel(label) { return this.labels.has(label); } isAnonymous() { return this.anonymous; } isAuthenticated() { return this.authenticated; } isAuthorized() { return this.authorized; } isSignatured() { return this.signatured; } isAlwaysSignature() { return this.alwaysSignature; } getBasename() { return this.basename; } setBasename(basename) { this.basename = basename; } } class SimpleRecorder { currentPath; allowPath; originPath; accessResource; accessAuthentication; accessAuthorization; getCurrentPath() { return this.currentPath; } setCurrentPath(currentPath) { this.currentPath = currentPath; } existCurrentPath() { return !!this.currentPath; } isCurrentPath(pathname) { if (this.currentPath) return this.currentPath.pathname === pathname; return false; } isCurrentPaths(...pathnames) { for (const pathname of pathnames){ const yes = this.isCurrentPath(pathname); if (yes) return true; } return false; } getAllowPath() { return this.allowPath; } setAllowPath(allowPath) { this.allowPath = allowPath; } existAllowPath() { return !!this.allowPath; } isAllowPath(pathname) { if (this.allowPath) return this.allowPath.pathname === pathname; return false; } isAllowPaths(...pathnames) { for (const pathname of pathnames){ const yes = this.isAllowPath(pathname); if (yes) return true; } return false; } getOriginPath() { return this.originPath; } setOriginPath(originPath) { this.originPath = originPath; } existOriginPath() { return !!this.originPath; } isOriginPath(pathname) { if (this.originPath) return this.originPath.pathname === pathname; return false; } isOriginPaths(...pathnames) { for (const pathname of pathnames){ const yes = this.isOriginPath(pathname); if (yes) return true; } return false; } getAccessResource() { return this.accessResource; } setAccessResource(accessResource) { this.accessResource = accessResource; } existAccessResource() { return !!this.accessResource; } getAccessAuthentication() { return this.accessAuthentication; } setAccessAuthentication(accessAuthentication) { this.accessAuthentication = accessAuthentication; } existAccessAuthentication() { return !!this.accessAuthentication; } getAccessAuthorization() { return this.accessAuthorization; } setAccessAuthorization(accessAuthorization) { this.accessAuthorization = accessAuthorization; } existAccessAuthorization() { return !!this.accessAuthorization; } clearOriginPath() { this.originPath = void 0; } clearAccessResource() { this.accessResource = void 0; } clearAccessAuthentication() { this.accessAuthentication = void 0; } clearAccessAuthorization() { this.accessAuthorization = void 0; } } class CacheVoter { cache; constructor(){ this.cache = new Map(); } cacheKey(term, have) { return `${[ ...have ].join('.')}_${[ ...term ].join('.')}`; } clearCache() { this.cache.clear(); } vote(term, have) { if (0 === term.size || 0 === have.size) return false; const key = this.cacheKey(term, have); if (this.cache.has(key)) return this.cache.get(key); const result = this.execVote(term, have); this.cache.set(key, result); return result; } } class SimpleVoter extends CacheVoter { all; constructor(all = false){ super(); this.all = all; } setAll(all) { this.all = all; } execVote(term, have) { for (const item of term)if (this.all) { if (!have.has(item)) return false; } else if (have.has(item)) return true; return this.all; } } class HierarchyPermission { permission; parent; constructor(permission){ this.permission = permission; } getPermission() { return this.permission; } setParent(parent) { this.parent = parent; } getParent() { return this.parent; } includeMy(permission) { if (this.permission === permission) return true; if (this.parent) return this.parent.includeMy(permission); return false; } } const OriginRelationResolver = (relation)=>relation; class HierarchyVoter extends CacheVoter { mapping; relation; all; resolver; constructor(resolver, relation, all = false){ super(); this.mapping = new Map(); this.relation = relation; this.all = all; this.resetResolver(resolver); } setAll(all) { this.all = all; } resetRelation(relation) { this.relation = relation; this.initHierarchy(); } resetResolver(resolver) { this.resolver = resolver; this.initHierarchy(); } initHierarchy() { const hierarchy = this.resolver(this.relation); const group = hierarchy.split(';'); if (group.length > 0) { this.clearCache(); this.mapping.clear(); for (const item of group){ const ps = item.split('>'); if (2 === ps.length) { const p1 = ps[0]; const p2 = ps[1]; let h1; if (this.mapping.has(p1)) h1 = this.mapping.get(p1); else { h1 = new HierarchyPermission(p1); this.mapping.set(p1, h1); } let h2; if (this.mapping.has(p2)) h2 = this.mapping.get(p2); else { h2 = new HierarchyPermission(p2); this.mapping.set(p2, h2); } h2.setParent(h1); } } } } includePermission(p1, p2) { if (this.mapping.has(p2)) return this.mapping.get(p2).includeMy(p1); return p1 === p2; } execVote(term, have) { for (const tp of term)for (const hp of have){ const hi = this.includePermission(hp, tp); if (hi) { if (!this.all) return true; } else if (this.all) return false; } return this.all; } getRelation() { return this.relation; } } class SimpleStorer { static KEY_AUTHENTICATION = '__aqi_rsr_authentication'; static KEY_AUTHORIZATION = '__aqi_rsr_authorization'; static KEY_SIGNATURE = '__aqi_rsr_signature'; aaaStorage; signStorage; authenticationKey; authorizationKey; signatureKey; authenticationValidator; constructor(aaaStorage, signStorage, authenticationKey = SimpleStorer.KEY_AUTHENTICATION, authorizationKey = SimpleStorer.KEY_AUTHORIZATION, signatureKey = SimpleStorer.KEY_SIGNATURE, authenticationValidator){ this.aaaStorage = aaaStorage; this.signStorage = signStorage; this.authenticationKey = authenticationKey; this.authorizationKey = authorizationKey; this.signatureKey = signatureKey; this.authenticationValidator = authenticationValidator; } loadAuthentication(recorder) { const authenticationStr = this.aaaStorage.getItem(this.authenticationKey); if (authenticationStr) { const authenticationObj = JSON.parse(authenticationStr); if ('boolean' == typeof authenticationObj.authenticated) if (void 0 !== authenticationObj.permissions && Array.isArray(authenticationObj.permissions)) return new SimpleUser(authenticationObj); else return new SimpleAuthentication(authenticationObj); } } verifyAuthentication(recorder, authentication) { if (this.authenticationValidator) return this.authenticationValidator(recorder, authentication); return true; } deleteAuthentication(recorder) { this.aaaStorage.removeItem(this.authenticationKey); } saveAuthentication(recorder, datasheet) { const ds = datasheet.getDatasheet(); const authenticationStr = JSON.stringify(ds); this.aaaStorage.setItem(this.authenticationKey, authenticationStr); } loadAuthorization(recorder, authentication) { if (authentication && authentication instanceof SimpleUser) return authentication; const authorizationStr = this.aaaStorage.getItem(this.authorizationKey); if (authorizationStr) { const authorizationObj = JSON.parse(authorizationStr); if (void 0 !== authorizationObj.permissions && Array.isArray(authorizationObj.permissions)) return new SimpleAuthorization(authorizationObj); } } deleteAuthorization(recorder) { const authentication = recorder.getAccessAuthentication(); if (authentication && authentication instanceof SimpleUser) return; this.aaaStorage.removeItem(this.authorizationKey); } saveAuthorization(recorder, datasheet) { const authentication = recorder.getAccessAuthentication(); if (authentication && authentication instanceof SimpleUser) return; const ds = datasheet.getDatasheet(); const authorizationStr = JSON.stringify(ds); this.aaaStorage.setItem(this.authorizationKey, authorizationStr); } loadSignature(recorder, path, authentication, authorization) { const signatureStr = this.signStorage.getItem(this.signatureKey); if (signatureStr) { const signatureList = JSON.parse(signatureStr); if (Array.isArray(signatureList) && signatureList.includes(path.pathname)) return true; } return false; } removeSignature(recorder, path) { const signatureStr = this.signStorage.getItem(this.signatureKey); if (signatureStr) { const signatureList = JSON.parse(signatureStr); if (Array.isArray(signatureList)) { const newSignatureList = signatureList.filter((signature)=>signature !== path.pathname); const newSignatureStr = JSON.stringify(newSignatureList); this.signStorage.setItem(this.signatureKey, newSignatureStr); } } } deleteSignature(recorder) { this.signStorage.removeItem(this.signatureKey); } saveSignature(recorder, path) { let signatureList; const signatureStr = this.signStorage.getItem(this.signatureKey); if (signatureStr) { signatureList = JSON.parse(signatureStr); if (!Array.isArray(signatureList)) signatureList = []; } else signatureList = []; const signatureSet = new Set(signatureList); signatureSet.add(path.pathname); const signatures = Array.from(signatureSet); const newSignatureStr = JSON.stringify(signatures); this.signStorage.setItem(this.signatureKey, newSignatureStr); } } class SimpleMatcher { cache; resources; basename; constructor(resources){ this.cache = new Map(); this.resources = resources; } match(resource, path) { let basename = resource.getBasename(); if (!basename) basename = this.getBasename(); const patterns = resource.getPatterns(); if (basename && basename.trim().length > 0) for (const pattern of patterns){ let matchPattern; matchPattern = 'string' == typeof pattern ? basename + pattern : { ...pattern, path: basename + pattern.path }; const pm = matchPath(matchPattern, path.pathname); if (pm) return true; } else for (const pattern of patterns){ const pm = matchPath(pattern, path.pathname); if (pm) return true; } return false; } obtain(path) { const pathname = path.pathname; if (this.cache.has(pathname)) return this.cache.get(pathname); for (const resource of this.resources){ const mp = this.match(resource, path); if (mp) { this.cache.set(pathname, resource); return resource; } } return null; } getBasename() { return this.basename; } setBasename(basename) { this.basename = basename; } } class SimpleNavigator { _navigate; constructor(navigate){ this._navigate = navigate; } navigate(to, options) { this._navigate(to, options); } } class SimpleContext { recorder; voter; storer; matcher; navigator; parent; constructor(recorder, voter, storer, matcher, navigator){ this.recorder = recorder; this.voter = voter; this.storer = storer; this.matcher = matcher; this.navigator = navigator; } getRecorder() { return this.recorder; } setRecorder(recorder) { this.recorder = recorder; } getVoter() { return this.voter; } setVoter(voter) { this.voter = voter; } getStorer() { return this.storer; } setStorer(storer) { this.storer = storer; } getMatcher() { return this.matcher; } setMatcher(matcher) { this.matcher = matcher; } getNavigator() { return this.navigator; } setNavigator(navigator) { this.navigator = navigator; } getParent() { return this.parent; } setParent(parent) { this.parent = parent; } } class AbstractAddon { guardBefore(context, manager, currentPath, currentResource) {} guardAfter(context, manager, currentPath, currentResource, currentDecision) {} permitBefore(context, manager, stayPath, blockPath, stayResource, blockResource) {} permitAfter(context, manager, stayPath, blockPath, stayResource, blockResource) {} } class BehaveHandler { _config; constructor(config){ this._config = config; } config(config) { this._config = config; } notResource(context) { if (this._config.notResourcePath) { context.getNavigator().navigate(this._config.notResourcePath); return common_AccessBehave.goNavigate; } if (this._config.notResourceFunc) return this._config.notResourceFunc(context); return this.accessDenied(context); } notAuthentication(context) { if (this._config.notAuthenticationPath) { context.getNavigator().navigate(this._config.notAuthenticationPath); return common_AccessBehave.goNavigate; } if (this._config.notAuthenticationFunc) return this._config.notAuthenticationFunc(context); throw new Error('没有认证的行为是必须配置的,请检查!'); } invalidAuthentication(context) { if (this._config.invalidAuthenticationPath) { context.getNavigator().navigate(this._config.invalidAuthenticationPath); return common_AccessBehave.goNavigate; } if (this._config.invalidAuthenticationFunc) return this._config.invalidAuthenticationFunc(context); return this.notAuthentication(context); } notAuthorization(context) { if (this._config.notAuthorizationPath) { context.getNavigator().navigate(this._config.notAuthorizationPath); return common_AccessBehave.goNavigate; } if (this._config.notAuthorizationFunc) return this._config.notAuthorizationFunc(context); return this.accessDenied(context); } notSignature(context) { if (this._config.notSignaturePath) { context.getNavigator().navigate(this._config.notSignaturePath); return common_AccessBehave.goNavigate; } if (this._config.notSignatureFunc) return this._config.notSignatureFunc(context); return this.accessDenied(context); } accessDenied(context) { if (this._config.accessDeniedPath) { context.getNavigator().navigate(this._config.accessDeniedPath); return common_AccessBehave.goNavigate; } if (this._config.accessDeniedFunc) return this._config.accessDeniedFunc(context); throw new Error('拒绝访问的行为是必须配置的,请检查!'); } allowAccess(context) { if (this._config.allowAccessFunc) this._config.allowAccessFunc(context); return common_AccessBehave.doNothing; } errorDecision(context, decision) { if (this._config.errorDecisionFunc) return void this._config.errorDecisionFunc(context, decision); if (decision === common_AccessDecision.notSignature) return; switch(decision){ case common_AccessDecision.notResource: this.accessDenied(context); break; case common_AccessDecision.notAuthentication: throw new Error('没有认证的错误决策,请检查!'); case common_AccessDecision.invalidAuthentication: this.notAuthentication(context); break; case common_AccessDecision.notAuthorization: this.accessDenied(context); break; case common_AccessDecision.accessDenied: default: throw new Error('拒绝访问的错误决策,请检查!'); } } } class SingleBlocker { handler; block(context, currentPath, currentResource) { if (this.handler) return this.handler(context, currentPath, currentResource); return false; } register(handler) { this.handler = handler; } unregister(handler) { this.handler = void 0; } } class MultiBlocker { handlers; constructor(){ this.handlers = new Set(); } block(context, currentPath, currentResource) { for (const handler of this.handlers){ const blocked = handler(context, currentPath, currentResource); if (blocked) return true; } return false; } register(handler) { this.handlers.add(handler); } unregister(handler) { if (handler) this.handlers.delete(handler); } clear() { this.handlers.clear(); } } class SimpleManager { disabled; handler; blocker; parent; constructor(disabled, handler, blocker){ this.disabled = disabled; this.handler = handler; this.blocker = blocker; } isDisabled() { return this.disabled; } setDisabled(disabled) { this.disabled = disabled; } getHandler() { return this.handler; } setHandler(handler) { this.handler = handler; } getBlocker() { return this.blocker; } setBlocker(blocker) { this.blocker = blocker; } getParent() { return this.parent; } setParent(parent) { this.parent = parent; } } class SimpleGuarder { context; manager; addons; constructor(context, manager, addons){ this.context = context; this.manager = manager; this.addons = addons; } guardDecision(blockPath) { const recorder = this.context.getRecorder(); recorder.setCurrentPath(blockPath); const resource = this.obtainResource(blockPath); let authentication; if (recorder.existAccessAuthentication()) authentication = recorder.getAccessAuthentication(); else { authentication = this.obtainAuthentication(); if (authentication) recorder.setAccessAuthentication(authentication); } let authorization; if (recorder.existAccessAuthorization()) authorization = recorder.getAccessAuthorization(); else { authorization = this.obtainAuthorization(authentication); if (authorization) recorder.setAccessAuthorization(authorization); } if (resource) recorder.setAccessResource(resource); else { recorder.clearAccessResource(); return common_AccessDecision.notResource; } if (resource.isAnonymous()) { recorder.setAllowPath(blockPath); return common_AccessDecision.allowAccess; } if (authentication?.isAuthenticated()) recorder.clearOriginPath(); else { recorder.setOriginPath(blockPath); return common_AccessDecision.notAuthentication; } const valid = this.checkAuthentication(authentication); if (valid) recorder.clearOriginPath(); else { recorder.setOriginPath(blockPath); return common_AccessDecision.invalidAuthentication; } if (resource.isAuthenticated()) { recorder.setAllowPath(blockPath); return common_AccessDecision.allowAccess; } if (authorization) recorder.clearOriginPath(); else { recorder.setOriginPath(blockPath); return common_AccessDecision.notAuthorization; } if (resource.isAuthorized()) { recorder.setAllowPath(blockPath); return common_AccessDecision.allowAccess; } const authorized = this.checkPermission(resource, authorization); if (authorized) recorder.clearOriginPath(); else { recorder.setOriginPath(blockPath); return common_AccessDecision.accessDenied; } if (resource.isSignatured() && !this.checkSignature(blockPath, authentication, authorization)) { recorder.setOriginPath(blockPath); return common_AccessDecision.notSignature; } recorder.clearOriginPath(); recorder.setAllowPath(blockPath); return common_AccessDecision.allowAccess; } guardHandle(currentDecision, beforeDecision) { const recorder = this.context.getRecorder(); const storer = this.context.getStorer(); const handler = this.manager.getHandler(); if (beforeDecision && beforeDecision !== common_AccessDecision.allowAccess && beforeDecision === currentDecision) { if (beforeDecision === common_AccessDecision.invalidAuthentication) { recorder.clearAccessAuthentication(); recorder.clearAccessAuthorization(); storer.deleteAuthentication(recorder); storer.deleteAuthorization(recorder); storer.deleteSignature(recorder); } handler.errorDecision(this.context, currentDecision); return common_AccessBehave.doNothing; } let behave; switch(currentDecision){ case common_AccessDecision.notResource: behave = handler.notResource(this.context); break; case common_AccessDecision.notAuthentication: recorder.clearAccessAuthentication(); recorder.clearAccessAuthorization(); storer.deleteAuthentication(recorder); storer.deleteAuthorization(recorder); storer.deleteSignature(recorder); behave = handler.notAuthentication(this.context); break; case common_AccessDecision.invalidAuthentication: behave = handler.invalidAuthentication(this.context); break; case common_AccessDecision.notAuthorization: recorder.clearAccessAuthorization(); storer.deleteAuthorization(recorder); storer.deleteSignature(recorder); behave = handler.notAuthorization(this.context); break; case common_AccessDecision.notSignature: behave = handler.notSignature(this.context); break; case common_AccessDecision.allowAccess: behave = handler.allowAccess(this.context); break; case common_AccessDecision.accessDenied: default: behave = handler.accessDenied(this.context); break; } return behave; } guardBlock(currentPath) { const currentResource = this.obtainResource(currentPath); const blocker = this.manager.getBlocker(); return blocker.block(this.context, currentPath, currentResource); } guardBefore(currentPath) { const currentResource = this.obtainResource(currentPath); this.forAddons((addon)=>{ addon.guardBefore(this.context, this.manager, currentPath, currentResource); }); } guardAfter(currentPath, currentDecision) { const currentResource = this.obtainResource(currentPath); this.forAddons((addon)=>{ addon.guardAfter(this.context, this.manager, currentPath, currentResource, currentDecision); }); } permitBefore(stayPath, blockPath) { const stayResource = this.obtainResource(stayPath); const blockResource = this.obtainResource(blockPath); this.clearSignature(stayPath, stayResource); this.forAddons((addon)=>{ addon.permitBefore(this.context, this.manager, stayPath, blockPath, stayResource, blockResource); }); } permitAfter(stayPath, blockPath) { const stayResource = this.obtainResource(stayPath); const blockResource = this.obtainResource(blockPath); this.forAddons((addon)=>{ addon.permitAfter(this.context, this.manager, stayPath, blockPath, stayResource, blockResource); }); } forAddons(fn) { if (Array.isArray(this.addons) && this.addons.length > 0) for (const addon of this.addons)fn(addon); } obtainResource(path) { const matcher = this.context.getMatcher(); return matcher.obtain(path); } obtainAuthentication() { const storer = this.context.getStorer(); const recorder = this.context.getRecorder(); return storer.loadAuthentication(recorder); } checkAuthentication(authentication) { const storer = this.context.getStorer(); const recorder = this.context.getRecorder(); return storer.verifyAuthentication(recorder, authentication); } obtainAuthorization(authentication) { const storer = this.context.getStorer(); const recorder = this.context.getRecorder(); return storer.loadAuthorization(recorder, authentication); } checkPermission(resource, authorization) { const voter = this.context.getVoter(); return voter.vote(resource.getPermissions(), authorization.getPermissions()); } checkSignature(path, authentication, authorization) { const storer = this.context.getStorer(); const recorder = this.context.getRecorder(); return storer.loadSignature(recorder, path, authentication, authorization); } clearSignature(stayPath, stayResource) { if (stayResource?.isSignatured() && stayResource.isAlwaysSignature()) { const storer = this.context.getStorer(); const recorder = this.context.getRecorder(); storer.removeSignature(recorder, stayPath); } } } class AccessRecorderBuilder { build() { return new SimpleRecorder(); } } class AccessVoterBuilder { _resolver; _hierarchy; _all = false; resolver(resolver) { this._resolver = resolver; return this; } hierarchy(hierarchy) { this._hierarchy = hierarchy; return this; } all(all) { this._all = all; return this; } build() { if (this._hierarchy && this._hierarchy.trim().length > 0) { if (!this._resolver) this._resolver = OriginRelationResolver; return new HierarchyVoter(this._resolver, this._hierarchy, this._all); } return new SimpleVoter(this._all); } } class AccessStorerBuilder { _aaaStorage; _signStorage; _authenticationKey; _authorizationKey; _signatureKey; _authenticationValidator; aaaStorage(aaaStorage) { this._aaaStorage = aaaStorage; return this; } signStorage(signStorage) { this._signStorage = signStorage; return this; } authenticationKey(authenticationKey) { this._authenticationKey = authenticationKey; return this; } authorizationKey(authorizationKey) { this._authorizationKey = authorizationKey; return this; } signatureKey(signatureKey) { this._signatureKey = signatureKey; return this; } authenticationValidator(authenticationValidator) { this._authenticationValidator = authenticationValidator; return this; } local() { return this.aaaStorage(window.localStorage).signStorage(window.localStorage); } session() { return this.aaaStorage(window.sessionStorage).signStorage(window.sessionStorage); } blend() { return this.aaaStorage(window.localStorage).signStorage(window.sessionStorage); } build() { if (!this._aaaStorage && !this._signStorage) this.session(); if (!this._aaaStorage) this.aaaStorage(window.localStorage); if (!this._signStorage) this.signStorage(window.sessionStorage); return new SimpleStorer(this._aaaStorage, this._signStorage, this._authenticationKey, this._authorizationKey, this._signatureKey, this._authenticationValidator); } } class AccessResourceBuilder { _patterns = new Set(); _permissions = new Set(); _labels = new Set(); _basename; patterns(...patterns) { for (const pattern of patterns)this._patterns.add(pattern); return this; } permissions(...permissions) { for (const permission of permissions)this._permissions.add(permission); return this; } labels(...labels) { for (const label of labels)this._labels.add(label); return this; } anonymous() { this._permissions.add(SimpleResource.PERMISSION_ANONYMOUS); return this; } authenticated() { this._permissions.add(SimpleResource.PERMISSION_AUTHENTICATED); return this; } authorized() { this._permissions.add(SimpleResource.PERMISSION_AUTHORIZED); return this; } signatured() { this._labels.add(SimpleResource.LABEL_SIGNATURED); return this; } alwaysSignature() { this.signatured(); this._labels.add(SimpleResource.LABEL_ALWAYS_SIGNATURE); return this; } basename(basename) { this._basename = basename; return this; } config(config) { this.patterns(...config.patterns).permissions(...config.permissions); if (config.labels) this.labels(...config.labels); if (config.basename) this.basename(config.basename); return this; } build() { return new SimpleResource(this._patterns, this._permissions, this._labels, this._basename); } } class AccessMatcherBuilder { _resources = []; config(config) { this._resources.push(new AccessResourceBuilder().config(config).build()); return this; } configs(...configs) { for (const config of configs)this.config(config); return this; } resource(builder) { this._resources.push(builder(new AccessResourceBuilder())); return this; } resources(resources) { this._resources.push(...resources); return this; } build() { return new SimpleMatcher(this._resources); } } class AccessNavigatorBuilder { _navigate; navigate(navigate) { this._navigate = navigate; return this; } build() { if (!this._navigate) throw new Error('导航函数是必须设置的,请检查!'); return new SimpleNavigator(this._navigate); } } class AccessContextBuilder { _recorder; _voter; _storer; _matcher; _navigator; _hierarchy; _validator; _resources = []; _navigate; recorder(recorder) { if ('function' == typeof recorder) this._recorder = recorder(new AccessRecorderBuilder()); else this._recorder = recorder; return this; } voter(voter) { if ('function' == typeof voter) this._voter = voter(new AccessVoterBuilder()); else this._voter = voter; return this; } storer(storer) { if ('function' == typeof storer) this._storer = storer(new AccessStorerBuilder()); else this._storer = storer; return this; } matcher(matcher) { if ('function' == typeof matcher) this._matcher = matcher(new AccessMatcherBuilder()); else this._matcher = matcher; return this; } navigator(navigator) { if ('function' == typeof navigator) this._navigator = navigator(new AccessNavigatorBuilder()); else this._navigator = navigator; return this; } hierarchy(hierarchy) { this._hierarchy = hierarchy; return this; } validator(validator) { this._validator = validator; return this; } resource(builder) { const resource = builder(new AccessResourceBuilder()); this._resources.push(resource); return this; } navigate(navigate) { this._navigate = navigate; return this; } drs() { this.resource((rb)=>rb.patterns('/login', '/logout', '/denied', '/signature').anonymous().build()); this.resource((rb)=>rb.patterns('/*').authenticated().build()); return this; } build() { if (!this._recorder) this.recorder((builder)=>builder.build()); if (!this._voter) this.voter((builder)=>{ if (this._hierarchy) builder.hierarchy(this._hierarchy); return builder.build(); }); if (!this._storer) this.storer((builder)=>{ if (this._validator) builder.authenticationValidator(this._validator); return builder.build(); }); if (!this._matcher) { if (0 === this._resources.length) this.drs(); this.matcher((builder)=>builder.resources(this._resources).build()); } if (!this._navigator) this.navigator((builder)=>{ if (this._navigate) builder.navigate(this._navigate); return builder.build(); }); return new SimpleContext(this._recorder, this._voter, this._storer, this._matcher, this._navigator); } } class AccessHandlerBuilder { _config; config(config) { this._config = config; return this; } build() { if (!this._config) throw new Error('行为配置是必须设置,请检查!'); return new BehaveHandler(this._config); } } class AccessBlockerBuilder { _multi; multi() { this._multi = true; return this; } single() { this._multi = false; return this; } build() { if (this._multi) return new MultiBlocker(); return new SingleBlocker(); } } class AccessManagerBuilder { _disabled = false; _handler; _blocker; _behave; disabled() { this._disabled = true; return this; } handler(handler) { if ('function' == typeof handler) this._handler = handler(new AccessHandlerBuilder()); else this._handler = handler; return this; } blocker(blocker) { if ('function' == typeof blocker) this._blocker = blocker(new AccessBlockerBuilder()); else this._blocker = blocker; return this; } behave(behave) { this._behave = behave; return this; } dbc() { return this.behave({ notAuthenticationPath: '/login', accessDeniedPath: '/denied', notSignaturePath: '/signature' }); } build() { if (!this._handler) this.handler((builder)=>{ if (!this._behave) this.dbc(); return builder.config(this._behave).build(); }); if (!this._blocker) this.blocker((builder)=>builder.single().build()); return new SimpleManager(this._disabled ?? false, this._handler, this._blocker); } } class AccessGuarderBuilder { _context; _manager; _addons = []; _navigate; context(context) { if ('function' == typeof context) { const builder = new AccessContextBuilder(); if (this._navigate) builder.navigate(this._navigate); this._context = context(builder); } else this._context = context; return this; } manager(manager) { if ('function' == typeof manager) this._manager = manager(new AccessManagerBuilder()); else this._manager = manager; return this; } addons(...addons) { for (const addon of addons)this._addons.push(addon); return this; } navigate(navigate) { this._navigate = navigate; return this; } build() { if (!this._context) this.context((builder)=>builder.build()); if (!this._manager) this.manager((builder)=>builder.build()); return { context: this._context, manager: this._manager, guarder: new SimpleGuarder(this._context, this._manager, this._addons) }; } } const SecurityContext = /*#__PURE__*/ createContext(null); const useSecurityContext = ()=>{ const sc = use(SecurityContext); if (!sc) throw new Error('安全上下文为空,必须使用安全提供者包裹组件来设置安全上下文'); return sc; }; function SecurityBlocker(t0) { const $ = c(14); const { children } = t0; const { context, guarder } = useSecurityContext(); const blocker = useBlocker(_temp); const [guarded, setGuarded] = useState(false); const [nextPath, setNextPath] = useState(useLocation()); const [firstAccess, setFirstAccess] = useState(true); const [firstHandle, setFirstHandle] = useState(true); const [countSignature, setCountSignature] = useState(1); const [handledDecision, setHandledDecision] = useState(false); const [beforeDecision, setBeforeDecision] = useState(void 0); const [currentDecision, setCurrentDecision] = useState(void 0); const [securityBlock, setSecurityBlock] = useState(false); const [executableBlocked, setExecutableBlocked] = useState(true); let t1; let t2; if ($[0] !== beforeDecision || $[1] !== blocker || $[2] !== context || $[3] !== countSignature || $[4] !== currentDecision || $[5] !== executableBlocked || $[6] !== firstAccess || $[7] !== firstHandle || $[8] !== guarder || $[9] !== handledDecision || $[10] !== nextPath || $[11] !== securityBlock) { t1 = ()=>{ if ("blocked" === blocker.state && executableBlocked) { let isProceed; const recorder = context.getRecorder(); const stayPath = recorder.getAllowPath(); const blockPath = blocker.location; let guardBlocked = false; if (securityBlock) guardBlocked = guarder.guardBlock(blockPath); if (guardBlocked) { setHandledDecision(false); setCurrentDecision(void 0); isProceed = false; } else { if (!beforeDecision) guarder.guardBefore(blockPath); const blockedDecision = guarder.guardDecision(blockPath); setHandledDecision(true); setCurrentDecision(blockedDecision); isProceed = blockedDecision === common_AccessDecision.allowAccess; } setNextPath(blockPath); setExecutableBlocked(false); if (isProceed) { const isDiff = !!stayPath && stayPath.pathname !== blockPath.pathname; if (isDiff) guarder.permitBefore(stayPath, blockPath); blocker.proceed(); if (isDiff) guarder.permitAfter(stayPath, blockPath); } else blocker.reset(); } else if ("unblocked" === blocker.state) { if (handledDecision && currentDecision) { let navNext; const behave = guarder.guardHandle(currentDecision, beforeDecision); switch(behave){ case common_AccessBehave.reDecision: setBeforeDecision(currentDecision); setSecurityBlock(false); navNext = true; break; case common_AccessBehave.goNavigate: setBeforeDecision(void 0); navNext = false; setSecurityBlock(false); break; case common_AccessBehave.doNothing: default: setBeforeDecision(void 0); navNext = false; setSecurityBlock(true); } if (firstHandle && currentDecision === common_AccessDecision.notSignature && behave === common_AccessBehave.reDecision) if (countSignature >= 3) { setFirstHandle(false); setBeforeDecision(common_AccessDecision.notSignature); setHandledDecision(true); setCurrentDecision(common_AccessDecision.accessDenied); } else { const signDecision = guarder.guardDecision(nextPath); setHandledDecision(true); setBeforeDecision(void 0); setCurrentDecision(signDecision); setCountSignature(countSignature + 1); } else { setFirstHandle(false); setHandledDecision(false); setCurrentDecision(void 0); if (navNext) context.getNavigator().navigate(nextPath); else { guarder.guardAfter(nextPath, currentDecision); setGuarded(true); } } } else if (firstAccess) { guarder.guardBefore(nextPath); const firstDecision = guarder.guardDecision(nextPath); setFirstAccess(false); setHandledDecision(true); setCurrentDecision(firstDecision); } if (!executableBlocked) setExecutableBlocked(true); } }; t2 = [ blocker, context, guarder, nextPath, firstAccess, firstHandle, countSignature, handledDecision, beforeDecision, currentDecision, securityBlock, executableBlocked ]; $[0] = beforeDecision; $[1] = blocker; $[2] = context; $[3] = countSignature; $[4] = currentDecision; $[5] = executableBlocked; $[6] = firstAccess; $[7] = firstHandle; $[8] = guarder; $[9] = handledDecision; $[10] = nextPath; $[11] = securityBlock; $[12] = t1; $[13] = t2; } else { t1 = $[12]; t2 = $[13]; } useEffect(t1, t2); if (!guarded) return null; return children; } function _temp(t0) { const { currentLocation, nextLocation } = t0; return currentLocation.pathname !== nextLocation.pathname; } function SecurityProvider(t0) { const $ = c(8); const { children, bundler } = t0; const navigate = useNavigate(); let t1; if ($[0] !== bundler || $[1] !== navigate) { t1 = bundler(new AccessGuarderBuilder().navigate(navigate)); $[0] = bundler; $[1] = navigate; $[2] = t1; } else t1 = $[2]; const provide = t1; if (provide.manager.isDisabled()) return children; let t2; if ($[3] !== children) { t2 = /*#__PURE__*/ jsx(SecurityBlocker, { children: children }); $[3] = children; $[4] = t2; } else t2 = $[4]; let t3; if ($[5] !== provide || $[6] !== t2) { t3 = /*#__PURE__*/ jsx(SecurityContext, { value: provide, children: t2 }); $[5] = provide;