feathers-ucan 0.1.19 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.cjs CHANGED
@@ -1,2 +1,1021 @@
1
- var e=require("symbol-ucan"),t=require("@feathersjs/authentication");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=/*#__PURE__*/n(require("long-timeout"));function i(e){function t(e){if(Object(e)!==e)return Promise.reject(new TypeError(e+" is not an object."));var t=e.done;return Promise.resolve(e.value).then(function(e){return{value:e,done:t}})}return i=function(e){this.s=e,this.n=e.next},i.prototype={s:null,n:null,next:function(){return t(this.n.apply(this.s,arguments))},return:function(e){var n=this.s.return;return void 0===n?Promise.resolve({value:e,done:!0}):t(n.apply(this.s,arguments))},throw:function(e){var n=this.s.return;return void 0===n?Promise.reject(e):t(n.apply(this.s,arguments))}},new i(e)}function o(){return o=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o.apply(this,arguments)}function a(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,u(e,t)}function c(e){return c=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},c(e)}function u(e,t){return u=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},u(e,t)}function s(e,t,n){return s=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}()?Reflect.construct.bind():function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&u(i,n.prototype),i},s.apply(null,arguments)}function l(e){var t="function"==typeof Map?new Map:void 0;return l=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return s(e,arguments,c(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),u(n,e)},l(e)}function f(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r<o.length;r++)t.indexOf(n=o[r])>=0||(i[n]=e[n]);return i}function h(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function p(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(n)return(n=n.call(e)).next.bind(n);if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return h(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?h(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0;return function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var v=/*#__PURE__*/function(e){function t(t){return e.call(this,t)||this}return a(t,e),t}(/*#__PURE__*/l(Error)),d=/(\S+)\s+(\S+)/,y=/*#__PURE__*/function(t){function n(){for(var e,n=arguments.length,r=new Array(n),i=0;i<n;i++)r[i]=arguments[i];return(e=t.call.apply(t,[this].concat(r))||this).expirationTimers=new WeakMap,e}a(n,t);var i,c,u=n.prototype;return u.setAuthentication=function(e){e.verifyAccessToken=function(e){return{}},t.prototype.setAuthentication.call(this,e)},u.handleConnection=function(t,n,i){try{var o=this,a="logout"===t&&n.authentication&&i&&n.authentication.accessToken===i.accessToken,c=(i||{}).accessToken,u=function(){if(c&&"login"===t)return Promise.resolve(e.validateUcan(c).catch(function(e){console.log("Could not validate ucan in connection: ",e.message);var t={code:0,message:"Unknown Issue Validating Ucan"};throw e.message.indexOf("Expired.")>-1&&(t.code=1,t.message="Expired Ucan"),new Error(t.message)})).then(function(e){var t=1e3*(e||{payload:{exp:0}}).payload.exp-Date.now(),i=r.default.setTimeout(function(){return o.app.emit("disconnect",n)},t);r.default.clearTimeout(o.expirationTimers.get(n)),o.expirationTimers.set(n,i),n.authentication={strategy:o.name,accessToken:c}});("disconnect"===t||a)&&(delete n[o.configuration.entity],delete n.authentication,r.default.clearTimeout(o.expirationTimers.get(n)),o.expirationTimers.delete(n))}();return Promise.resolve(u&&u.then?u.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},u.verifyConfiguration=function(){for(var e=["entity","entityId","service","header","schemes","audience"],t=0,n=Object.keys(this.configuration);t<n.length;t++){var r=n[t];if(!e.includes(r))throw new Error("Invalid ucanStrategy option 'authentication."+this.name+"."+r+"'. Did you mean to set it in 'authentication.jwtOptions'?")}if("string"!=typeof this.configuration.header)throw new Error("The 'header' option for the "+this.name+" strategy must be a string")},u.getEntityQuery=function(e){return Promise.resolve({})},u.getEntity=function(t,n){try{var r=this,i=r.entityService,a=r.configuration.entity;if(null===i)throw new v("Could not find entity service");return Promise.resolve(r.getEntityQuery(n)).then(function(r){var c=Object.assign({},e._unset(n,"provider"),{query:r});return Promise.resolve(i.get(t,c)).then(function(e){var r;return n.provider?i.get(t,o({},n,((r={})[a]=e,r))):e})})}catch(e){return Promise.reject(e)}},u.getEntityId=function(e,t){try{var n=t.query,r=t.loginId;if(r)return Promise.resolve(r);var i,a,c=this.configuration,u=c.service,s=c.core_path,l=void 0===s?"core":s,f=((i={query:o({},n,{$limit:1})})[l]=o({skipJoins:!0},t[l]),i);return Promise.resolve(null==(a=this.app)?void 0:a.service(u).find(o({},f,{skipJoins:!0,skip_hooks:!0,admin_pass:!0}))).then(function(e){if(e.total)return e.data[0]._id;throw new v("Could not find login associated with this ucan")})}catch(e){return Promise.reject(e)}},u.authenticate=function(t,n){try{var r=this,i=t.accessToken,a=t.loginId,c=t.ucan,u=r.configuration,s=u.entity,l=u.core_path;if(!i){if(!c)throw new v("Error generating ucan");i=e.ucanToken(c)}return Promise.resolve(e.validateUcan(i).catch(function(e){console.log("Could not validate ucan during authentication: ",e.message);var t={code:0,message:"Unknown Issue Validating Ucan"};throw e.message.indexOf("Expired.")>-1&&(t.code=1,t.message="Expired Ucan"),new Error(t.message)})).then(function(t){function c(){var e;return o({},f,((e={})[s]=u,e))}var u,f={accessToken:i,authentication:{strategy:"jwt",accessToken:i}};if(null===s)return f;var h=e._get(n,[l,s]),p=function(){if(!h)return Promise.resolve(r.getEntityId(f,o({},n,{loginId:a,query:{did:null==t?void 0:t.payload.aud}}))).then(function(e){return Promise.resolve(r.getEntity(e,n)).then(function(e){u=e})});u=h}();return p&&p.then?p.then(c):c()})}catch(e){return Promise.reject(e)}},u.parse=function(e){try{var t=this.configuration,n=t.schemes,r=e.headers&&e.headers[t.header.toLowerCase()];if(!r||"string"!=typeof r)return Promise.resolve(null);var i=r.match(d)||[],o=i[1],a=i[2],c=o&&n.some(function(e){return new RegExp(e,"i").test(o)});return Promise.resolve(o&&!c?null:{strategy:this.name,accessToken:c?a:r})}catch(e){return Promise.reject(e)}},i=n,(c=[{key:"configuration",get:function(){var e,n=(null==(e=this.authentication)?void 0:e.configuration)||{service:void 0,entity:void 0,entityId:void 0};return o({service:n.service,entity:n.entity,entityId:n.entityId,header:"Authorization",schemes:["Bearer","JWT"]},t.prototype.configuration)}}])&&function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,"symbol"==typeof(i=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,"string");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(r.key))?i:String(i),r)}var i}(i.prototype,c),Object.defineProperty(i,"prototype",{writable:!1}),n}(t.AuthenticationBaseStrategy),g=["NotAuthenticated"],m=/*#__PURE__*/function(e){function t(t){return e.call(this,t)||this}return a(t,e),t}(/*#__PURE__*/l(Error)),P=/*#__PURE__*/function(t){function n(e,n,r){var i;void 0===n&&(n="authentication"),void 0===r&&(r={});var o=r.NotAuthenticated,a=f(r,g);return(i=t.call(this,e,n,a)||this).options=void 0,i.app=e,i.options={NotAuthenticated:o},i}return a(n,t),n.prototype.create=function(t,n){try{var r,i,a=this,c=(null==(r=a.options)?void 0:r.NotAuthenticated)||m,u=a.app.get("authentication"),s=u.entity,l=u.service,f=u.ucan_path,h=void 0===f?"ucan":f,p=(null==(i=n)?void 0:i.authStrategies)||a.configuration.authStrategies;if(n||(n={}),!p.length)throw new c("No authentication strategies allowed for creating a JWT (`authStrategies`)");return Promise.resolve(a.authenticate.apply(a,[t,n].concat(p)).catch(function(e){throw new Error(e.message)})).then(function(r){if(r.accessToken)return r;var i=t.did||e._get(r,[s,"did"]),c=t.ucan||e._get(r,[s,"ucan"]);if(!i)throw new Error("No did audience provided");if(!c)throw new Error("No ucan provided to authentication call");return Promise.resolve(e.validateUcan(c).catch(function(e){console.log("Could not validate ucan creating authentication: ",e.message);var t={code:0,message:"Unknown Issue Validating Ucan"};return e.message.indexOf("Expired.")>-1&&(t.code=1,t.message="Expired Ucan"),console.warn("Could not validate ucan creating authentication",c,t.message),null})).then(function(t){function i(){var t=e.ucanToken(c);return o({accessToken:t},r,{authentication:o({},r.authentication,{payload:t})})}var u=function(){if(!t){var i=e.parseUcan(c),u=a.app.get("authentication"),f=e.encodeKeyPair({secretKey:u.secret});return Promise.resolve(e.buildUcan({audience:i.payload.aud,issuer:f,lifetimeInSeconds:5184e3,capabilities:i.payload.att})).then(function(t){var i;return c=t,n.admin_pass=!0,Promise.resolve(a.app.service(l).patch(e._get(r,[s,"_id"]),(i={},i[h]=e.ucanToken(c),i),o({},n))).then(function(){})})}}();return u&&u.then?u.then(i):i()})})}catch(e){return Promise.reject(e)}},n}(t.AuthenticationService),_=/*#__PURE__*/function(){function e(e,t,n){var r;this.context=void 0,this.service=void 0,this.core=void 0,this.entity=void 0,this.service=e,this.context=t;var i=(t.app.get("authentication")||{entity:"login"}).entity||"login";this.entity=i;var a=(null==(r=t.params)?void 0:r.core)||{};a[i]||(a[i]=t.params[i]),this.core=o({},a,n)}var t=e.prototype;return t.get=function(e,t){void 0===t&&(t={});try{var n,r,i,a=this,c=a.context.app.get("authentication").core_path;return Promise.resolve(null==(n=a.context.app)?void 0:n.service(a.service).get(e,o({},t,((r={})[a.entity]=t[a.entity],r),((i={})[c]=a.core,i))))}catch(e){return Promise.reject(e)}},t.find=function(e){void 0===e&&(e={});try{var t,n,r,i=this,a=i.context.app.get("authentication").core_path;return Promise.resolve(null==(t=i.context.app)?void 0:t.service(i.service).find(o({},e,((n={})[i.entity]=e[i.entity],n.skip_hooks=!0,n.admin_pass=!0,n),((r={})[a]=i.core,r))))}catch(e){return Promise.reject(e)}},t.create=function(e,t){void 0===t&&(t={});try{var n,r,i,a=this,c=a.context.app.get("authentication").core_path;return Promise.resolve(null==(n=a.context.app)?void 0:n.service(a.service).create(e,o({},t,((r={})[a.entity]=t[a.entity],r),((i={})[c]=a.core,i))))}catch(e){return Promise.reject(e)}},t.patch=function(e,t,n){void 0===n&&(n={});try{var r,i,a,c=this,u=c.context.app.get("authentication").core_path;return Promise.resolve(null==(r=c.context.app)?void 0:r.service(c.service).patch(e,t,o({},n,((i={})[c.entity]=n[c.entity],i),((a={})[u]=c.core,a))))}catch(e){return Promise.reject(e)}},t.update=function(e,t,n){void 0===n&&(n={});try{var r,i,a,c=this,u=c.context.app.get("authentication").core_path;return Promise.resolve(null==(r=c.context.app)?void 0:r.service(c.service).update(e,t,o({},n,((i={})[c.entity]=n[c.entity],i),((a={})[u]=c.core,a))))}catch(e){return Promise.reject(e)}},t.remove=function(e,t){void 0===t&&(t={});try{var n,r,i,a=this,c=a.context.app.get("authentication").core_path;return Promise.resolve(null==(n=a.context.app)?void 0:n.service(a.service).remove(e,o({},t,((r={})[a.entity]=t[a.entity],r),((i={})[c]=a.core,i))))}catch(e){return Promise.reject(e)}},t._get=function(e,t){void 0===t&&(t={});try{var n,r,i,a=this,c=a.context.app.get("authentication").core_path;return Promise.resolve(null==(n=a.context.app)?void 0:n.service(a.service)._get(e,o({},t,((r={})[a.entity]=t[a.entity],r),((i={})[c]=a.core,i))))}catch(e){return Promise.reject(e)}},t._find=function(e){void 0===e&&(e={});try{var t,n,r,i=this,a=i.context.app.get("authentication").core_path;return Promise.resolve(null==(t=i.context.app)?void 0:t.service(i.service)._find(o({},e,((n={})[i.entity]=e[i.entity],n),((r={})[a]=i.core,r))))}catch(e){return Promise.reject(e)}},t._create=function(e,t){void 0===t&&(t={});try{var n,r,i,a=this,c=a.context.app.get("authentication").core_path;return Promise.resolve(null==(n=a.context.app)?void 0:n.service(a.service)._create(e,o({},t,((r={})[a.entity]=t[a.entity],r),((i={})[c]=a.core,i))))}catch(e){return Promise.reject(e)}},t._patch=function(e,t,n){void 0===n&&(n={});try{var r,i,a,c=this,u=c.context.app.get("authentication").core_path;return Promise.resolve(null==(r=c.context.app)?void 0:r.service(c.service)._patch(e,t,o({},n,((i={})[c.entity]=n[c.entity],i),((a={})[u]=c.core,a))))}catch(e){return Promise.reject(e)}},t._update=function(e,t,n){void 0===n&&(n={});try{var r,i,a,c=this,u=c.context.app.get("authentication").core_path;return Promise.resolve(null==(r=c.context.app)?void 0:r.service(c.service)._update(e,t,o({},n,((i={})[c.entity]=n[c.entity],i),((a={})[u]=c.core,a))))}catch(e){return Promise.reject(e)}},t._remove=function(e,t){void 0===t&&(t={});try{var n,r,i,a=this,c=a.context.app.get("authentication").core_path;return Promise.resolve(null==(n=a.context.app)?void 0:n.service(a.service)._remove(e,o({},t,((r={})[a.entity]=t[a.entity],r),((i={})[c]=a.core,i))))}catch(e){return Promise.reject(e)}},e}(),b="_exists",w=function(t){var n=t.app.get("existsPath")||b;return e._get(t.params,"core."+n+"."+t.path+"."+t.id)||void 0},x=function(e,t){try{var n=w(e),r=function(){if(!n&&e.id)return Promise.resolve(new _(e.path,e,{skipJoins:!1!==(null==t?void 0:t.skipJoins)}).get(e.id,o({exists_check:!0,admin_pass:!0,skip_hooks:!0},(null==t?void 0:t.params)||{}))).then(function(e){n=e})}();return Promise.resolve(r&&r.then?r.then(function(){return n}):n)}catch(e){return Promise.reject(e)}},j=function(t,n){var r=t.app.get("existsPath")||b;return t.params=e._set(t.params,"core."+r+"."+t.path+"."+((null==n?void 0:n._id)||t.id),n),t},k=["ucan"];function S(e,t){try{var n=e()}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}function A(e,t,n){if(!e.s){if(n instanceof E){if(!n.s)return void(n.o=A.bind(null,e,t));1&t&&(t=n.s),n=n.v}if(n&&n.then)return void n.then(A.bind(null,e,t),A.bind(null,e,2));e.s=t,e.v=n;var r=e.o;r&&r(e)}}const E=/*#__PURE__*/function(){function e(){}return e.prototype.then=function(t,n){const r=new e,i=this.s;if(i){const e=1&i?t:n;if(e){try{A(r,1,e(this.v))}catch(e){A(r,2,e)}return r}return this}return this.o=function(e){try{const i=e.v;1&e.s?A(r,1,t?t(i):i):n?A(r,1,n(i)):A(r,2,i)}catch(e){A(r,2,e)}},r},e}();function T(e){return e instanceof E&&1&e.s}function O(e,t,n){var r,i,o=-1;return function a(c){try{for(;++o<e.length&&(!n||!n());)if((c=t(o))&&c.then){if(!T(c))return void c.then(a,i||(i=A.bind(null,r=new E,2)));c=c.v}r?A(r,1,c):r=c}catch(e){A(r||(r=new E),2,e)}}(),r}function U(e,t,n){var r=[];for(var i in e)r.push(i);return O(r,function(e){return t(r[e])},n)}var C="undefined"!=typeof Symbol?Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator")):"@@iterator";function I(e,t){try{var n=e()}catch(e){return t(!0,e)}return n&&n.then?n.then(t.bind(null,!1),t.bind(null,!0)):t(!1,n)}var q=function(n){try{var r,i=n.app.get("authentication"),o=e._get(n,["auth",i.entity]);o&&(n=e._set(n,[i.core_path,i.entity],o));var a=S(function(){return Promise.resolve(t.authenticate("jwt")(n).catch(function(){return n})).then(function(e){n=e})},function(){return r=1,n});return Promise.resolve(a&&a.then?a.then(function(e){return r?e:n}):r?a:n)}catch(e){return Promise.reject(e)}},$=function(n){try{var r=n.app.get("authentication"),i=e._get(n,["auth",r.entity]);return i&&(n=e._set(n,[r.core_path,r.entity],i)),Promise.resolve(t.authenticate("jwt")(n))}catch(e){return Promise.reject(e)}},N=function(t,n,r){try{return Promise.resolve(S(function(){return Promise.resolve(e.verifyUcan(t,n)).then(function(i){var a=function(a){if((null==(a=i)||!a.ok)&&n.requiredCapabilities){var c=n.requiredCapabilities.map(function(e){return"*"!==e.capability.can&&(e.capability.can.segments=["*"]),e});return r&&console.log("set new req capabilities",c,e.parseUcan(t)),Promise.resolve(e.verifyUcan(t,o({},n,{requiredCapabilities:c}))).then(function(e){i=e,r&&console.log("Second verification result:",i)})}}();return a&&a.then?a.then(function(){return i}):i})},function(e){return{ok:!1,err:[e.message]}}))}catch(e){return Promise.reject(e)}},K=function(t,n){try{var r={ok:!1,value:[]};return Promise.resolve(S(function(){var i,o=U(t,function(o){n&&console.log("or verify loop",t[o],e.parseUcan(t[o].ucan));var a=function(e){if(null==(e=r)||!e.ok){var a=t[o],c=a.ucan,u=f(a,k);return Promise.resolve(N(c,u,n)).then(function(e){r=e,n&&console.log("got in verify loop",r)})}i=1}();if(a&&a.then)return a.then(function(){})},function(){return i});return o&&o.then?o.then(function(){return r}):r},function(e){return{ok:!1,err:[e.message]}}))}catch(e){return Promise.reject(e)}},J=function(t,n,r){return function(i){try{var o,a=null==r?void 0:r.log,c=e._get(i.params,n.client_ucan),u=(null==r?void 0:r.audience)||e._get(i.params,n.ucan_aud);a&&console.log("verify against reqs",t);var s=(null==r?void 0:r.or)||[];return o=c&&("*"===s||s.includes(i.method))?function(e,n){return K((t||[]).map(function(t){return{ucan:e||c,audience:(null==n?void 0:n.aud)||u,requiredCapabilities:[t]}}),a)}:function(e,n){return N(e||c,{audience:(null==n?void 0:n.aud)||u,requiredCapabilities:t},a)},Promise.resolve(o()).then(function(t){var c,u;if(a&&console.log("first verify try",t),null!=(c=t)&&c.ok)return t;var s=((null==r?void 0:r.cap_subjects)||[]).filter(function(e){return!!e});a&&console.log("check cap_subjects",s);var l=function(){if(s){var c=(null==n?void 0:n.loginConfig)||i.app.get("authentication"),l=String(e._get(i.params,c.entity+"._id"||""));return Promise.resolve(new _(c.capability_service||"caps",i).find({query:{$limit:s.length,subject:{$in:s}},skip_hooks:!0,admin_pass:!0}).catch(function(e){return console.log("Error finding caps in ucan auth: "+e.message)})).then(function(n){var i;return a&&console.log("caps",n),function(){if(null!=n&&n.data)return function(e,t,n){if("function"==typeof e[C]){var r,i,o,a=e[C]();if(function e(c){try{for(;!((r=a.next()).done||n&&n());)if((c=t(r.value))&&c.then){if(!T(c))return void c.then(e,o||(o=A.bind(null,i=new E,2)));c=c.v}i?A(i,1,c):i=c}catch(e){A(i||(i=new E),2,e)}}(),a.return){var c=function(e){try{r.done||a.return()}catch(e){}return e};if(i&&i.then)return i.then(c,function(e){throw c(e)});c()}return i}if(!("length"in e))throw new TypeError("Object is not iterable");for(var u=[],s=0;s<e.length;s++)u.push(e[s]);return O(u,function(e){return t(u[e])},n)}(n.data,function(n){return U(n.caps||{},function(i){return a&&console.log("check cap",i,n.caps[i].logins,l),function(){if((n.caps[i].logins||[]).map(function(e){return String(e)}).includes(l)){var c=function(){var e;if(null!=r&&r.log&&console.log("tried v on cap",t),null!=(e=t)&&e.ok)return u=1,t},s=S(function(){var r=e.ucanToken(n.caps[i].ucan);a&&console.log("got ucan string",r);var c=function(){if(r)return Promise.resolve(o(r,{aud:n.did})).then(function(e){t=e,a&&console.log("tried v on cap",t)})}();if(c&&c.then)return c.then(function(){})},function(e){console.log("Error verifying ucan from cap: "+n._id+". Err:"+e.message)});return s&&s.then?s.then(c):c()}}()},function(){return i})},function(){return i})}()})}}();return l&&l.then?l.then(function(e){return u?e:t}):u?l:t})}catch(e){return Promise.reject(e)}}},R=function(t,n){var r=e.encodeKeyPair({secretKey:n.secret}).did();return Array.isArray(t)?t.map(function(t){return{capability:Array.isArray(t)?e.genCapability({with:{scheme:n.defaultScheme,hierPart:n.defaultHierPart},can:{namespace:t[0],segments:"string"==typeof t[1]?[t[1]]:t[1]}},n):e.genCapability(t,n),rootIssuer:r}}):[]},M=function(t,n){return function(r){try{var o=function(){var t,o;if(null!=(t=c)&&t.ok)return r.params.authenticated=!0,r.params.canU=!0,r;if(null!=n&&n.log&&console.log("checking special change",null==n?void 0:n.specialChange),null!=n&&n.specialChange){if("*"===n.specialChange)return r.params.canU=!0,r;if(Array.isArray(n.specialChange)&&["create","patch","update"].includes(r.method)){if(Array.isArray(r.data))throw new Error("No multi data allowed with special change");for(var u in r.data||{})if(["$set","$unset","$addToSet","$pull","$push"].includes(u)){for(var s in r.data[u]||{})if(!n.specialChange.includes(s)){var l=s.split(".");1===l.length?delete r.data[u][s]:n.specialChange.includes(l[0])||delete r.data[u][s]}}else n.specialChange.includes(u)||delete r.data[u];return r.params.canU=!0,r}}if(null!=(o=c)&&o.ok)return r.params.authenticated=!0,r.params.canU=!0,r;var f=function(e){var t;if(null!=(t=c)&&t.ok)return r.params.authenticated=!0,r.params.canU=!0,r;if(null!=n&&n.log&&console.error("Ucan capabilities requirements not met: ",c,r.type,r.path),null!=n&&n.noThrow)return r.params._no_throw_error={type:r.type,method:r.method,path:r.path},r;throw new Error("Missing proper capabilities for this action: "+r.type+": "+r.path+" - "+r.method)},h=(n||{loginPass:[[["*"],["nonExistentMethod"]]]}).loginPass,v=function(){if(null!=h&&h.length){var t,o=function(t){if(_interrupt2)return t;s&&(r=e._set(r,"data",u))},u={},s=!0,l=!1,f=!1,v=I(function(){return S(function(){var t,o,f=function(e){var t,n,r,o=2;for("undefined"!=typeof Symbol&&(n=Symbol.asyncIterator,r=Symbol.iterator);o--;){if(n&&null!=(t=e[n]))return t.call(e);if(r&&null!=(t=e[r]))return new i(t.call(e));n="@@asyncIterator",r="@@iterator"}throw new TypeError("Object is not async iterable")}(h),v=function(e,t,n){for(var r;;){var i=e();if(T(i)&&(i=i.v),!i)return o;if(i.then){r=0;break}var o=n();if(o&&o.then){if(!T(o)){r=1;break}o=o.s}if(t){var a=t();if(a&&a.then&&!T(a)){r=2;break}}}var c=new E,u=A.bind(null,c,2);return(0===r?i.then(l):1===r?o.then(s):a.then(f)).then(void 0,u),c;function s(r){o=r;do{if(t&&(a=t())&&a.then&&!T(a))return void a.then(f).then(void 0,u);if(!(i=e())||T(i)&&!i.v)return void A(c,1,o);if(i.then)return void i.then(l).then(void 0,u);T(o=n())&&(o=o.v)}while(!o||!o.then);o.then(s).then(void 0,u)}function l(e){e?(o=n())&&o.then?o.then(s).then(void 0,u):s(o):A(c,1,o)}function f(){(i=e())?i.then?i.then(l).then(void 0,u):l(i):A(c,1,o)}}(function(){function e(e){return!t&&(l=!(o=e).done)}return t?!!e(!t&&f.next()):Promise.resolve(!t&&f.next()).then(e)},function(){return!!(l=!1)},function(){var i=o.value,l=function(){if(s)return Promise.resolve(function(t){try{var i=[],o="*"===t[1],l=-1;o?l=0:(i=t[1].map(function(e){return e.split("/")[0]}),l=i.indexOf(r.method));var f=function(){if(l>-1)return Promise.resolve(x(r,{params:null==n?void 0:n.existingParams})).then(function(n){var i=!1,f=function(t,n){void 0===n&&(n="_id");var o=e._get(r.params,a.entity+"."+n);if(o&&t){var c=Array.isArray(o)?o.map(function(e){return String(e)}):[String(o)];if(Array.isArray(t))for(var u=0;u<c.length;u++){for(var s=String(c[u]),l=0;l<t.length;)String(t[l])===s?i=!0:l++;if(i)return}else if(c.includes(String(t)))return i=!0}};if(n){r=j(r,n);for(var h,v=p(t[0]||[]);!(h=v()).done;){var d=String(h.value).split("/");if(d[0].includes("*")){var y=d[0].split("*"),g=e._get(n,y[0]);if(g&&"object"==typeof g)if(Array.isArray(g))for(var m,P=p(g);!(m=P()).done&&(f(e._get(m.value,y[1]),d[1]||"_id"),!i););else for(var _ in g)if(f(e._get(g,_+"."+y[1]),d[1]||"_id"),i)break}else f(e._get(n,d[0]),d[1]||"_id")}}if(i)if(c.ok=!0,"*"===t[1]||["find","get","remove"].some(function(e){return t[1].includes(e)}))s=!1;else{var b=o?"*":t[1][l];if(b.split("/")[0]!==b)for(var w,x=p(b.split("/").slice(1).join("").split(",")||[]);!(w=x()).done;){var k=w.value,S=e._get(r.data,k);if(S)u=e._set(u,k,S);else for(var A=0,E=["$addToSet","$pull"];A<E.length;A++){var T=E[A],O=e._get(r.data,T+"."+k);O&&(u=e._set(u,T+"."+k,O))}}else s=!1}})}();return Promise.resolve(f&&f.then?f.then(function(){}):void 0)}catch(e){return Promise.reject(e)}}(i)).then(function(){});t=1}();return l&&l.then?l.then(function(){}):void 0});if(v&&v.then)return v.then(function(){})},function(e){f=!0,t=e})},function(e,n){function r(t){if(e)throw n;return n}var i=I(function(){var e=function(){if(l&&null!=_iterator.return)return Promise.resolve(_iterator.return()).then(function(){})}();if(e&&e.then)return e.then(function(){})},function(e,n){if(f)throw t;if(e)throw n;return n});return i&&i.then?i.then(r):r()});return v&&v.then?v.then(o):o(v)}}();return v&&v.then?v.then(f):f()},a=(null==n?void 0:n.loginConfig)||r.app.get("authentication"),c={ok:!1,value:[]},u=R(t,a),s=function(){if(u.length)return Promise.resolve(J(u,a,n)(r)).then(function(e){c=e});"*"!==t&&(c.ok=!0)}();return Promise.resolve(s&&s.then?s.then(o):o())}catch(e){return Promise.reject(e)}}},B=function(t,n){return function(r){try{var i,o=function(o){if(i)return o;function c(){return"*"!==t||null!=n&&n.specialChange?s?r:t?Promise.resolve(M(t,n)(r)):r:(r.params.authenticated=!!r.params[u],r)}var s=((null==n?void 0:n.adminPass)||[]).includes(r.method)&&(e._get(r.params,"admin_pass")||e._get(r.params,[a.core_path,"admin_pass"])),l=function(){if(!f&&!h)return Promise.resolve(s||null!=n&&n.specialChange?q(r):$(r)).then(function(e){r=e})}();return l&&l.then?l.then(c):c()},a=r.app.get("authentication"),c=a.core_path||"core",u=a.entity||"login",s=e._get(r.params,[c,u])||e._get(r.params,"login")||e._get(r.params.connect,u),l="string"==typeof s?s:null==s?void 0:s._id,f=!(!s||"string"!=typeof s&&!l),h=e._get(r.params,a.client_ucan||"client_ucan");null!=n&&n.log&&console.log("ucan auth","hasLogin",f,"loginId",l,"existingUcan",!!h,"core_path",c,"entity",u,"core",r.params[c],"params login",r.params.login,"required capabilities",t);var p=function(){if("$"===t||t&&"$"===t[r.method]){var e=function(e){return i=1,e};return f?e(r):Promise.resolve(q(r)).then(e)}}();return Promise.resolve(p&&p.then?p.then(o):o(p))}catch(e){return Promise.reject(e)}}};exports.AuthService=P,exports.CoreCall=_,exports.NotAuthError=m,exports.UcanStrategy=y,exports.allUcanAuth=function(t,n){return function(r){try{var i=r.app.get("authentication"),o=i.core_path||"core",a=i.entity||"login";if(!e._get(r.params,[o,a])){var c=e._get(r,["auth",a]);c&&(r=e._set(r,[o,a],c))}if("before"===r.type){var u=r.method;return Promise.resolve(t[u]||t.all?B(t[u]||t.all,n)(r):r)}return Promise.resolve(r)}catch(e){return Promise.reject(e)}}},exports.anyAuth="*",exports.bareAuth=$,exports.checkUcan=M,exports.existsPath=b,exports.getExists=w,exports.loadExists=x,exports.modelCapabilities=R,exports.noThrow="$",exports.noThrowAuth=q,exports.orVerifyLoop=K,exports.setExists=j,exports.ucanAuth=B,exports.updateUcan=function(){return function(t){try{var n=t.data,r=n.add,i=void 0===r?[]:r,a=n.remove,c=void 0===a?[]:a;if(!(null!=i&&i.length||null!=c&&c.length))throw new Error("No new capabilities passed");var u=t.app.get("authentication"),s=u.secret,l=u.ucan_aud,f=u.entity,h=u.ucan,p=e.encodeKeyPair({secretKey:s}).did(),v=e.stackAbilities([].concat(i,c));return Promise.resolve(e.verifyUcan(e._get(t.params,[f,h]),{audience:e._get(t.params,l),requiredCapabilities:v.map(function(e){return{capability:e,rootIssuer:p}})})).then(function(n){if(null==n||!n.ok)throw new Error("You don't have sufficient capabilities to grant those capabilities");var r=t.id,a=t.data.service||"logins",u=t.data.path||"ucan";return Promise.resolve(new _(a,t,{skipJoins:!0}).get(r)).then(function(n){var l=e.parseUcan(e._get(n,u)).payload,f=l.aud,h=l.att,p=l.prf,v=[].concat(h);return null!=c&&c.length&&(v=e.reduceAbilities(c,h)),null!=i&&i.length&&(v=e.stackAbilities([].concat(h,i))),Promise.resolve(e.buildUcan(o({issuer:e.encodeKeyPair({secretKey:s}),audience:f,lifetimeInSeconds:5184e3,proofs:p},t.data,{capabilities:v}))).then(function(n){var i=e.ucanToken(n);return Promise.resolve(e.validateUcan(i)).then(function(e){var n;if(!e)throw new Error("Invalid ucan generated when updating");return Promise.resolve(new _(a,t).patch(r,(n={},n[u]=i,n))).then(function(e){return t.result={raw:t.data,encoded:i,subject:e},t})})})})})}catch(e){return Promise.reject(e)}}},exports.verifyAgainstReqs=J;
1
+ var symbolUcan = require('symbol-ucan');
2
+ var authentication = require('@feathersjs/authentication');
3
+ var lt = require('long-timeout');
4
+
5
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
6
+
7
+ var lt__default = /*#__PURE__*/_interopDefaultLegacy(lt);
8
+
9
+ class NotAuthError$1 extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ }
13
+ }
14
+ const SPLIT_HEADER = /(\S+)\s+(\S+)/;
15
+ class UcanStrategy extends authentication.AuthenticationBaseStrategy {
16
+ constructor(...args) {
17
+ super(...args);
18
+ this.expirationTimers = new WeakMap();
19
+ }
20
+ setAuthentication(auth) {
21
+ // console.log('set authentication', auth);
22
+ auth.verifyAccessToken = accessToken => {
23
+ return {};
24
+ };
25
+ super.setAuthentication(auth);
26
+ }
27
+ get configuration() {
28
+ var _this$authentication;
29
+ const authConfig = ((_this$authentication = this.authentication) == null ? void 0 : _this$authentication.configuration) || {
30
+ service: undefined,
31
+ entity: undefined,
32
+ entityId: undefined
33
+ };
34
+ const config = super.configuration;
35
+ return {
36
+ service: authConfig.service,
37
+ entity: authConfig.entity,
38
+ entityId: authConfig.entityId,
39
+ header: 'Authorization',
40
+ schemes: ['Bearer', 'JWT'],
41
+ ...config
42
+ };
43
+ }
44
+ async handleConnection(event, connection, authResult) {
45
+ const isValidLogout = event === 'logout' && connection.authentication && authResult && connection.authentication.accessToken === authResult.accessToken;
46
+ const {
47
+ accessToken,
48
+ entity
49
+ } = authResult || {};
50
+ if (accessToken && event === 'login') {
51
+ const validUcan = await symbolUcan.validateUcan(accessToken).catch(err => {
52
+ console.log('Could not validate ucan in connection: ', err.message);
53
+ const errObj = {
54
+ code: 0,
55
+ message: 'Unknown Issue Validating Ucan'
56
+ };
57
+ if (err.message.indexOf('Expired.') > -1) {
58
+ errObj.code = 1;
59
+ errObj.message = 'Expired Ucan';
60
+ }
61
+ throw new Error(errObj.message);
62
+ });
63
+ const {
64
+ payload: {
65
+ exp
66
+ }
67
+ } = validUcan || {
68
+ payload: {
69
+ exp: 0
70
+ }
71
+ };
72
+ // The time (in ms) until the token expires
73
+ const duration = exp * 1000 - Date.now();
74
+ // This may have to be a `logout` event but right now we don't want
75
+ // the whole context object lingering around until the timer is gone
76
+ const timer = lt__default["default"].setTimeout(() => this.app.emit('disconnect', connection), duration);
77
+ lt__default["default"].clearTimeout(this.expirationTimers.get(connection));
78
+ this.expirationTimers.set(connection, timer);
79
+ connection.authentication = {
80
+ strategy: this.name,
81
+ accessToken
82
+ };
83
+ } else if (event === 'disconnect' || isValidLogout) {
84
+ const {
85
+ entity
86
+ } = this.configuration;
87
+ delete connection[entity];
88
+ delete connection.authentication;
89
+ lt__default["default"].clearTimeout(this.expirationTimers.get(connection));
90
+ this.expirationTimers.delete(connection);
91
+ }
92
+ }
93
+ verifyConfiguration() {
94
+ const allowedKeys = ['entity', 'entityId', 'service', 'header', 'schemes', 'audience'];
95
+ for (const key of Object.keys(this.configuration)) {
96
+ if (!allowedKeys.includes(key)) {
97
+ throw new Error(`Invalid ucanStrategy option 'authentication.${this.name}.${key}'. Did you mean to set it in 'authentication.jwtOptions'?`);
98
+ }
99
+ }
100
+ if (typeof this.configuration.header !== 'string') {
101
+ throw new Error(`The 'header' option for the ${this.name} strategy must be a string`);
102
+ }
103
+ }
104
+ // eslint-disable-next-line no-unused-vars
105
+ async getEntityQuery(_params) {
106
+ return {};
107
+ }
108
+ /**
109
+ * Return the entity for a given id
110
+ * @param id The id to use
111
+ * @param params Service call parameters
112
+ */
113
+ async getEntity(id, params) {
114
+ const entityService = this.entityService;
115
+ const {
116
+ entity
117
+ } = this.configuration;
118
+ if (entityService === null) {
119
+ throw new NotAuthError$1('Could not find entity service');
120
+ }
121
+ const query = await this.getEntityQuery(params);
122
+ const getParams = Object.assign({}, symbolUcan._unset(params, 'provider'), {
123
+ query
124
+ });
125
+ const result = await entityService.get(id, getParams);
126
+ if (!params.provider) {
127
+ return result;
128
+ }
129
+ return entityService.get(id, {
130
+ ...params,
131
+ [entity]: result
132
+ });
133
+ }
134
+ async getEntityId(authResult, _params) {
135
+ let {
136
+ query,
137
+ loginId
138
+ } = _params;
139
+ if (loginId) return loginId;else {
140
+ var _this$app;
141
+ const {
142
+ service,
143
+ core_path = 'core'
144
+ } = this.configuration;
145
+ const pms = {
146
+ query: {
147
+ ...query,
148
+ $limit: 1
149
+ },
150
+ [core_path]: {
151
+ skipJoins: true,
152
+ ..._params[core_path]
153
+ }
154
+ };
155
+ const entities = await ((_this$app = this.app) == null ? void 0 : _this$app.service(service).find({
156
+ ...pms,
157
+ skipJoins: true,
158
+ skip_hooks: true,
159
+ admin_pass: true
160
+ }));
161
+ if (entities.total) return entities.data[0]._id;else throw new NotAuthError$1('Could not find login associated with this ucan');
162
+ }
163
+ }
164
+ async authenticate(authentication, params) {
165
+ let {
166
+ accessToken,
167
+ loginId,
168
+ ucan
169
+ } = authentication;
170
+ const {
171
+ entity,
172
+ core_path
173
+ } = this.configuration;
174
+ if (!accessToken) {
175
+ if (ucan) accessToken = symbolUcan.ucanToken(ucan);else throw new NotAuthError$1('Error generating ucan');
176
+ // } else throw new NotAuthenticated('No access token');
177
+ }
178
+ //
179
+ // await verifyUcan(accessToken, {audience: ucan_audience || params.ucan_aud, requiredCapabilities})
180
+ // .catch(err => {
181
+ // console.error('error verifying ucan', err);
182
+ // throw new NotAuthenticated('Could not verify ucan: ' + err.message);
183
+ // });
184
+ const decodedUcan = await symbolUcan.validateUcan(accessToken).catch(err => {
185
+ console.log('Could not validate ucan during authentication: ', err.message);
186
+ const errObj = {
187
+ code: 0,
188
+ message: 'Unknown Issue Validating Ucan'
189
+ };
190
+ if (err.message.indexOf('Expired.') > -1) {
191
+ errObj.code = 1;
192
+ errObj.message = 'Expired Ucan';
193
+ }
194
+ throw new Error(errObj.message);
195
+ });
196
+ const result = {
197
+ accessToken,
198
+ authentication: {
199
+ strategy: 'jwt',
200
+ accessToken
201
+ }
202
+ };
203
+ if (entity === null) {
204
+ return result;
205
+ }
206
+ let value;
207
+ const coreEntity = symbolUcan._get(params, [core_path, entity]);
208
+ if (!coreEntity) {
209
+ const entityId = await this.getEntityId(result, {
210
+ ...params,
211
+ loginId,
212
+ query: {
213
+ did: decodedUcan == null ? void 0 : decodedUcan.payload.aud
214
+ }
215
+ });
216
+ value = await this.getEntity(entityId, params);
217
+ } else value = coreEntity;
218
+ return {
219
+ ...result,
220
+ [entity]: value
221
+ };
222
+ }
223
+ async parse(req) {
224
+ const {
225
+ header,
226
+ schemes
227
+ } = this.configuration;
228
+ const headerValue = req.headers && req.headers[header.toLowerCase()];
229
+ if (!headerValue || typeof headerValue !== 'string') {
230
+ return null;
231
+ }
232
+ const [, scheme, schemeValue] = headerValue.match(SPLIT_HEADER) || [];
233
+ const hasScheme = scheme && schemes.some(current => new RegExp(current, 'i').test(scheme));
234
+ if (scheme && !hasScheme) {
235
+ return null;
236
+ }
237
+ return {
238
+ strategy: this.name,
239
+ accessToken: hasScheme ? schemeValue : headerValue
240
+ };
241
+ }
242
+ }
243
+
244
+ class NotAuthError extends Error {
245
+ constructor(message) {
246
+ super(message);
247
+ }
248
+ }
249
+ class AuthService extends authentication.AuthenticationService {
250
+ constructor(app, configKey = 'authentication', opts = {}) {
251
+ const {
252
+ NotAuthenticated,
253
+ ...rest
254
+ } = opts;
255
+ super(app, configKey, rest);
256
+ this.options = void 0;
257
+ this.app = app;
258
+ this.options = {
259
+ NotAuthenticated
260
+ };
261
+ }
262
+ async create(data, params) {
263
+ var _this$options, _params;
264
+ const NotAuth = ((_this$options = this.options) == null ? void 0 : _this$options.NotAuthenticated) || NotAuthError;
265
+ const {
266
+ entity,
267
+ service,
268
+ ucan_path = 'ucan'
269
+ } = this.app.get('authentication');
270
+ const authStrategies = ((_params = params) == null ? void 0 : _params.authStrategies) || this.configuration.authStrategies;
271
+ if (!params) params = {};
272
+ if (!authStrategies.length) {
273
+ throw new NotAuth('No authentication strategies allowed for creating a JWT (`authStrategies`)');
274
+ }
275
+ const authResult = await this.authenticate(data, params, ...authStrategies).catch(err => {
276
+ throw new Error(err.message);
277
+ });
278
+ if (authResult.accessToken) {
279
+ return authResult;
280
+ }
281
+ const did = data.did || symbolUcan._get(authResult, [entity, 'did']);
282
+ let ucan = data.ucan || symbolUcan._get(authResult, [entity, 'ucan']);
283
+ if (!did) throw new Error('No did audience provided');
284
+ if (!ucan) throw new Error('No ucan provided to authentication call');
285
+ // const {secret} = this.configuration;
286
+ const validatedUcan = await symbolUcan.validateUcan(ucan).catch(err => {
287
+ console.log('Could not validate ucan creating authentication: ', err.message);
288
+ const errObj = {
289
+ code: 0,
290
+ message: 'Unknown Issue Validating Ucan'
291
+ };
292
+ if (err.message.indexOf('Expired.') > -1) {
293
+ errObj.code = 1;
294
+ errObj.message = 'Expired Ucan';
295
+ }
296
+ console.warn('Could not validate ucan creating authentication', ucan, errObj.message);
297
+ return null;
298
+ });
299
+ if (!validatedUcan) {
300
+ const parsed = symbolUcan.parseUcan(ucan);
301
+ let {
302
+ secret
303
+ } = this.app.get('authentication');
304
+ const issuer = symbolUcan.encodeKeyPair({
305
+ secretKey: secret
306
+ });
307
+ ucan = await symbolUcan.buildUcan({
308
+ audience: parsed.payload.aud,
309
+ issuer,
310
+ lifetimeInSeconds: 60 * 60 * 24 * 60,
311
+ capabilities: parsed.payload.att
312
+ });
313
+ params.admin_pass = true;
314
+ await this.app.service(service).patch(symbolUcan._get(authResult, [entity, '_id']), {
315
+ [ucan_path]: symbolUcan.ucanToken(ucan)
316
+ }, {
317
+ ...params
318
+ });
319
+ }
320
+ const accessToken = symbolUcan.ucanToken(ucan);
321
+ return {
322
+ accessToken,
323
+ ...authResult,
324
+ authentication: {
325
+ ...authResult.authentication,
326
+ payload: accessToken
327
+ }
328
+ };
329
+ }
330
+ }
331
+
332
+ class CoreCall {
333
+ constructor(service, context, coreOptions) {
334
+ var _context$params;
335
+ this.context = void 0;
336
+ this.service = void 0;
337
+ this.core = void 0;
338
+ this.entity = void 0;
339
+ this.service = service;
340
+ this.context = context;
341
+ const entity = (context.app.get('authentication') || {
342
+ entity: 'login'
343
+ }).entity || 'login';
344
+ this.entity = entity;
345
+ const core = ((_context$params = context.params) == null ? void 0 : _context$params.core) || {};
346
+ if (!core[entity]) core[entity] = context.params[entity];
347
+ this.core = {
348
+ ...core,
349
+ ...coreOptions
350
+ };
351
+ }
352
+ async get(id, params = {}) {
353
+ var _this$context$app;
354
+ const {
355
+ core_path
356
+ } = this.context.app.get('authentication');
357
+ return (_this$context$app = this.context.app) == null ? void 0 : _this$context$app.service(this.service).get(id, {
358
+ ...params,
359
+ [this.entity]: params[this.entity],
360
+ ...{
361
+ [core_path]: this.core
362
+ }
363
+ });
364
+ }
365
+ async find(params = {}) {
366
+ var _this$context$app2;
367
+ const {
368
+ core_path
369
+ } = this.context.app.get('authentication');
370
+ return (_this$context$app2 = this.context.app) == null ? void 0 : _this$context$app2.service(this.service).find({
371
+ ...params,
372
+ [this.entity]: params[this.entity],
373
+ skip_hooks: true,
374
+ admin_pass: true,
375
+ ...{
376
+ [core_path]: this.core
377
+ }
378
+ });
379
+ }
380
+ async create(data, params = {}) {
381
+ var _this$context$app3;
382
+ const {
383
+ core_path
384
+ } = this.context.app.get('authentication');
385
+ return (_this$context$app3 = this.context.app) == null ? void 0 : _this$context$app3.service(this.service).create(data, {
386
+ ...params,
387
+ [this.entity]: params[this.entity],
388
+ ...{
389
+ [core_path]: this.core
390
+ }
391
+ });
392
+ }
393
+ async patch(id, data, params = {}) {
394
+ var _this$context$app4;
395
+ const {
396
+ core_path
397
+ } = this.context.app.get('authentication');
398
+ return (_this$context$app4 = this.context.app) == null ? void 0 : _this$context$app4.service(this.service).patch(id, data, {
399
+ ...params,
400
+ [this.entity]: params[this.entity],
401
+ ...{
402
+ [core_path]: this.core
403
+ }
404
+ });
405
+ }
406
+ async update(id, data, params = {}) {
407
+ var _this$context$app5;
408
+ const {
409
+ core_path
410
+ } = this.context.app.get('authentication');
411
+ return (_this$context$app5 = this.context.app) == null ? void 0 : _this$context$app5.service(this.service).update(id, data, {
412
+ ...params,
413
+ [this.entity]: params[this.entity],
414
+ ...{
415
+ [core_path]: this.core
416
+ }
417
+ });
418
+ }
419
+ async remove(id, params = {}) {
420
+ var _this$context$app6;
421
+ const {
422
+ core_path
423
+ } = this.context.app.get('authentication');
424
+ return (_this$context$app6 = this.context.app) == null ? void 0 : _this$context$app6.service(this.service).remove(id, {
425
+ ...params,
426
+ [this.entity]: params[this.entity],
427
+ ...{
428
+ [core_path]: this.core
429
+ }
430
+ });
431
+ }
432
+ async _get(id, params = {}) {
433
+ var _this$context$app7;
434
+ const {
435
+ core_path
436
+ } = this.context.app.get('authentication');
437
+ return (_this$context$app7 = this.context.app) == null ? void 0 : _this$context$app7.service(this.service)._get(id, {
438
+ ...params,
439
+ [this.entity]: params[this.entity],
440
+ ...{
441
+ [core_path]: this.core
442
+ }
443
+ });
444
+ }
445
+ async _find(params = {}) {
446
+ var _this$context$app8;
447
+ const {
448
+ core_path
449
+ } = this.context.app.get('authentication');
450
+ return (_this$context$app8 = this.context.app) == null ? void 0 : _this$context$app8.service(this.service)._find({
451
+ ...params,
452
+ [this.entity]: params[this.entity],
453
+ ...{
454
+ [core_path]: this.core
455
+ }
456
+ });
457
+ }
458
+ async _create(data, params = {}) {
459
+ var _this$context$app9;
460
+ const {
461
+ core_path
462
+ } = this.context.app.get('authentication');
463
+ return (_this$context$app9 = this.context.app) == null ? void 0 : _this$context$app9.service(this.service)._create(data, {
464
+ ...params,
465
+ [this.entity]: params[this.entity],
466
+ ...{
467
+ [core_path]: this.core
468
+ }
469
+ });
470
+ }
471
+ async _patch(id, data, params = {}) {
472
+ var _this$context$app10;
473
+ const {
474
+ core_path
475
+ } = this.context.app.get('authentication');
476
+ return (_this$context$app10 = this.context.app) == null ? void 0 : _this$context$app10.service(this.service)._patch(id, data, {
477
+ ...params,
478
+ [this.entity]: params[this.entity],
479
+ ...{
480
+ [core_path]: this.core
481
+ }
482
+ });
483
+ }
484
+ async _update(id, data, params = {}) {
485
+ var _this$context$app11;
486
+ const {
487
+ core_path
488
+ } = this.context.app.get('authentication');
489
+ return (_this$context$app11 = this.context.app) == null ? void 0 : _this$context$app11.service(this.service)._update(id, data, {
490
+ ...params,
491
+ [this.entity]: params[this.entity],
492
+ ...{
493
+ [core_path]: this.core
494
+ }
495
+ });
496
+ }
497
+ async _remove(id, params = {}) {
498
+ var _this$context$app12;
499
+ const {
500
+ core_path
501
+ } = this.context.app.get('authentication');
502
+ return (_this$context$app12 = this.context.app) == null ? void 0 : _this$context$app12.service(this.service)._remove(id, {
503
+ ...params,
504
+ [this.entity]: params[this.entity],
505
+ ...{
506
+ [core_path]: this.core
507
+ }
508
+ });
509
+ }
510
+ }
511
+
512
+ const existsPath = '_exists';
513
+ const getExists = context => {
514
+ const path = context.app.get('existsPath') || existsPath;
515
+ return symbolUcan._get(context.params, `core.${path}.${context.path}.${context.id}`) || undefined;
516
+ };
517
+ const loadExists = async (context, options) => {
518
+ let ex = getExists(context);
519
+ if (!ex && context.id) {
520
+ ex = await new CoreCall(context.path, context, {
521
+ skipJoins: (options == null ? void 0 : options.skipJoins) !== false
522
+ }).get(context.id, {
523
+ exists_check: true,
524
+ admin_pass: true,
525
+ skip_hooks: true,
526
+ ...((options == null ? void 0 : options.params) || {})
527
+ });
528
+ }
529
+ return ex;
530
+ };
531
+ const setExists = (context, val) => {
532
+ const path = context.app.get('existsPath') || existsPath;
533
+ context.params = symbolUcan._set(context.params, `core.${path}.${context.path}.${(val == null ? void 0 : val._id) || context.id}`, val);
534
+ return context;
535
+ };
536
+
537
+ const SUPERUSER = '*';
538
+ const anyAuth = '*';
539
+ const noThrow = '$';
540
+ const noThrowAuth = async context => {
541
+ const config = context.app.get('authentication');
542
+ const entity = symbolUcan._get(context, ['auth', config.entity]);
543
+ if (entity) {
544
+ context = symbolUcan._set(context, [config.core_path, config.entity], entity);
545
+ }
546
+ try {
547
+ context = await authentication.authenticate('jwt')(context).catch(() => {
548
+ return context;
549
+ });
550
+ } catch (e) {
551
+ return context;
552
+ }
553
+ return context;
554
+ };
555
+ const bareAuth = async context => {
556
+ const config = context.app.get('authentication');
557
+ const entity = symbolUcan._get(context, ['auth', config.entity]);
558
+ if (entity) context = symbolUcan._set(context, [config.core_path, config.entity], entity);
559
+ return authentication.authenticate('jwt')(context);
560
+ };
561
+ const verifyOne = async (ucan, options, log) => {
562
+ try {
563
+ var _v;
564
+ let v = await symbolUcan.verifyUcan(ucan, options);
565
+ if (!((_v = v) != null && _v.ok) && options.requiredCapabilities) {
566
+ const newCapabilities = options.requiredCapabilities.map(a => {
567
+ if (a.capability.can !== SUPERUSER) a.capability.can.segments = ['*'];
568
+ return a;
569
+ });
570
+ if (log) console.log('set new req capabilities', newCapabilities, symbolUcan.parseUcan(ucan));
571
+ v = await symbolUcan.verifyUcan(ucan, {
572
+ ...options,
573
+ requiredCapabilities: newCapabilities
574
+ });
575
+ if (log) console.log('Second verification result:', v);
576
+ }
577
+ return v;
578
+ } catch (e) {
579
+ return {
580
+ ok: false,
581
+ err: [e.message]
582
+ };
583
+ }
584
+ };
585
+ const orVerifyLoop = async (arr, log) => {
586
+ let v = {
587
+ ok: false,
588
+ value: []
589
+ };
590
+ try {
591
+ for (const i in arr) {
592
+ var _v2;
593
+ if (log) console.log('or verify loop', arr[i], symbolUcan.parseUcan(arr[i].ucan));
594
+ if (!((_v2 = v) != null && _v2.ok)) {
595
+ const {
596
+ ucan,
597
+ ...options
598
+ } = arr[i];
599
+ v = await verifyOne(ucan, options, log);
600
+ if (log) console.log('got in verify loop', v);
601
+ } else break;
602
+ }
603
+ return v;
604
+ } catch (e) {
605
+ return {
606
+ ok: false,
607
+ err: [e.message]
608
+ };
609
+ }
610
+ };
611
+ const verifyAgainstReqs = (reqs, config, options) => {
612
+ return async context => {
613
+ var _v3;
614
+ const log = options == null ? void 0 : options.log;
615
+ const ucan = symbolUcan._get(context.params, config.client_ucan);
616
+ const audience = (options == null ? void 0 : options.audience) || symbolUcan._get(context.params, config.ucan_aud);
617
+ if (log) console.log('verify against reqs', reqs);
618
+ let vMethod;
619
+ const or = (options == null ? void 0 : options.or) || [];
620
+ if (ucan && (or === '*' || or.includes(context.method))) vMethod = (uc, methodOpts) => orVerifyLoop((reqs || []).map(a => {
621
+ return {
622
+ ucan: uc || ucan,
623
+ audience: (methodOpts == null ? void 0 : methodOpts.aud) || audience,
624
+ requiredCapabilities: [a]
625
+ };
626
+ }), log);else vMethod = (uc, methodOpts) => verifyOne(uc || ucan, {
627
+ audience: (methodOpts == null ? void 0 : methodOpts.aud) || audience,
628
+ requiredCapabilities: reqs
629
+ }, log);
630
+ let v = await vMethod();
631
+ if (log) console.log('first verify try', v);
632
+ if ((_v3 = v) != null && _v3.ok) return v;
633
+ const cs = ((options == null ? void 0 : options.cap_subjects) || []).filter(a => !!a);
634
+ if (log) console.log('check cap_subjects', cs);
635
+ if (cs) {
636
+ const configuration = (config == null ? void 0 : config.loginConfig) || context.app.get('authentication');
637
+ const loginCheckId = String(symbolUcan._get(context.params, `${configuration.entity}._id` || ''));
638
+ const caps = await new CoreCall(configuration.capability_service || 'caps', context).find({
639
+ query: {
640
+ $limit: cs.length,
641
+ subject: {
642
+ $in: cs
643
+ }
644
+ },
645
+ skip_hooks: true,
646
+ admin_pass: true
647
+ }).catch(err => console.log(`Error finding caps in ucan auth: ${err.message}`));
648
+ if (log) console.log('caps', caps);
649
+ if (caps != null && caps.data) {
650
+ for (const cap of caps.data) {
651
+ for (const k in cap.caps || {}) {
652
+ if (log) console.log('check cap', k, cap.caps[k].logins, loginCheckId);
653
+ if ((cap.caps[k].logins || []).map(a => String(a)).includes(loginCheckId)) {
654
+ var _v4;
655
+ try {
656
+ const ucanString = symbolUcan.ucanToken(cap.caps[k].ucan);
657
+ if (log) console.log('got ucan string', ucanString);
658
+ if (ucanString) {
659
+ v = await vMethod(ucanString, {
660
+ aud: cap.did
661
+ });
662
+ if (log) console.log('tried v on cap', v);
663
+ }
664
+ } catch (e) {
665
+ console.log(`Error verifying ucan from cap: ${cap._id}. Err:${e.message}`);
666
+ }
667
+ if (options != null && options.log) console.log('tried v on cap', v);
668
+ if ((_v4 = v) != null && _v4.ok) return v;
669
+ }
670
+ }
671
+ }
672
+ }
673
+ }
674
+ return v;
675
+ };
676
+ };
677
+ const modelCapabilities = (reqs, config) => {
678
+ const rootIssuer = symbolUcan.encodeKeyPair({
679
+ secretKey: config.secret
680
+ }).did();
681
+ if (!Array.isArray(reqs)) return [];
682
+ return reqs.map(a => {
683
+ return {
684
+ capability: Array.isArray(a) ? symbolUcan.genCapability({
685
+ with: {
686
+ scheme: config.defaultScheme,
687
+ hierPart: config.defaultHierPart
688
+ },
689
+ can: {
690
+ namespace: a[0],
691
+ segments: typeof a[1] === 'string' ? [a[1]] : a[1]
692
+ }
693
+ }, config) : symbolUcan.genCapability(a, config),
694
+ rootIssuer
695
+ };
696
+ });
697
+ };
698
+ const checkUcan = (requiredCapabilities, options) => {
699
+ return async context => {
700
+ var _v5;
701
+ const configuration = (options == null ? void 0 : options.loginConfig) || context.app.get('authentication');
702
+ let v = {
703
+ ok: false,
704
+ value: []
705
+ };
706
+ const reqs = modelCapabilities(requiredCapabilities, configuration);
707
+ if (reqs.length) {
708
+ v = await verifyAgainstReqs(reqs, configuration, options)(context);
709
+ /** if the anyAuth setting is used along with specialChange, a user could get through to this point despite not being authenticated, so this step does not allow a pass for anyAuth setting even though no requiredCapabilities are present - because it was intended to throw if not authenticated unless special change conditions are met */
710
+ } else if (requiredCapabilities !== '*') v.ok = true;
711
+ if ((_v5 = v) != null && _v5.ok) {
712
+ context.params.authenticated = true;
713
+ context.params.canU = true;
714
+ return context;
715
+ } else {
716
+ var _v6;
717
+ // if (!v?.ok) {
718
+ // let hasSplitNamespace = false;
719
+ // const reducedReqs: Array<RequiredCapability> = [];
720
+ // reqs.forEach((req, i) => {
721
+ // const splt = (_get<RequiredCapability, string>(req, 'capability.can.namespace') || '').split(':')
722
+ // if (splt[1]) {
723
+ // req = _set(req, 'capability.can.namespace', splt[0]);
724
+ // hasSplitNamespace = true;
725
+ // }
726
+ // reducedReqs.push(req)
727
+ // })
728
+ // if (hasSplitNamespace) v = await verifyAgainstReqs(reqs, configuration as VerifyConfig, options)(context);
729
+ // }
730
+ if (options != null && options.log) console.log('checking special change', options == null ? void 0 : options.specialChange);
731
+ if (options != null && options.specialChange) {
732
+ if (options.specialChange === anyAuth) {
733
+ context.params.canU = true;
734
+ return context;
735
+ } else if (Array.isArray(options.specialChange)) {
736
+ if (['create', 'patch', 'update'].includes(context.method)) {
737
+ if (Array.isArray(context.data)) throw new Error('No multi data allowed with special change');
738
+ for (const k in context.data || {}) {
739
+ if (['$set', '$unset', '$addToSet', '$pull', '$push'].includes(k)) {
740
+ for (const sk in context.data[k] || {}) {
741
+ if (!options.specialChange.includes(sk)) {
742
+ const spl = sk.split('.');
743
+ if (spl.length === 1) delete context.data[k][sk];else if (!options.specialChange.includes(spl[0])) delete context.data[k][sk];
744
+ }
745
+ }
746
+ } else if (!options.specialChange.includes(k)) delete context.data[k];
747
+ }
748
+ context.params.canU = true;
749
+ return context;
750
+ }
751
+ }
752
+ }
753
+ if ((_v6 = v) != null && _v6.ok) {
754
+ context.params.authenticated = true;
755
+ context.params.canU = true;
756
+ return context;
757
+ } else {
758
+ var _v7;
759
+ //If creator pass enabled, check to see if the auth login is the creator of the record
760
+ const {
761
+ loginPass
762
+ } = options || {
763
+ loginPass: [[['*'], ['nonExistentMethod']]]
764
+ };
765
+ if (loginPass != null && loginPass.length) {
766
+ //object of scrubbed data object for pass that includes only limited access or full context.data object if no limits were present
767
+ let scrubbedData = {};
768
+ //scruData defaults to true - is only set to false
769
+ let scrubData = true;
770
+ const checkLoginPass = async lpass => {
771
+ let methodsOnly = [];
772
+ const allMethods = lpass[1] === '*';
773
+ let methodIdx = -1;
774
+ if (allMethods) methodIdx = 0;else {
775
+ //separate out any field specific methods e.g. patch/name,avatar
776
+ methodsOnly = lpass[1].map(a => a.split('/')[0]);
777
+ methodIdx = methodsOnly.indexOf(context.method);
778
+ }
779
+ /**ensure loginPass is allowed for this method*/
780
+ if (methodIdx > -1) {
781
+ /**retrieve existing record to check ids for login id*/
782
+ const existing = await loadExists(context, {
783
+ params: options == null ? void 0 : options.existingParams
784
+ });
785
+ let loginOk = false;
786
+ /** function for comparing record login id with context login*/
787
+ const checkLogin = (recordLoginPassId, loginIdPath = '_id') => {
788
+ const loginCheckId = symbolUcan._get(context.params, `${configuration.entity}.${loginIdPath}`);
789
+ /**Make sure both are present to avoid pass on undefined*/
790
+ if (loginCheckId && recordLoginPassId) {
791
+ /** change login path result to array no matter what */
792
+ const checkArr = Array.isArray(loginCheckId) ? loginCheckId.map(a => String(a)) : [String(loginCheckId)];
793
+ if (Array.isArray(recordLoginPassId)) {
794
+ /**loop through to see if there is a match present use for loops for performance instead of some*/
795
+ for (let i = 0; i < checkArr.length; i++) {
796
+ const checkId = String(checkArr[i]);
797
+ for (let rl = 0; rl < recordLoginPassId.length;) {
798
+ const rlId = String(recordLoginPassId[rl]);
799
+ if (rlId === checkId) loginOk = true;else rl++;
800
+ }
801
+ if (loginOk) return;
802
+ }
803
+ } else if (checkArr.includes(String(recordLoginPassId))) {
804
+ return loginOk = true;
805
+ }
806
+ } else return;
807
+ };
808
+ if (existing) {
809
+ context = setExists(context, existing);
810
+ for (const passPath of lpass[0] || []) {
811
+ const spl = String(passPath).split('/');
812
+ if (spl[0].includes('*')) {
813
+ const spl2 = spl[0].split('*');
814
+ const obj = symbolUcan._get(existing, spl2[0]);
815
+ if (obj && typeof obj === 'object') {
816
+ if (Array.isArray(obj)) {
817
+ /** IF array, iterate through array and check the sub-path */
818
+ for (const o of obj) {
819
+ checkLogin(symbolUcan._get(o, spl2[1]), spl[1] || '_id');
820
+ if (loginOk) break;
821
+ }
822
+ } else {
823
+ /** IF object, iterate through object and check the sub-path */
824
+ for (const k in obj) {
825
+ checkLogin(symbolUcan._get(obj, `${k}.${spl2[1]}`), spl[1] || '_id');
826
+ if (loginOk) break;
827
+ }
828
+ }
829
+ }
830
+ } else checkLogin(symbolUcan._get(existing, spl[0]), spl[1] || '_id');
831
+ }
832
+ }
833
+ if (loginOk) {
834
+ v.ok = true;
835
+ /**loginPass is true - but check for granular field permissions such as patch/owner,color,status that imply limited permission*/
836
+ //TODO: possibly a throw option here. If loginPass is ok, it will go forward, but could send an empty or modified patch object
837
+ if (lpass[1] !== '*' && !['find', 'get', 'remove'].some(a => lpass[1].includes(a))) {
838
+ const currentMethod = allMethods ? '*' : lpass[1][methodIdx];
839
+ const splitMethod = currentMethod.split('/')[0];
840
+ //check if current method contains a split '/' signaling limited permission check
841
+ if (splitMethod !== currentMethod) {
842
+ //get an array of the allowed fields
843
+ const fields = currentMethod.split('/').slice(1).join('').split(',') || [];
844
+ for (const field of fields) {
845
+ const topLevel = symbolUcan._get(context.data, field);
846
+ if (topLevel) scrubbedData = symbolUcan._set(scrubbedData, field, topLevel);else {
847
+ for (const operator of ['$addToSet', '$pull']) {
848
+ const operatorLevel = symbolUcan._get(context.data, `${operator}.${field}`);
849
+ if (operatorLevel) scrubbedData = symbolUcan._set(scrubbedData, `${operator}.${field}`, operatorLevel);
850
+ }
851
+ }
852
+ }
853
+ } else scrubData = false;
854
+ } else scrubData = false;
855
+ }
856
+ }
857
+ };
858
+ for await (const lpass of loginPass) {
859
+ if (scrubData) await checkLoginPass(lpass);else break;
860
+ }
861
+ if (scrubData) context = symbolUcan._set(context, 'data', scrubbedData);
862
+ }
863
+ if ((_v7 = v) != null && _v7.ok) {
864
+ context.params.authenticated = true;
865
+ context.params.canU = true;
866
+ return context;
867
+ } else {
868
+ if (options != null && options.log) console.error('Ucan capabilities requirements not met: ', v, context.type, context.path);
869
+ if (!(options != null && options.noThrow)) throw new Error('Missing proper capabilities for this action: ' + context.type + ': ' + context.path + ' - ' + context.method);else {
870
+ context.params._no_throw_error = {
871
+ type: context.type,
872
+ method: context.method,
873
+ path: context.path
874
+ };
875
+ return context;
876
+ }
877
+ }
878
+ }
879
+ }
880
+ };
881
+ };
882
+ const ucanAuth = (requiredCapabilities, options) => {
883
+ return async context => {
884
+ const configuration = context.app.get('authentication');
885
+ const core_path = configuration.core_path || 'core';
886
+ const entity = configuration.entity || 'login';
887
+ const existingLogin = symbolUcan._get(context.params, [core_path, entity]) || symbolUcan._get(context.params, 'login') || symbolUcan._get(context.params.connection, entity);
888
+ if (existingLogin) context.params[entity] = existingLogin;
889
+ const loginId = typeof existingLogin === 'string' ? existingLogin : existingLogin == null ? void 0 : existingLogin._id;
890
+ const hasLogin = !!(existingLogin && (typeof existingLogin === 'string' || !!loginId));
891
+ const existingUcan = symbolUcan._get(context.params, configuration.client_ucan || 'client_ucan');
892
+ if (options != null && options.log) console.log('ucan auth', 'hasLogin', hasLogin, 'loginId', loginId, 'existingUcan', !!existingUcan, 'core_path', core_path, 'entity', entity, 'core', context.params[core_path], 'params login', context.params.login, 'required capabilities', requiredCapabilities);
893
+ //Below for passing through auth with no required capabilities
894
+ if (requiredCapabilities === noThrow || requiredCapabilities && requiredCapabilities[context.method] === noThrow) return hasLogin ? context : await noThrowAuth(context);
895
+ const adminPass = ((options == null ? void 0 : options.adminPass) || []).includes(context.method) && (symbolUcan._get(context.params, 'admin_pass') || symbolUcan._get(context.params, [configuration.core_path, 'admin_pass']));
896
+ // If no login is present and no client UCAN is provided, perform authentication. Otherwise, reuse existing state/ucan.
897
+ if (!hasLogin && !existingUcan) context = adminPass || options != null && options.specialChange ? await noThrowAuth(context) : await bareAuth(context);
898
+ if (requiredCapabilities === anyAuth && !(options != null && options.specialChange)) {
899
+ context.params.authenticated = !!context.params[entity];
900
+ return context;
901
+ }
902
+ if (adminPass) return context;
903
+ if (!requiredCapabilities) return context;
904
+ return await checkUcan(requiredCapabilities, options)(context);
905
+ };
906
+ };
907
+ const allUcanAuth = (methods, options) => {
908
+ return async context => {
909
+ const config = context.app.get('authentication');
910
+ // if a login is already present in params[core_path][entity], don't overwrite it
911
+ const corePath = config.core_path || 'core';
912
+ const entityKey = config.entity || 'login';
913
+ const existingLogin = symbolUcan._get(context.params, [corePath, entityKey]);
914
+ if (!existingLogin) {
915
+ const entity = symbolUcan._get(context, ['auth', entityKey]);
916
+ if (entity) context = symbolUcan._set(context, [corePath, entityKey], entity);
917
+ }
918
+ if (context.type === 'before') {
919
+ const {
920
+ method
921
+ } = context;
922
+ if (methods[method] || methods['all']) {
923
+ return await ucanAuth(methods[method] || methods['all'], options)(context);
924
+ } else return context;
925
+ } else return context;
926
+ };
927
+ };
928
+
929
+ const updateUcan = () => {
930
+ return async context => {
931
+ const {
932
+ add = [],
933
+ remove = []
934
+ } = context.data;
935
+ //ensure capabilities were passed
936
+ if (!(add != null && add.length) && !(remove != null && remove.length)) throw new Error('No new capabilities passed');
937
+ //check ability to edit the affected capabilities
938
+ const {
939
+ secret,
940
+ ucan_aud,
941
+ entity,
942
+ ucan
943
+ } = context.app.get('authentication');
944
+ const rootIssuer = symbolUcan.encodeKeyPair({
945
+ secretKey: secret
946
+ }).did();
947
+ const checkAbilities = symbolUcan.stackAbilities([...add, ...remove]);
948
+ const canEdit = await symbolUcan.verifyUcan(symbolUcan._get(context.params, [entity, ucan]), {
949
+ audience: symbolUcan._get(context.params, ucan_aud),
950
+ requiredCapabilities: checkAbilities.map(a => {
951
+ return {
952
+ //TODO: possibly READ shouldn't have the ability to allow others to READ
953
+ capability: a,
954
+ rootIssuer
955
+ };
956
+ })
957
+ });
958
+ if (!(canEdit != null && canEdit.ok)) throw new Error('You don\'t have sufficient capabilities to grant those capabilities');
959
+ //prep edited ucan
960
+ const subjectId = context.id;
961
+ const service = context.data.service || 'logins';
962
+ const path = context.data.path || 'ucan';
963
+ const subject = await new CoreCall(service, context, {
964
+ skipJoins: true
965
+ }).get(subjectId);
966
+ const decoded = symbolUcan.parseUcan(symbolUcan._get(subject, path));
967
+ const {
968
+ aud,
969
+ att,
970
+ fct,
971
+ nbf,
972
+ prf
973
+ } = decoded.payload;
974
+ let capabilities = [...att];
975
+ if (remove != null && remove.length) capabilities = symbolUcan.reduceAbilities(remove, att);
976
+ if (add != null && add.length) capabilities = symbolUcan.stackAbilities([...att, ...add]);
977
+ const raw = await symbolUcan.buildUcan({
978
+ issuer: symbolUcan.encodeKeyPair({
979
+ secretKey: secret
980
+ }),
981
+ audience: aud,
982
+ lifetimeInSeconds: 60 * 60 * 24 * 60,
983
+ proofs: prf,
984
+ ...context.data,
985
+ capabilities
986
+ });
987
+ const encoded = symbolUcan.ucanToken(raw);
988
+ const isValid = await symbolUcan.validateUcan(encoded);
989
+ if (!isValid) throw new Error('Invalid ucan generated when updating');
990
+ const patched = await new CoreCall(service, context).patch(subjectId, {
991
+ [path]: encoded
992
+ });
993
+ context.result = {
994
+ raw: context.data,
995
+ encoded,
996
+ subject: patched
997
+ };
998
+ return context;
999
+ };
1000
+ };
1001
+
1002
+ exports.AuthService = AuthService;
1003
+ exports.CoreCall = CoreCall;
1004
+ exports.NotAuthError = NotAuthError;
1005
+ exports.UcanStrategy = UcanStrategy;
1006
+ exports.allUcanAuth = allUcanAuth;
1007
+ exports.anyAuth = anyAuth;
1008
+ exports.bareAuth = bareAuth;
1009
+ exports.checkUcan = checkUcan;
1010
+ exports.existsPath = existsPath;
1011
+ exports.getExists = getExists;
1012
+ exports.loadExists = loadExists;
1013
+ exports.modelCapabilities = modelCapabilities;
1014
+ exports.noThrow = noThrow;
1015
+ exports.noThrowAuth = noThrowAuth;
1016
+ exports.orVerifyLoop = orVerifyLoop;
1017
+ exports.setExists = setExists;
1018
+ exports.ucanAuth = ucanAuth;
1019
+ exports.updateUcan = updateUcan;
1020
+ exports.verifyAgainstReqs = verifyAgainstReqs;
2
1021
  //# sourceMappingURL=index.cjs.map