@nocobase/plugin-idp-oauth 2.2.0-beta.7 → 2.2.0-beta.8

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.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import React from 'react';
10
+ export declare const DevicePage: () => React.JSX.Element;
11
+ export default DevicePage;
@@ -7,4 +7,4 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("antd"),require("react"),require("@nocobase/client"),require("react-router-dom")):"function"==typeof define&&define.amd?define("@nocobase/plugin-idp-oauth",["antd","react","@nocobase/client","react-router-dom"],t):"object"==typeof exports?exports["@nocobase/plugin-idp-oauth"]=t(require("antd"),require("react"),require("@nocobase/client"),require("react-router-dom")):e["@nocobase/plugin-idp-oauth"]=t(e.antd,e.react,e["@nocobase/client"],e["react-router-dom"])}(self,function(e,t,r,n){return function(){"use strict";var o={342:function(e){e.exports=r},59:function(t){t.exports=e},155:function(e){e.exports=t},442:function(e){e.exports=n}},i={};function a(e){var t=i[e];if(void 0!==t)return t.exports;var r=i[e]={exports:{}};return o[e](r,r.exports,a),r.exports}a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,{a:t}),t},a.d=function(e,t){for(var r in t)a.o(t,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.r=function(e){"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.g.importScripts&&(u=a.g.location+"");var u,c=a.g.document;if(!u&&c&&(c.currentScript&&"SCRIPT"===c.currentScript.tagName.toUpperCase()&&(u=c.currentScript.src),!u)){var l=c.getElementsByTagName("script");if(l.length)for(var s=l.length-1;s>-1&&(!u||!/^http(s?):/.test(u));)u=l[s--].src}if(!u)throw Error("Automatic publicPath is not supported in this browser");a.p=u.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/");var p={};return!function(){var e="",t="u">typeof document?document.currentScript:null;if(t&&t.src){var r=t.src.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"");r.indexOf("/static/plugins/@nocobase/plugin-idp-oauth/dist/client/")>=0&&(e=r.replace(/\/[^\/]+$/,"/"))}if(!e){var n=window.__webpack_public_path__||"";n&&("/"!==n.charAt(n.length-1)&&(n+="/"),e=n+"static/plugins/@nocobase/plugin-idp-oauth/dist/client/")}if(!e){var o=window.__nocobase_modern_client_prefix__||"v",i="/"+(o=String(o).replace(/^\/+|\/+$/g,"")||"v")+"/";if(!(e=window.__nocobase_public_path__||"")&&window.location&&window.location.pathname){var u=window.location.pathname||"/",c=u.indexOf(i);e=c>=0?u.slice(0,c+1):"/"}e&&(e=e.replace(RegExp("/"+o+"/?$"),"/")),e||(e="/"),"/"!==e.charAt(e.length-1)&&(e+="/"),e+="static/plugins/@nocobase/plugin-idp-oauth/dist/client/"}a.p=e}(),!function(){a.r(p),a.d(p,{default:function(){return _}});var e=a(342),t=a(59),r=a(155),n=a.n(r),o=a(442);function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}var u=function(){var e,r=(function(e){if(Array.isArray(e))return e}(e=(0,o.useSearchParams)())||function(e){var t,r,n=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var o=[],i=!0,a=!1;try{for(n=n.call(e);!(i=(t=n.next()).done)&&(o.push(t.value),1!==o.length);i=!0);}catch(e){a=!0,r=e}finally{try{i||null==n.return||n.return()}finally{if(a)throw r}}return o}}(e)||function(e){if(e){if("string"==typeof e)return i(e,1);var t=Object.prototype.toString.call(e).slice(8,-1);if("Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t)return Array.from(t);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return i(e,1)}}(e)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())[0],a=r.get("error"),u=r.get("error_description"),c=r.get("iss");return n().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},n().createElement(t.Result,{status:"error",title:a||"Authentication failed",subTitle:u||void 0}),n().createElement(t.Space,{direction:"vertical",size:"middle",style:{width:"100%"}},c?n().createElement("div",null,n().createElement(t.Typography.Text,{type:"secondary"},"Issuer"),n().createElement("div",null,n().createElement(t.Typography.Text,{code:!0},c))):null))};function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function l(e,t,r,n,o,i,a){try{var u=e[i](a),c=u.value}catch(e){r(e);return}u.done?t(c):Promise.resolve(c).then(n,o)}function s(e){return function(){var t=this,r=arguments;return new Promise(function(n,o){var i=e.apply(t,r);function a(e){l(i,n,o,a,u,"next",e)}function u(e){l(i,n,o,a,u,"throw",e)}a(void 0)})}}function f(e,t){return null!=t&&"u">typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t}function d(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r,n,o=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=o){var i=[],a=!0,u=!1;try{for(o=o.call(e);!(a=(r=o.next()).done)&&(i.push(r.value),!t||i.length!==t);a=!0);}catch(e){u=!0,n=e}finally{try{a||null==o.return||o.return()}finally{if(u)throw n}}return i}}(e,t)||function(e,t){if(e){if("string"==typeof e)return c(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if("Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r)return Array.from(r);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return c(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function y(e,t){var r,n,o,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(a,"next",{value:c(0)}),u(a,"throw",{value:c(1)}),u(a,"return",{value:c(2)}),"function"==typeof Symbol&&u(a,Symbol.iterator,{value:function(){return this}}),a;function c(u){return function(c){var l=[u,c];if(r)throw TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(i=0)),i;)try{if(r=1,n&&(o=2&l[0]?n.return:l[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,l[1])).done)return o;switch(n=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,n=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){i.label=l[1];break}if(6===l[0]&&i.label<o[1]){i.label=o[1],o=l;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(l);break}o[2]&&i.ops.pop(),i.trys.pop();continue}l=t.call(e,i)}catch(e){l=[6,e],n=0}finally{r=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}function h(e,t){return f(e,Error)?e.message:t}var m=function(){var i=(0,e.useAPIClient)(),a=(0,e.useApp)(),u=(0,o.useNavigate)(),c=(0,o.useParams)(),l=d((0,r.useState)(!0),2),p=l[0],m=l[1],v=d((0,r.useState)(null),2),b=v[0],g=v[1],w=d((0,r.useState)(null),2),x=w[0],E=w[1],S=(0,r.useMemo)(function(){return c.uid?"main"===a.name?"idpOAuth/interaction/".concat(c.uid):"__app/".concat(a.name,"/idpOAuth/interaction/").concat(c.uid):null},[a.name,c.uid]),_=(0,r.useMemo)(function(){return c.uid?"/idp-oauth/interaction/".concat(c.uid):"/signin"},[c.uid]),O=(0,r.useCallback)(function(e,t){return s(function(){var r,n,o,a,c;return y(this,function(l){switch(l.label){case 0:if(!S)return g("Invalid interaction path"),m(!1),[2];return n=i.auth.getToken(),o=i.auth.getAuthenticator()||"basic",[4,i.request({url:S,method:e,skipNotify:!0,withCredentials:!0,data:"post"===e?t:void 0,headers:n?{Authorization:"Bearer ".concat(n),"X-Authenticator":o}:void 0})];case 1:if(null==(c=(null==(a=l.sent())||null==(r=a.data)?void 0:r.data)||(null==a?void 0:a.data))?void 0:c.redirectTo)return window.location.replace(c.redirectTo),[2];if((null==c?void 0:c.prompt)!=="login")return[3,4];if(!n)return u("/signin?redirect=".concat(encodeURIComponent(_)),{replace:!0}),[2];if("get"!==e)return[3,3];return[4,O("post")];case 2:return l.sent(),[2];case 3:return u("/signin?redirect=".concat(encodeURIComponent(_)),{replace:!0}),[2];case 4:return E(c),m(!1),[2]}})})()},[i,_,S,u]),j=(0,r.useCallback)(function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return s(function(){return y(this,function(t){switch(t.label){case 0:m(!0),g(null),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,O("post",e?{cancel:1}:{submit:1})];case 2:return t.sent(),[3,4];case 3:return g(h(t.sent(),"Failed to submit interaction")),m(!1),[3,4];case 4:return[2]}})})()},[O]);return((0,r.useEffect)(function(){var e=!1;return s(function(){var t;return y(this,function(r){switch(r.label){case 0:return r.trys.push([0,2,,3]),[4,O("get")];case 1:return r.sent(),[3,3];case 2:return t=r.sent(),e||(g(h(t,"Failed to load interaction")),m(!1)),[3,3];case 3:return[2]}})})(),function(){e=!0}},[O]),(0,r.useEffect)(function(){if((null==x?void 0:x.prompt)==="consent"&&!p){var e=function(e){if(!e.defaultPrevented){var t=e.target;if(null==t||!t.closest('input, textarea, select, [contenteditable="true"]')){if("Enter"===e.key&&!e.shiftKey&&!e.ctrlKey&&!e.metaKey&&!e.altKey){var r=document.activeElement;if(f(r,HTMLButtonElement)||f(r,HTMLAnchorElement))return;e.preventDefault(),j(!1);return}"Escape"===e.key&&(e.preventDefault(),j(!0))}}};return window.addEventListener("keydown",e),function(){return window.removeEventListener("keydown",e)}}},[null==x?void 0:x.prompt,p,j]),p)?n().createElement("div",{style:{position:"fixed",inset:0,display:"flex",alignItems:"center",justifyContent:"center"}},n().createElement(t.Spin,{style:{fontSize:72}})):b?n().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},n().createElement(t.Alert,{type:"error",message:b,showIcon:!0})):(null==x?void 0:x.prompt)==="consent"?n().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},n().createElement(t.Card,null,n().createElement(t.Space,{direction:"vertical",size:"large",style:{width:"100%"}},n().createElement("div",null,n().createElement(t.Typography.Title,{level:3,style:{marginBottom:8}},"Authorize application"),n().createElement(t.Typography.Paragraph,{style:{marginBottom:0}},x.clientName||"Application"," requests access to your account.")),x.details?n().createElement(t.Alert,{type:"info",showIcon:!0,message:"Requested permissions",description:x.details}):null,n().createElement(t.Space,null,n().createElement(t.Button,{type:"primary",loading:p,onClick:function(){return j(!1)}},"Continue"),n().createElement(t.Button,{loading:p,onClick:function(){return j(!0)}},"Cancel"))))):n().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},n().createElement(t.Result,{title:"Redirecting...",subTitle:"Please wait while authorization continues."}))},v={};function b(e,t,r,n,o,i,a){try{var u=e[i](a),c=u.value}catch(e){r(e);return}u.done?t(c):Promise.resolve(c).then(n,o)}function g(e,t,r){return(g=S()?Reflect.construct:function(e,t,r){var n=[null];n.push.apply(n,t);var o=new(Function.bind.apply(e,n));return r&&x(o,r.prototype),o}).apply(null,arguments)}function w(e){return(w=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function x(e,t){return(x=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function E(e){var t="function"==typeof Map?new Map:void 0;return(E=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw 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,r)}function r(){return g(e,arguments,w(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),x(r,e)})(e)}function S(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(S=function(){return!!e})()}var _=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function r(){var e,t;if(!(this instanceof r))throw TypeError("Cannot call a class as a function");return e=r,t=arguments,e=w(e),function(e,t){var r;if(t&&("object"==((r=t)&&"u">typeof Symbol&&r.constructor===Symbol?"symbol":typeof r)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,S()?Reflect.construct(e,t||[],w(this).constructor):e.apply(this,t))}return r.prototype=Object.create(e&&e.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),e&&x(r,e),t=[{key:"load",value:function(){var e;return(e=function(){var e;return function(e,t){var r,n,o,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(a,"next",{value:c(0)}),u(a,"throw",{value:c(1)}),u(a,"return",{value:c(2)}),"function"==typeof Symbol&&u(a,Symbol.iterator,{value:function(){return this}}),a;function c(u){return function(c){var l=[u,c];if(r)throw TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(i=0)),i;)try{if(r=1,n&&(o=2&l[0]?n.return:l[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,l[1])).done)return o;switch(n=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,n=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){i.label=l[1];break}if(6===l[0]&&i.label<o[1]){i.label=o[1],o=l;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(l);break}o[2]&&i.ops.pop(),i.trys.pop();continue}l=t.call(e,i)}catch(e){l=[6,e],n=0}finally{r=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(t){return e=this,e.flowEngine.registerModels(v),e.router.add("idp-oauth.interaction",{path:"/idp-oauth/interaction/:uid",Component:m,skipAuthCheck:!0}),e.router.add("idp-oauth.error",{path:"/idp-oauth/error",Component:u,skipAuthCheck:!0}),[2]})},function(){var t=this,r=arguments;return new Promise(function(n,o){var i=e.apply(t,r);function a(e){b(i,n,o,a,u,"next",e)}function u(e){b(i,n,o,a,u,"throw",e)}a(void 0)})}).call(this)}}],function(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}(r.prototype,t),r}(E(e.Plugin))}(),p}()});
10
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("antd"),require("@nocobase/client"),require("react-router-dom"),require("@nocobase/flow-engine")):"function"==typeof define&&define.amd?define("@nocobase/plugin-idp-oauth",["react","antd","@nocobase/client","react-router-dom","@nocobase/flow-engine"],t):"object"==typeof exports?exports["@nocobase/plugin-idp-oauth"]=t(require("react"),require("antd"),require("@nocobase/client"),require("react-router-dom"),require("@nocobase/flow-engine")):e["@nocobase/plugin-idp-oauth"]=t(e.react,e.antd,e["@nocobase/client"],e["react-router-dom"],e["@nocobase/flow-engine"])}(self,function(e,t,n,r,o){return function(){"use strict";var a={342:function(e){e.exports=n},694:function(e){e.exports=o},59:function(e){e.exports=t},155:function(t){t.exports=e},442:function(e){e.exports=r}},i={};function u(e){var t=i[e];if(void 0!==t)return t.exports;var n=i[e]={exports:{}};return a[e](n,n.exports,u),n.exports}u.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(t,{a:t}),t},u.d=function(e,t){for(var n in t)u.o(t,n)&&!u.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},u.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),u.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},u.r=function(e){"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.g.importScripts&&(c=u.g.location+"");var c,l=u.g.document;if(!c&&l&&(l.currentScript&&"SCRIPT"===l.currentScript.tagName.toUpperCase()&&(c=l.currentScript.src),!c)){var s=l.getElementsByTagName("script");if(s.length)for(var p=s.length-1;p>-1&&(!c||!/^http(s?):/.test(c));)c=s[p--].src}if(!c)throw Error("Automatic publicPath is not supported in this browser");u.p=c.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/");var f={};return!function(){var e="",t="u">typeof document?document.currentScript:null;if(t&&t.src){var n=t.src.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"");n.indexOf("/static/plugins/@nocobase/plugin-idp-oauth/dist/client/")>=0&&(e=n.replace(/\/[^\/]+$/,"/"))}if(!e){var r=window.__webpack_public_path__||"";r&&("/"!==r.charAt(r.length-1)&&(r+="/"),e=r+"static/plugins/@nocobase/plugin-idp-oauth/dist/client/")}if(!e){var o=window.__nocobase_modern_client_prefix__||"v",a="/"+(o=String(o).replace(/^\/+|\/+$/g,"")||"v")+"/";if(!(e=window.__nocobase_public_path__||"")&&window.location&&window.location.pathname){var i=window.location.pathname||"/",c=i.indexOf(a);e=c>=0?i.slice(0,c+1):"/"}e&&(e=e.replace(RegExp("/"+o+"/?$"),"/")),e||(e="/"),"/"!==e.charAt(e.length-1)&&(e+="/"),e+="static/plugins/@nocobase/plugin-idp-oauth/dist/client/"}u.p=e}(),!function(){u.r(f),u.d(f,{default:function(){return B}});var e=u(342),t=u(59),n=u(155),r=u.n(n),o=u(442),a=u(694),i=JSON.parse('{"UU":"@nocobase/plugin-idp-oauth"}');function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function l(e,t,n,r,o,a,i){try{var u=e[a](i),c=u.value}catch(e){n(e);return}u.done?t(c):Promise.resolve(c).then(r,o)}function s(e){return function(){var t=this,n=arguments;return new Promise(function(r,o){var a=e.apply(t,n);function i(e){l(a,r,o,i,u,"next",e)}function u(e){l(a,r,o,i,u,"throw",e)}i(void 0)})}}function p(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,o=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=o){var a=[],i=!0,u=!1;try{for(o=o.call(e);!(i=(n=o.next()).done)&&(a.push(n.value),!t||a.length!==t);i=!0);}catch(e){u=!0,r=e}finally{try{i||null==o.return||o.return()}finally{if(u)throw r}}return a}}(e,t)||function(e,t){if(e){if("string"==typeof e)return c(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return c(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function d(e,t){var n,r,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(i,"next",{value:c(0)}),u(i,"throw",{value:c(1)}),u(i,"return",{value:c(2)}),"function"==typeof Symbol&&u(i,Symbol.iterator,{value:function(){return this}}),i;function c(u){return function(c){var l=[u,c];if(n)throw TypeError("Generator is already executing.");for(;i&&(i=0,l[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return a.label++,{value:l[1],done:!1};case 5:a.label++,r=l[1],l=[0];continue;case 7:l=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){a.label=l[1];break}if(6===l[0]&&a.label<o[1]){a.label=o[1],o=l;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(l);break}o[2]&&a.ops.pop(),a.trys.pop();continue}l=t.call(e,a)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}function y(e,t){var n;return(null!=(n=Error)&&"u">typeof Symbol&&n[Symbol.hasInstance]?!!n[Symbol.hasInstance](e):e instanceof n)?e.message:t}var m=function(){var u,c=(0,e.useAPIClient)(),l=(0,e.useApp)(),f=(0,o.useLocation)(),m=(0,o.useNavigate)(),h=(u=(0,a.useFlowEngine)(),(0,n.useCallback)(function(e,t){return u.context.t(e,function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){var r;r=n[t],t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r})}return e}({ns:[i.UU,"client"]},t))},[u])),v=p((0,o.useSearchParams)(),2),b=v[0],g=v[1],w=p((0,n.useState)(!0),2),E=w[0],x=w[1],S=p((0,n.useState)(!1),2),O=S[0],C=S[1],_=p((0,n.useState)(null),2),T=_[0],A=_[1],k=p((0,n.useState)(null),2),j=k[0],I=k[1],P=b.get("user_code")||void 0,B=(0,n.useCallback)(function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1?arguments[1]:void 0;return s(function(){var n,r;return d(this,function(o){switch(o.label){case 0:return[4,c.request({url:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return"".concat("main"===e?"":"__app/".concat(e,"/"),"idpOAuth/device/verification").concat(t)}(l.name,e),method:e?"post":"get",skipNotify:!0,params:e?void 0:{user_code:P},data:t})];case 1:return[2,(null==(r=o.sent())||null==(n=r.data)?void 0:n.data)||(null==r?void 0:r.data)]}})})()},[c,l.name,P]),q=(0,n.useCallback)(function(){return s(function(){var e;return d(this,function(t){switch(t.label){case 0:x(!0),A(null),t.label=1;case 1:return t.trys.push([1,3,4,5]),[4,B()];case 2:if(I(e=t.sent()),"login"===e.status){var n,r,o,a;return m("/signin?redirect=".concat(encodeURIComponent((n=f.pathname,r=f.search,a=(o=e.userCode||P)?"?user_code=".concat(encodeURIComponent(o)):r,"".concat(n).concat(a)))),{replace:!0}),[2]}return[3,5];case 3:return A(y(t.sent(),h("Failed to load device sign-in."))),[3,5];case 4:return x(!1),[7];case 5:return[2]}})})()},[f.pathname,f.search,m,B,h,P]);(0,n.useEffect)(function(){q()},[q]);var R=(0,n.useCallback)(function(e){var t=e.user_code,n=null==t?void 0:t.trim();n&&g({user_code:n})},[g]),M=(0,n.useCallback)(function(e){return s(function(){return d(this,function(t){switch(t.label){case 0:C(!0),A(null),t.label=1;case 1:return t.trys.push([1,3,4,5]),[4,B(e,{user_code:(null==j?void 0:j.userCode)||P})];case 2:return I(t.sent()),[3,5];case 3:return A(y(t.sent(),h("Failed to submit device sign-in."))),[3,5];case 4:return C(!1),[7];case 5:return[2]}})})()},[null==j?void 0:j.userCode,B,h,P]);if(E)return r().createElement("div",{style:{position:"fixed",inset:0,display:"flex",alignItems:"center",justifyContent:"center"}},r().createElement(t.Spin,{style:{fontSize:72}}));if(T)return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Alert,{type:"error",message:T,showIcon:!0}));if(!j||"missing_code"===j.status)return r().createElement("div",{style:{maxWidth:440,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Card,null,r().createElement(t.Space,{direction:"vertical",size:"large",style:{width:"100%"}},r().createElement("div",null,r().createElement(t.Typography.Title,{level:3,style:{marginBottom:8}},h("Device sign-in")),r().createElement(t.Typography.Paragraph,{style:{marginBottom:0}},h("Enter the code shown in your terminal to continue signing in."))),r().createElement(t.Form,{layout:"vertical",onFinish:R},r().createElement(t.Form.Item,{name:"user_code",rules:[{required:!0,message:h("Enter the device code.")}]},r().createElement(t.Input,{autoFocus:!0,size:"large",style:{textTransform:"uppercase"}})),r().createElement(t.Button,{type:"primary",htmlType:"submit",block:!0},h("Continue"))))));if("complete"===j.status)return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{status:"success",title:h("Device sign-in complete"),subTitle:h("Authorization is complete. You can return to the terminal."),extra:r().createElement(t.Button,{type:"primary",onClick:function(){return m("/")}},h("Back to home"))}));if("cancelled"===j.status)return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{status:"warning",title:h("Device sign-in cancelled"),subTitle:h("The device sign-in request was cancelled.")}));if("pending"!==j.status){var F={not_found:h("The device code was not found."),expired:h("The device code has expired."),already_used:h("The device code has already been used.")};return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{status:"error",title:h("Device sign-in failed"),subTitle:F[j.status]}))}return r().createElement("div",{style:{maxWidth:520,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Card,null,r().createElement(t.Space,{direction:"vertical",size:"large",style:{width:"100%"}},r().createElement("div",null,r().createElement(t.Typography.Title,{level:3,style:{marginBottom:8}},h("Confirm device")),r().createElement(t.Typography.Paragraph,{style:{marginBottom:0}},h("{{clientName}} is requesting access. Confirm that this code matches the one shown in your terminal.",{clientName:j.clientName||h("Application")}))),r().createElement(t.Typography.Title,{level:2,style:{margin:0,letterSpacing:"0.08em",textAlign:"center"}},j.userCode),r().createElement(t.Space,null,r().createElement(t.Button,{type:"primary",loading:O,onClick:function(){return M(":approve")}},h("Continue")),r().createElement(t.Button,{loading:O,onClick:function(){return M(":cancel")}},h("Cancel"))))))};function h(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var v=function(){var e,n=(function(e){if(Array.isArray(e))return e}(e=(0,o.useSearchParams)())||function(e){var t,n,r=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var o=[],a=!0,i=!1;try{for(r=r.call(e);!(a=(t=r.next()).done)&&(o.push(t.value),1!==o.length);a=!0);}catch(e){i=!0,n=e}finally{try{a||null==r.return||r.return()}finally{if(i)throw n}}return o}}(e)||function(e){if(e){if("string"==typeof e)return h(e,1);var t=Object.prototype.toString.call(e).slice(8,-1);if("Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t)return Array.from(t);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return h(e,1)}}(e)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())[0],a=n.get("error"),i=n.get("error_description"),u=n.get("iss");return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{status:"error",title:a||"Authentication failed",subTitle:i||void 0}),r().createElement(t.Space,{direction:"vertical",size:"middle",style:{width:"100%"}},u?r().createElement("div",null,r().createElement(t.Typography.Text,{type:"secondary"},"Issuer"),r().createElement("div",null,r().createElement(t.Typography.Text,{code:!0},u))):null))};function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function g(e,t,n,r,o,a,i){try{var u=e[a](i),c=u.value}catch(e){n(e);return}u.done?t(c):Promise.resolve(c).then(r,o)}function w(e){return function(){var t=this,n=arguments;return new Promise(function(r,o){var a=e.apply(t,n);function i(e){g(a,r,o,i,u,"next",e)}function u(e){g(a,r,o,i,u,"throw",e)}i(void 0)})}}function E(e,t){return null!=t&&"u">typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t}function x(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,o=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=o){var a=[],i=!0,u=!1;try{for(o=o.call(e);!(i=(n=o.next()).done)&&(a.push(n.value),!t||a.length!==t);i=!0);}catch(e){u=!0,r=e}finally{try{i||null==o.return||o.return()}finally{if(u)throw r}}return a}}(e,t)||function(e,t){if(e){if("string"==typeof e)return b(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return b(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function S(e,t){var n,r,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(i,"next",{value:c(0)}),u(i,"throw",{value:c(1)}),u(i,"return",{value:c(2)}),"function"==typeof Symbol&&u(i,Symbol.iterator,{value:function(){return this}}),i;function c(u){return function(c){var l=[u,c];if(n)throw TypeError("Generator is already executing.");for(;i&&(i=0,l[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return a.label++,{value:l[1],done:!1};case 5:a.label++,r=l[1],l=[0];continue;case 7:l=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){a.label=l[1];break}if(6===l[0]&&a.label<o[1]){a.label=o[1],o=l;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(l);break}o[2]&&a.ops.pop(),a.trys.pop();continue}l=t.call(e,a)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}function O(e,t){return E(e,Error)?e.message:t}var C=function(){var a=(0,e.useAPIClient)(),i=(0,e.useApp)(),u=(0,o.useNavigate)(),c=(0,o.useParams)(),l=x((0,n.useState)(!0),2),s=l[0],p=l[1],f=x((0,n.useState)(null),2),d=f[0],y=f[1],m=x((0,n.useState)(null),2),h=m[0],v=m[1],b=(0,n.useMemo)(function(){return c.uid?"main"===i.name?"idpOAuth/interaction/".concat(c.uid):"__app/".concat(i.name,"/idpOAuth/interaction/").concat(c.uid):null},[i.name,c.uid]),g=(0,n.useMemo)(function(){return c.uid?"/idp-oauth/interaction/".concat(c.uid):"/signin"},[c.uid]),C=(0,n.useCallback)(function(e,t){return w(function(){var n,r,o,i,c;return S(this,function(l){switch(l.label){case 0:if(!b)return y("Invalid interaction path"),p(!1),[2];return r=a.auth.getToken(),o=a.auth.getAuthenticator()||"basic",[4,a.request({url:b,method:e,skipNotify:!0,withCredentials:!0,data:"post"===e?t:void 0,headers:r?{Authorization:"Bearer ".concat(r),"X-Authenticator":o}:void 0})];case 1:if(null==(c=(null==(i=l.sent())||null==(n=i.data)?void 0:n.data)||(null==i?void 0:i.data))?void 0:c.redirectTo)return window.location.replace(c.redirectTo),[2];if((null==c?void 0:c.prompt)!=="login")return[3,4];if(!r)return u("/signin?redirect=".concat(encodeURIComponent(g)),{replace:!0}),[2];if("get"!==e)return[3,3];return[4,C("post")];case 2:return l.sent(),[2];case 3:return u("/signin?redirect=".concat(encodeURIComponent(g)),{replace:!0}),[2];case 4:return v(c),p(!1),[2]}})})()},[a,g,b,u]),_=(0,n.useCallback)(function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return w(function(){return S(this,function(t){switch(t.label){case 0:p(!0),y(null),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,C("post",e?{cancel:1}:{submit:1})];case 2:return t.sent(),[3,4];case 3:return y(O(t.sent(),"Failed to submit interaction")),p(!1),[3,4];case 4:return[2]}})})()},[C]);return((0,n.useEffect)(function(){var e=!1;return w(function(){var t;return S(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,C("get")];case 1:return n.sent(),[3,3];case 2:return t=n.sent(),e||(y(O(t,"Failed to load interaction")),p(!1)),[3,3];case 3:return[2]}})})(),function(){e=!0}},[C]),(0,n.useEffect)(function(){if((null==h?void 0:h.prompt)==="consent"&&!s){var e=function(e){if(!e.defaultPrevented){var t=e.target;if(null==t||!t.closest('input, textarea, select, [contenteditable="true"]')){if("Enter"===e.key&&!e.shiftKey&&!e.ctrlKey&&!e.metaKey&&!e.altKey){var n=document.activeElement;if(E(n,HTMLButtonElement)||E(n,HTMLAnchorElement))return;e.preventDefault(),_(!1);return}"Escape"===e.key&&(e.preventDefault(),_(!0))}}};return window.addEventListener("keydown",e),function(){return window.removeEventListener("keydown",e)}}},[null==h?void 0:h.prompt,s,_]),s)?r().createElement("div",{style:{position:"fixed",inset:0,display:"flex",alignItems:"center",justifyContent:"center"}},r().createElement(t.Spin,{style:{fontSize:72}})):d?r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Alert,{type:"error",message:d,showIcon:!0})):(null==h?void 0:h.prompt)==="consent"?r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Card,null,r().createElement(t.Space,{direction:"vertical",size:"large",style:{width:"100%"}},r().createElement("div",null,r().createElement(t.Typography.Title,{level:3,style:{marginBottom:8}},"Authorize application"),r().createElement(t.Typography.Paragraph,{style:{marginBottom:0}},h.clientName||"Application"," requests access to your account.")),h.details?r().createElement(t.Alert,{type:"info",showIcon:!0,message:"Requested permissions",description:h.details}):null,r().createElement(t.Space,null,r().createElement(t.Button,{type:"primary",loading:s,onClick:function(){return _(!1)}},"Continue"),r().createElement(t.Button,{loading:s,onClick:function(){return _(!0)}},"Cancel"))))):r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{title:"Redirecting...",subTitle:"Please wait while authorization continues."}))},_={};function T(e,t,n,r,o,a,i){try{var u=e[a](i),c=u.value}catch(e){n(e);return}u.done?t(c):Promise.resolve(c).then(r,o)}function A(e,t,n){return(A=P()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var o=new(Function.bind.apply(e,r));return n&&j(o,n.prototype),o}).apply(null,arguments)}function k(e){return(k=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function j(e,t){return(j=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function I(e){var t="function"==typeof Map?new Map:void 0;return(I=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw 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 A(e,arguments,k(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),j(n,e)})(e)}function P(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(P=function(){return!!e})()}var B=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function n(){var e,t;if(!(this instanceof n))throw TypeError("Cannot call a class as a function");return e=n,t=arguments,e=k(e),function(e,t){var n;if(t&&("object"==((n=t)&&"u">typeof Symbol&&n.constructor===Symbol?"symbol":typeof n)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,P()?Reflect.construct(e,t||[],k(this).constructor):e.apply(this,t))}return n.prototype=Object.create(e&&e.prototype,{constructor:{value:n,writable:!0,configurable:!0}}),e&&j(n,e),t=[{key:"load",value:function(){var e;return(e=function(){var e;return function(e,t){var n,r,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(i,"next",{value:c(0)}),u(i,"throw",{value:c(1)}),u(i,"return",{value:c(2)}),"function"==typeof Symbol&&u(i,Symbol.iterator,{value:function(){return this}}),i;function c(u){return function(c){var l=[u,c];if(n)throw TypeError("Generator is already executing.");for(;i&&(i=0,l[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return a.label++,{value:l[1],done:!1};case 5:a.label++,r=l[1],l=[0];continue;case 7:l=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){a.label=l[1];break}if(6===l[0]&&a.label<o[1]){a.label=o[1],o=l;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(l);break}o[2]&&a.ops.pop(),a.trys.pop();continue}l=t.call(e,a)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(t){return e=this,e.flowEngine.registerModels(_),e.router.add("idp-oauth.interaction",{path:"/idp-oauth/interaction/:uid",Component:C,skipAuthCheck:!0}),e.router.add("idp-oauth.device",{path:"/idpOAuth/device",Component:m,skipAuthCheck:!0}),e.router.add("idp-oauth.error",{path:"/idp-oauth/error",Component:v,skipAuthCheck:!0}),[2]})},function(){var t=this,n=arguments;return new Promise(function(r,o){var a=e.apply(t,n);function i(e){T(a,r,o,i,u,"next",e)}function u(e){T(a,r,o,i,u,"throw",e)}i(void 0)})}).call(this)}}],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,r.key,r)}}(n.prototype,t),n}(I(e.Plugin))}(),f}()});
@@ -6,5 +6,5 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- export declare function useT(): (str: string) => string;
9
+ export declare function useT(): (str: string, options?: Record<string, unknown>) => string;
10
10
  export declare function tExpr(key: string): string;
@@ -8,14 +8,14 @@
8
8
  */
9
9
 
10
10
  module.exports = {
11
+ "@nocobase/client": "2.2.0-beta.8",
11
12
  "antd": "5.24.2",
12
13
  "react": "18.2.0",
13
14
  "react-router-dom": "6.30.1",
14
- "@nocobase/client": "2.2.0-beta.7",
15
- "@nocobase/flow-engine": "2.2.0-beta.7",
16
- "@nocobase/server": "2.2.0-beta.7",
17
- "@nocobase/cache": "2.2.0-beta.7",
18
- "@nocobase/plugin-auth": "2.2.0-beta.7",
19
- "@nocobase/utils": "2.2.0-beta.7",
20
- "@nocobase/database": "2.2.0-beta.7"
15
+ "@nocobase/flow-engine": "2.2.0-beta.8",
16
+ "@nocobase/server": "2.2.0-beta.8",
17
+ "@nocobase/cache": "2.2.0-beta.8",
18
+ "@nocobase/plugin-auth": "2.2.0-beta.8",
19
+ "@nocobase/utils": "2.2.0-beta.8",
20
+ "@nocobase/database": "2.2.0-beta.8"
21
21
  };
@@ -1 +1,21 @@
1
- {}
1
+ {
2
+ "Application": "Application",
3
+ "Authorization is complete. You can return to the terminal.": "Authorization is complete. You can return to the terminal.",
4
+ "Back to home": "Back to home",
5
+ "Cancel": "Cancel",
6
+ "Confirm device": "Confirm device",
7
+ "Continue": "Continue",
8
+ "Device sign-in": "Device sign-in",
9
+ "Device sign-in cancelled": "Device sign-in cancelled",
10
+ "Device sign-in complete": "Device sign-in complete",
11
+ "Device sign-in failed": "Device sign-in failed",
12
+ "Enter the code shown in your terminal to continue signing in.": "Enter the code shown in your terminal to continue signing in.",
13
+ "Enter the device code.": "Enter the device code.",
14
+ "Failed to load device sign-in.": "Failed to load device sign-in.",
15
+ "Failed to submit device sign-in.": "Failed to submit device sign-in.",
16
+ "The device code has already been used.": "The device code has already been used.",
17
+ "The device code has expired.": "The device code has expired.",
18
+ "The device code was not found.": "The device code was not found.",
19
+ "The device sign-in request was cancelled.": "The device sign-in request was cancelled.",
20
+ "{{clientName}} is requesting access. Confirm that this code matches the one shown in your terminal.": "{{clientName}} is requesting access. Confirm that this code matches the one shown in your terminal."
21
+ }
@@ -1 +1,21 @@
1
- {}
1
+ {
2
+ "Application": "应用",
3
+ "Authorization is complete. You can return to the terminal.": "授权已完成。你可以返回终端。",
4
+ "Back to home": "返回首页",
5
+ "Cancel": "取消",
6
+ "Confirm device": "确认设备",
7
+ "Continue": "继续",
8
+ "Device sign-in": "设备登录",
9
+ "Device sign-in cancelled": "设备登录已取消",
10
+ "Device sign-in complete": "设备登录完成",
11
+ "Device sign-in failed": "设备登录失败",
12
+ "Enter the code shown in your terminal to continue signing in.": "输入终端中显示的代码以继续登录。",
13
+ "Enter the device code.": "请输入设备代码。",
14
+ "Failed to load device sign-in.": "加载设备登录失败。",
15
+ "Failed to submit device sign-in.": "提交设备登录失败。",
16
+ "The device code has already been used.": "设备代码已被使用。",
17
+ "The device code has expired.": "设备代码已过期。",
18
+ "The device code was not found.": "未找到设备代码。",
19
+ "The device sign-in request was cancelled.": "设备登录请求已取消。",
20
+ "{{clientName}} is requesting access. Confirm that this code matches the one shown in your terminal.": "{{clientName}} 正在请求访问。请确认此代码与终端中显示的代码一致。"
21
+ }
@@ -1 +1 @@
1
- {"name":"light-my-request","version":"6.6.0","description":"Fake HTTP injection library","main":"index.js","type":"commonjs","types":"types/index.d.ts","dependencies":{"cookie":"^1.0.1","process-warning":"^4.0.0","set-cookie-parser":"^2.6.0"},"devDependencies":{"@fastify/ajv-compiler":"^4.0.0","@fastify/pre-commit":"^2.1.0","@types/node":"^22.7.7","c8":"^10.1.2","end-of-stream":"^1.4.4","eslint":"^9.17.0","express":"^4.19.2","form-auto-content":"^3.2.1","form-data":"^4.0.0","formdata-node":"^6.0.3","multer":"^1.4.5-lts.1","neostandard":"^0.12.0","tinybench":"^3.0.0","tsd":"^0.31.0","undici":"^7.0.0"},"scripts":{"benchmark":"node benchmark/benchmark.js","coverage":"npm run unit -- --cov --coverage-report=html","lint":"eslint","lint:fix":"eslint --fix","test":"npm run lint && npm run test:unit && npm run test:typescript","test:typescript":"tsd","test:unit":"c8 --100 node --test"},"repository":{"type":"git","url":"git+https://github.com/fastify/light-my-request.git"},"keywords":["http","inject","fake","request","server"],"author":"Tomas Della Vedova - @delvedor (http://delved.org)","contributors":[{"name":"Matteo Collina","email":"hello@matteocollina.com"},{"name":"Manuel Spigolon","email":"behemoth89@gmail.com"},{"name":"Aras Abbasi","email":"aras.abbasi@gmail.com"},{"name":"Frazer Smith","email":"frazer.dev@icloud.com","url":"https://github.com/fdawgs"}],"license":"BSD-3-Clause","bugs":{"url":"https://github.com/fastify/light-my-request/issues"},"homepage":"https://github.com/fastify/light-my-request#readme","funding":[{"type":"github","url":"https://github.com/sponsors/fastify"},{"type":"opencollective","url":"https://opencollective.com/fastify"}],"_lastModified":"2026-06-25T01:02:59.135Z"}
1
+ {"name":"light-my-request","version":"6.6.0","description":"Fake HTTP injection library","main":"index.js","type":"commonjs","types":"types/index.d.ts","dependencies":{"cookie":"^1.0.1","process-warning":"^4.0.0","set-cookie-parser":"^2.6.0"},"devDependencies":{"@fastify/ajv-compiler":"^4.0.0","@fastify/pre-commit":"^2.1.0","@types/node":"^22.7.7","c8":"^10.1.2","end-of-stream":"^1.4.4","eslint":"^9.17.0","express":"^4.19.2","form-auto-content":"^3.2.1","form-data":"^4.0.0","formdata-node":"^6.0.3","multer":"^1.4.5-lts.1","neostandard":"^0.12.0","tinybench":"^3.0.0","tsd":"^0.31.0","undici":"^7.0.0"},"scripts":{"benchmark":"node benchmark/benchmark.js","coverage":"npm run unit -- --cov --coverage-report=html","lint":"eslint","lint:fix":"eslint --fix","test":"npm run lint && npm run test:unit && npm run test:typescript","test:typescript":"tsd","test:unit":"c8 --100 node --test"},"repository":{"type":"git","url":"git+https://github.com/fastify/light-my-request.git"},"keywords":["http","inject","fake","request","server"],"author":"Tomas Della Vedova - @delvedor (http://delved.org)","contributors":[{"name":"Matteo Collina","email":"hello@matteocollina.com"},{"name":"Manuel Spigolon","email":"behemoth89@gmail.com"},{"name":"Aras Abbasi","email":"aras.abbasi@gmail.com"},{"name":"Frazer Smith","email":"frazer.dev@icloud.com","url":"https://github.com/fdawgs"}],"license":"BSD-3-Clause","bugs":{"url":"https://github.com/fastify/light-my-request/issues"},"homepage":"https://github.com/fastify/light-my-request#readme","funding":[{"type":"github","url":"https://github.com/sponsors/fastify"},{"type":"opencollective","url":"https://opencollective.com/fastify"}],"_lastModified":"2026-06-29T01:53:47.387Z"}
@@ -1 +1 @@
1
- {"name":"ms","version":"2.1.3","description":"Tiny millisecond conversion utility","repository":"vercel/ms","main":"./index","files":["index.js"],"scripts":{"precommit":"lint-staged","lint":"eslint lib/* bin/*","test":"mocha tests.js"},"eslintConfig":{"extends":"eslint:recommended","env":{"node":true,"es6":true}},"lint-staged":{"*.js":["npm run lint","prettier --single-quote --write","git add"]},"license":"MIT","devDependencies":{"eslint":"4.18.2","expect.js":"0.3.1","husky":"0.14.3","lint-staged":"5.0.0","mocha":"4.0.1","prettier":"2.0.5"},"_lastModified":"2026-06-25T01:02:59.181Z"}
1
+ {"name":"ms","version":"2.1.3","description":"Tiny millisecond conversion utility","repository":"vercel/ms","main":"./index","files":["index.js"],"scripts":{"precommit":"lint-staged","lint":"eslint lib/* bin/*","test":"mocha tests.js"},"eslintConfig":{"extends":"eslint:recommended","env":{"node":true,"es6":true}},"lint-staged":{"*.js":["npm run lint","prettier --single-quote --write","git add"]},"license":"MIT","devDependencies":{"eslint":"4.18.2","expect.js":"0.3.1","husky":"0.14.3","lint-staged":"5.0.0","mocha":"4.0.1","prettier":"2.0.5"},"_lastModified":"2026-06-29T01:53:47.435Z"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import type { IdpOauthService } from './service';
10
+ type DeviceVerificationAction = 'show' | 'approve' | 'cancel';
11
+ type DeviceVerificationContext = {
12
+ method: string;
13
+ path: string;
14
+ query?: Record<string, unknown>;
15
+ request: {
16
+ body?: unknown;
17
+ };
18
+ status?: number;
19
+ body?: unknown;
20
+ withoutDataWrapping?: boolean;
21
+ throw: (...args: unknown[]) => never;
22
+ };
23
+ export declare function getDeviceVerificationAction(pathname: string, apiBasePath: string): DeviceVerificationAction | null;
24
+ export declare function isProviderDeviceVerificationPage(pathname: string, apiBasePath: string): boolean;
25
+ export declare function handleDeviceVerificationRequest(ctx: DeviceVerificationContext, service: IdpOauthService, apiBasePath: string): Promise<boolean>;
26
+ export {};
@@ -0,0 +1,256 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var device_verification_exports = {};
28
+ __export(device_verification_exports, {
29
+ getDeviceVerificationAction: () => getDeviceVerificationAction,
30
+ handleDeviceVerificationRequest: () => handleDeviceVerificationRequest,
31
+ isProviderDeviceVerificationPage: () => isProviderDeviceVerificationPage
32
+ });
33
+ module.exports = __toCommonJS(device_verification_exports);
34
+ var import_utils = require("./utils");
35
+ const OIDC_SCOPES = /* @__PURE__ */ new Set(["openid", "offline_access", "profile", "email"]);
36
+ function epochTime(date = Date.now()) {
37
+ return Math.floor(date / 1e3);
38
+ }
39
+ function normalizeUserCode(input) {
40
+ return String(input || "").replace(/[a-z]/g, (char) => char.toUpperCase()).replace(/\W/g, "");
41
+ }
42
+ function formatUserCode(input) {
43
+ var _a;
44
+ const userCode = normalizeUserCode(input);
45
+ return ((_a = userCode.match(/.{1,4}/g)) == null ? void 0 : _a.join("-")) || "";
46
+ }
47
+ function splitScopes(value) {
48
+ return typeof value === "string" ? value.split(/\s+/).filter(Boolean) : [];
49
+ }
50
+ function getStringArray(value) {
51
+ if (Array.isArray(value)) {
52
+ return value.filter((item) => typeof item === "string" && !!item);
53
+ }
54
+ return typeof value === "string" && value ? [value] : [];
55
+ }
56
+ function isRecordLike(value) {
57
+ return !!value && typeof value === "object" && !Array.isArray(value);
58
+ }
59
+ function getUserCode(ctx) {
60
+ var _a;
61
+ const body = isRecordLike(ctx.request.body) ? ctx.request.body : void 0;
62
+ return normalizeUserCode((body == null ? void 0 : body.user_code) || ((_a = ctx.query) == null ? void 0 : _a.user_code));
63
+ }
64
+ function getDeviceVerificationAction(pathname, apiBasePath) {
65
+ const basePath = `${apiBasePath}/idpOAuth/device/verification`;
66
+ if (pathname === basePath) {
67
+ return "show";
68
+ }
69
+ if (pathname === `${basePath}:approve`) {
70
+ return "approve";
71
+ }
72
+ if (pathname === `${basePath}:cancel`) {
73
+ return "cancel";
74
+ }
75
+ return null;
76
+ }
77
+ function isProviderDeviceVerificationPage(pathname, apiBasePath) {
78
+ const devicePath = `${apiBasePath}/idpOAuth/device`;
79
+ if (pathname === devicePath) {
80
+ return true;
81
+ }
82
+ if (!pathname.startsWith(`${devicePath}/`)) {
83
+ return false;
84
+ }
85
+ return !pathname.startsWith(`${devicePath}/auth`) && !pathname.startsWith(`${devicePath}/verification`);
86
+ }
87
+ async function findDeviceCode(provider, userCode) {
88
+ return provider.DeviceCode.findByUserCode(userCode, {
89
+ ignoreExpiration: true
90
+ });
91
+ }
92
+ async function getDeviceClient(provider, code) {
93
+ if (!code.clientId) {
94
+ return void 0;
95
+ }
96
+ return provider.Client.find(code.clientId);
97
+ }
98
+ function getClientName(client) {
99
+ return (client == null ? void 0 : client.clientName) || (client == null ? void 0 : client.clientId) || "Application";
100
+ }
101
+ async function buildDeviceState(ctx, provider, user) {
102
+ const userCode = getUserCode(ctx);
103
+ const displayUserCode = formatUserCode(userCode);
104
+ if (!userCode) {
105
+ return {
106
+ status: "missing_code"
107
+ };
108
+ }
109
+ const code = await findDeviceCode(provider, userCode);
110
+ if (!code) {
111
+ return {
112
+ status: "not_found",
113
+ userCode: displayUserCode
114
+ };
115
+ }
116
+ const client = await getDeviceClient(provider, code);
117
+ const baseState = {
118
+ userCode: displayUserCode,
119
+ clientName: getClientName(client)
120
+ };
121
+ if (code.isExpired) {
122
+ return {
123
+ ...baseState,
124
+ status: "expired"
125
+ };
126
+ }
127
+ if (code.error) {
128
+ return {
129
+ ...baseState,
130
+ status: "cancelled"
131
+ };
132
+ }
133
+ if (code.accountId) {
134
+ return {
135
+ ...baseState,
136
+ status: "complete"
137
+ };
138
+ }
139
+ if (code.inFlight || code.consumed) {
140
+ return {
141
+ ...baseState,
142
+ status: "already_used"
143
+ };
144
+ }
145
+ if (!user) {
146
+ return {
147
+ ...baseState,
148
+ status: "login"
149
+ };
150
+ }
151
+ return {
152
+ ...baseState,
153
+ status: "pending"
154
+ };
155
+ }
156
+ function getRequestedResources(params) {
157
+ return getStringArray(params.resource);
158
+ }
159
+ function splitRequestedScopes(params) {
160
+ const requestedScopes = splitScopes(params.scope);
161
+ const oidcScopes = requestedScopes.filter((scope) => OIDC_SCOPES.has(scope));
162
+ const resourceScopes = requestedScopes.filter((scope) => !OIDC_SCOPES.has(scope));
163
+ return {
164
+ requestedScopes,
165
+ oidcScopes,
166
+ resourceScopes
167
+ };
168
+ }
169
+ async function approveDeviceCode(ctx, provider, user) {
170
+ if (!(user == null ? void 0 : user.id)) {
171
+ ctx.throw(401, "Authentication required");
172
+ }
173
+ const userCode = getUserCode(ctx);
174
+ const displayUserCode = formatUserCode(userCode);
175
+ const code = userCode ? await findDeviceCode(provider, userCode) : void 0;
176
+ if (!code || code.isExpired || code.error || code.accountId || code.inFlight || code.consumed) {
177
+ return buildDeviceState(ctx, provider, user);
178
+ }
179
+ const clientId = code.clientId;
180
+ const params = code.params || {};
181
+ const { requestedScopes, oidcScopes, resourceScopes } = splitRequestedScopes(params);
182
+ const resources = getRequestedResources(params);
183
+ const grant = new provider.Grant({
184
+ accountId: String(user.id),
185
+ clientId
186
+ });
187
+ if (oidcScopes.length) {
188
+ grant.addOIDCScope(oidcScopes.join(" "));
189
+ }
190
+ if (resourceScopes.length) {
191
+ resources.forEach((resource) => grant.addResourceScope(resource, resourceScopes.join(" ")));
192
+ }
193
+ Object.assign(code, {
194
+ accountId: String(user.id),
195
+ authTime: epochTime(),
196
+ grantId: await grant.save(),
197
+ resource: resources.length > 1 ? resources : resources[0],
198
+ scope: requestedScopes.join(" ")
199
+ });
200
+ if (!resources.length) {
201
+ delete code.resource;
202
+ }
203
+ await code.save();
204
+ return {
205
+ status: "complete",
206
+ userCode: displayUserCode,
207
+ clientName: getClientName(await getDeviceClient(provider, code))
208
+ };
209
+ }
210
+ async function cancelDeviceCode(ctx, provider) {
211
+ const userCode = getUserCode(ctx);
212
+ const displayUserCode = formatUserCode(userCode);
213
+ const code = userCode ? await findDeviceCode(provider, userCode) : void 0;
214
+ if (!code || code.isExpired || code.error || code.accountId || code.inFlight || code.consumed) {
215
+ return buildDeviceState(ctx, provider);
216
+ }
217
+ Object.assign(code, {
218
+ error: "access_denied",
219
+ errorDescription: "End-User aborted interaction"
220
+ });
221
+ await code.save();
222
+ return {
223
+ status: "cancelled",
224
+ userCode: displayUserCode,
225
+ clientName: getClientName(await getDeviceClient(provider, code))
226
+ };
227
+ }
228
+ async function handleDeviceVerificationRequest(ctx, service, apiBasePath) {
229
+ const action = getDeviceVerificationAction(ctx.path, apiBasePath);
230
+ if (!action) {
231
+ return false;
232
+ }
233
+ if (action === "show" && ctx.method !== "GET" || action !== "show" && ctx.method !== "POST") {
234
+ ctx.throw(405);
235
+ }
236
+ ctx.withoutDataWrapping = true;
237
+ const provider = await service.ensureProviderForContext(ctx);
238
+ const user = await (0, import_utils.resolveCurrentUser)(ctx, service);
239
+ const body = await service.runWithProviderContext(ctx, async () => {
240
+ if (action === "approve") {
241
+ return approveDeviceCode(ctx, provider, user);
242
+ }
243
+ if (action === "cancel") {
244
+ return cancelDeviceCode(ctx, provider);
245
+ }
246
+ return buildDeviceState(ctx, provider, user);
247
+ });
248
+ ctx.body = body;
249
+ return true;
250
+ }
251
+ // Annotate the CommonJS export names for ESM import in node:
252
+ 0 && (module.exports = {
253
+ getDeviceVerificationAction,
254
+ handleDeviceVerificationRequest,
255
+ isProviderDeviceVerificationPage
256
+ });
@@ -14,6 +14,7 @@ type InteractionUser = {
14
14
  type InteractionContext = {
15
15
  req: any;
16
16
  res: any;
17
+ status?: number;
17
18
  throw: (...args: any[]) => never;
18
19
  request: {
19
20
  body?: Record<string, any>;
@@ -50,6 +50,24 @@ function shouldSkipConsent(clientId) {
50
50
  function getClientId(details) {
51
51
  return String(details.params.client_id || "");
52
52
  }
53
+ function isInteractionSessionNotFound(error) {
54
+ return error instanceof Error && error.name === "SessionNotFound" && error.error === "invalid_request";
55
+ }
56
+ async function getInteractionDetails(ctx, provider) {
57
+ try {
58
+ return await provider.interactionDetails(ctx.req, ctx.res);
59
+ } catch (error) {
60
+ if (!isInteractionSessionNotFound(error)) {
61
+ throw error;
62
+ }
63
+ ctx.status = 400;
64
+ ctx.body = {
65
+ error: "invalid_request",
66
+ error_description: "The authorization request has expired or is no longer available."
67
+ };
68
+ return null;
69
+ }
70
+ }
53
71
  async function getInteractionRedirect(ctx, provider, service, result, mergeWithLastSubmission) {
54
72
  const redirectTo = await provider.interactionResult(ctx.req, ctx.res, result, {
55
73
  mergeWithLastSubmission
@@ -130,7 +148,10 @@ async function completeConsent(ctx, provider, service, details, accountId) {
130
148
  }
131
149
  async function handleInteractionGet(ctx, provider, user, service) {
132
150
  var _a;
133
- const details = await provider.interactionDetails(ctx.req, ctx.res);
151
+ const details = await getInteractionDetails(ctx, provider);
152
+ if (!details) {
153
+ return;
154
+ }
134
155
  const interactionUser = user || await service.resolveInteractionSessionUser((_a = details.session) == null ? void 0 : _a.accountId);
135
156
  if (details.prompt.name === "login") {
136
157
  if (!interactionUser) {
@@ -165,7 +186,10 @@ async function handleInteractionGet(ctx, provider, user, service) {
165
186
  }
166
187
  async function handleInteractionPost(ctx, provider, user, service) {
167
188
  var _a, _b;
168
- const details = await provider.interactionDetails(ctx.req, ctx.res);
189
+ const details = await getInteractionDetails(ctx, provider);
190
+ if (!details) {
191
+ return;
192
+ }
169
193
  const interactionUser = user || await service.resolveInteractionSessionUser((_a = details.session) == null ? void 0 : _a.accountId);
170
194
  if ((_b = ctx.request.body) == null ? void 0 : _b.cancel) {
171
195
  ctx.body = {
@@ -31,6 +31,7 @@ __export(plugin_exports, {
31
31
  });
32
32
  module.exports = __toCommonJS(plugin_exports);
33
33
  var import_server = require("@nocobase/server");
34
+ var import_device_verification = require("./device-verification");
34
35
  var import_interaction = require("./interaction");
35
36
  var import_paths = require("./paths");
36
37
  var import_provider_dispatch = require("./provider-dispatch");
@@ -71,6 +72,17 @@ class PluginIdpOauthServer extends import_server.Plugin {
71
72
  await next();
72
73
  return;
73
74
  }
75
+ if (await (0, import_device_verification.handleDeviceVerificationRequest)(ctx, this.service, paths.apiBasePath)) {
76
+ return;
77
+ }
78
+ if ((0, import_device_verification.isProviderDeviceVerificationPage)(ctx.path, paths.apiBasePath)) {
79
+ ctx.withoutDataWrapping = true;
80
+ ctx.status = 404;
81
+ ctx.body = {
82
+ error: "not_found"
83
+ };
84
+ return;
85
+ }
74
86
  if (paths.isProviderPath(ctx.path)) {
75
87
  await (0, import_provider_dispatch.dispatchCurrentRequestToProvider)(ctx, this.service, paths.apiBasePath);
76
88
  return;
@@ -44,6 +44,7 @@ module.exports = __toCommonJS(provider_dispatch_exports);
44
44
  var import_light_my_request = __toESM(require("light-my-request"));
45
45
  var import_paths = require("./paths");
46
46
  const LOOPBACK_REDIRECT_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
47
+ const DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
47
48
  function getRequestBody(ctx) {
48
49
  const body = ctx.request.body;
49
50
  if (typeof body === "string") {
@@ -77,7 +78,12 @@ function assertRegistrationRedirectUris(ctx, pathname) {
77
78
  };
78
79
  return false;
79
80
  }
81
+ const grantTypes = Array.isArray(body == null ? void 0 : body.grant_types) ? body.grant_types.filter((grantType) => typeof grantType === "string") : [];
82
+ const isDeviceCodeOnlyClient = grantTypes.includes(DEVICE_CODE_GRANT_TYPE) && !grantTypes.includes("authorization_code");
80
83
  const redirectUris = body == null ? void 0 : body.redirect_uris;
84
+ if (isDeviceCodeOnlyClient && (redirectUris === void 0 || Array.isArray(redirectUris) && !redirectUris.length)) {
85
+ return true;
86
+ }
81
87
  if (!Array.isArray(redirectUris) || !redirectUris.length || !redirectUris.every((uri) => typeof uri === "string" && isLoopbackRedirectUri(uri))) {
82
88
  ctx.status = 400;
83
89
  ctx.body = {
@@ -152,12 +158,28 @@ function rewriteProviderUrl(ctx, service, value) {
152
158
  function rewriteProviderLocationHeader(ctx, service, location) {
153
159
  return rewriteProviderUrl(ctx, service, location);
154
160
  }
161
+ function rewriteDeviceVerificationUrl(ctx, service, value) {
162
+ const { appName, origin, issuerPath } = service.getProviderContext(ctx);
163
+ const publicOriginUrl = new URL(origin);
164
+ const publicDevicePath = service.getFrontendDevicePath(appName, issuerPath);
165
+ try {
166
+ const url = value.startsWith("/") ? new URL(value, origin) : new URL(value);
167
+ url.protocol = publicOriginUrl.protocol;
168
+ url.host = publicOriginUrl.host;
169
+ url.pathname = publicDevicePath;
170
+ return url.toString();
171
+ } catch (error) {
172
+ return value;
173
+ }
174
+ }
155
175
  function getFrontendInteractionCookiePath(originalPath) {
156
- const match = originalPath.match(/^\/(?:apps\/([^/]+)\/)?idp-oauth\/interaction\/([^/]+)$/);
157
- if (!match) {
176
+ const segments = originalPath.split("/").filter(Boolean);
177
+ const interactionIndex = segments.lastIndexOf("idp-oauth");
178
+ if (interactionIndex < 0 || segments[interactionIndex + 1] !== "interaction" || !segments[interactionIndex + 2] || segments.length !== interactionIndex + 3) {
158
179
  return void 0;
159
180
  }
160
- const [, appName, uid] = match;
181
+ const appName = segments[interactionIndex - 2] === "apps" ? segments[interactionIndex - 1] : void 0;
182
+ const uid = segments[interactionIndex + 2];
161
183
  return { appName, uid };
162
184
  }
163
185
  function rewriteProviderSetCookieHeader(ctx, service, cookie) {
@@ -188,6 +210,7 @@ function rewriteProviderJsonBody(ctx, service, body) {
188
210
  "/idpOAuth/authorize",
189
211
  "/idpOAuth/token",
190
212
  "/idpOAuth/register",
213
+ "/idpOAuth/device/auth",
191
214
  "/idpOAuth/revoke",
192
215
  "/idpOAuth/jwks",
193
216
  "/idpOAuth/me",
@@ -198,6 +221,7 @@ function rewriteProviderJsonBody(ctx, service, body) {
198
221
  "authorization_endpoint",
199
222
  "token_endpoint",
200
223
  "registration_endpoint",
224
+ "device_authorization_endpoint",
201
225
  "revocation_endpoint",
202
226
  "jwks_uri",
203
227
  "userinfo_endpoint",
@@ -216,8 +240,23 @@ function rewriteProviderJsonBody(ctx, service, body) {
216
240
  const clientId = body.client_id || registrationClientUri.pathname.split("/").pop();
217
241
  body.registration_client_uri = `${issuer}/idpOAuth/register/${clientId}`;
218
242
  }
243
+ if (typeof body.verification_uri === "string") {
244
+ body.verification_uri = rewriteDeviceVerificationUrl(ctx, service, body.verification_uri);
245
+ }
246
+ if (typeof body.verification_uri_complete === "string") {
247
+ body.verification_uri_complete = rewriteDeviceVerificationUrl(ctx, service, body.verification_uri_complete);
248
+ }
219
249
  return body;
220
250
  }
251
+ function rewriteProviderHtmlBody(ctx, service, html) {
252
+ return html.replace(/\b(action|href)=(["'])(.*?)\2/g, (match, attribute, quote, value) => {
253
+ const rewritten = rewriteProviderUrl(ctx, service, value);
254
+ if (rewritten === value) {
255
+ return match;
256
+ }
257
+ return `${attribute}=${quote}${rewritten}${quote}`;
258
+ });
259
+ }
221
260
  function rewriteProviderResponseHeaders(ctx, service, headers) {
222
261
  for (const [name, value] of Object.entries(headers)) {
223
262
  if (value === void 0) {
@@ -239,6 +278,27 @@ function rewriteProviderResponseHeaders(ctx, service, headers) {
239
278
  ctx.set(name, Array.isArray(value) ? value.map(String) : String(value));
240
279
  }
241
280
  }
281
+ function decodeProviderPayload(payload) {
282
+ if (typeof payload === "string") {
283
+ return payload;
284
+ }
285
+ if (Buffer.isBuffer(payload)) {
286
+ return payload.toString("utf8");
287
+ }
288
+ if (payload instanceof Uint8Array) {
289
+ return Buffer.from(payload).toString("utf8");
290
+ }
291
+ if (payload && typeof payload === "object" && payload.type === "Buffer" && Array.isArray(payload.data)) {
292
+ return Buffer.from(payload.data).toString("utf8");
293
+ }
294
+ return String(payload ?? "");
295
+ }
296
+ function resolveProviderPayloadBody(payload, payloadText) {
297
+ if (typeof payload === "string" || Buffer.isBuffer(payload) || payload instanceof Uint8Array) {
298
+ return payload.length ? payload : void 0;
299
+ }
300
+ return payloadText || void 0;
301
+ }
242
302
  async function dispatchToProvider(ctx, provider, pathname, service) {
243
303
  var _a, _b, _c, _d, _e, _f;
244
304
  ctx.withoutDataWrapping = true;
@@ -261,8 +321,9 @@ async function dispatchToProvider(ctx, provider, pathname, service) {
261
321
  });
262
322
  ctx.status = response.statusCode;
263
323
  rewriteProviderResponseHeaders(ctx, service, response.headers);
324
+ const responseHeaders = response.headers;
264
325
  const payload = response.rawPayload;
265
- const contentType = String(response.headers["content-type"] || "").toLowerCase();
326
+ const contentType = String(responseHeaders["content-type"] || responseHeaders["Content-Type"] || "").toLowerCase();
266
327
  (_d = (_c = ctx.logger) == null ? void 0 : _c.debug) == null ? void 0 : _d.call(_c, "idp-oauth provider response", {
267
328
  method: ctx.method,
268
329
  externalPath: ctx.path,
@@ -271,9 +332,11 @@ async function dispatchToProvider(ctx, provider, pathname, service) {
271
332
  contentType,
272
333
  location: response.headers.location
273
334
  });
274
- if (payload.length && (contentType.includes("application/json") || contentType.includes("+json"))) {
335
+ const isDiscoveryResponse = ctx.path.endsWith("/.well-known/oauth-authorization-server") || ctx.path.endsWith("/.well-known/openid-configuration") || pathname.endsWith("/.well-known/oauth-authorization-server") || pathname.endsWith("/.well-known/openid-configuration");
336
+ const payloadText = decodeProviderPayload(payload);
337
+ if (payloadText && (isDiscoveryResponse || contentType.includes("application/json") || contentType.includes("+json"))) {
275
338
  try {
276
- const body = rewriteProviderJsonBody(ctx, service, JSON.parse(payload.toString("utf8")));
339
+ const body = rewriteProviderJsonBody(ctx, service, JSON.parse(payloadText));
277
340
  ctx.body = body;
278
341
  return;
279
342
  } catch (error) {
@@ -284,11 +347,15 @@ async function dispatchToProvider(ctx, provider, pathname, service) {
284
347
  status: response.statusCode,
285
348
  contentType,
286
349
  error: error instanceof Error ? error.message : String(error),
287
- payloadPreview: payload.toString("utf8").slice(0, 500)
350
+ payloadPreview: payloadText.slice(0, 500)
288
351
  });
289
352
  }
290
353
  }
291
- ctx.body = payload.length ? payload : void 0;
354
+ if (payloadText && contentType.includes("text/html")) {
355
+ ctx.body = rewriteProviderHtmlBody(ctx, service, payloadText);
356
+ return;
357
+ }
358
+ ctx.body = resolveProviderPayloadBody(payload, payloadText);
292
359
  }
293
360
  async function dispatchCurrentRequestToProvider(ctx, service, apiBasePath) {
294
361
  const provider = await service.ensureProviderForContext(ctx);
@@ -42,6 +42,7 @@ export declare class IdpOauthService {
42
42
  private getBridgeTokenCache;
43
43
  getOrigin(ctx: any): string;
44
44
  private getApiBasePath;
45
+ private getAppPublicPath;
45
46
  private getRequestPath;
46
47
  private getAppIssuerPath;
47
48
  getIssuerPath(appName?: string, ctx?: any): string;
@@ -49,6 +50,7 @@ export declare class IdpOauthService {
49
50
  private shouldUseSubAppPublicPrefix;
50
51
  getFrontendInteractionPath(appName: string, uid: string, issuerPath?: string): string;
51
52
  getFrontendErrorPath(appName: string, issuerPath?: string): string;
53
+ getFrontendDevicePath(appName: string, issuerPath?: string): string;
52
54
  getProviderContext(ctx: any): ProviderContext;
53
55
  getCurrentProviderContext(): ProviderContext;
54
56
  runWithProviderContext<T>(ctx: any, callback: () => T): T;
@@ -69,12 +69,121 @@ const envJwksKeys = ["IDP_OAUTH_JWKS", "OAUTH_JWKS"];
69
69
  const MAX_CACHE_TTL_MS = 2147483647;
70
70
  const DEFAULT_ACCESS_TOKEN_TTL_SECONDS = Math.floor((0, import_ms.default)(String(import_plugin_auth.defaultTokenPolicyConfig.tokenExpirationTime)) / 1e3);
71
71
  const DEFAULT_SESSION_TTL_SECONDS = Math.floor((0, import_ms.default)(String(import_plugin_auth.defaultTokenPolicyConfig.sessionExpirationTime)) / 1e3);
72
+ const DEVICE_CODE_TTL_SECONDS = 10 * 60;
72
73
  function policyMillisecondsToSeconds(value, fallback) {
73
74
  if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
74
75
  return fallback;
75
76
  }
76
77
  return Math.max(1, Math.floor(value / 1e3));
77
78
  }
79
+ function escapeHtmlText(value) {
80
+ return String(value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
81
+ }
82
+ function renderDevicePage(options) {
83
+ return `<!doctype html>
84
+ <html lang="en">
85
+ <head>
86
+ <meta charset="utf-8">
87
+ <meta name="viewport" content="width=device-width, initial-scale=1">
88
+ <title>${escapeHtmlText(options.title)}</title>
89
+ <style>
90
+ * { box-sizing: border-box; }
91
+ body {
92
+ margin: 0;
93
+ min-height: 100vh;
94
+ display: grid;
95
+ place-items: center;
96
+ padding: 24px;
97
+ background: #f5f5f5;
98
+ color: rgba(0, 0, 0, 0.88);
99
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
100
+ }
101
+ main {
102
+ width: min(100%, 440px);
103
+ padding: 32px;
104
+ border: 1px solid #f0f0f0;
105
+ border-radius: 8px;
106
+ background: #fff;
107
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.08);
108
+ }
109
+ h1 { margin: 0 0 12px; font-size: 26px; line-height: 1.25; font-weight: 600; }
110
+ p { margin: 0 0 20px; color: rgba(0, 0, 0, 0.65); line-height: 1.7; }
111
+ form { display: grid; gap: 12px; }
112
+ input[type="text"] {
113
+ width: 100%;
114
+ height: 44px;
115
+ padding: 0 12px;
116
+ border: 1px solid #d9d9d9;
117
+ border-radius: 6px;
118
+ font-size: 18px;
119
+ text-align: center;
120
+ text-transform: uppercase;
121
+ letter-spacing: 0.08em;
122
+ }
123
+ button {
124
+ min-height: 40px;
125
+ border: 1px solid #1677ff;
126
+ border-radius: 6px;
127
+ background: #1677ff;
128
+ color: #fff;
129
+ cursor: pointer;
130
+ font-size: 14px;
131
+ font-weight: 500;
132
+ }
133
+ button[name="abort"] {
134
+ margin-top: 8px;
135
+ border: 0;
136
+ background: transparent;
137
+ color: rgba(0, 0, 0, 0.45);
138
+ }
139
+ code {
140
+ display: inline-block;
141
+ margin: 8px 0;
142
+ font-size: 28px;
143
+ letter-spacing: 0.08em;
144
+ color: rgba(0, 0, 0, 0.88);
145
+ }
146
+ .footer { margin-top: 20px; margin-bottom: 0; font-size: 13px; color: rgba(0, 0, 0, 0.45); }
147
+ </style>
148
+ </head>
149
+ <body>
150
+ <main>
151
+ <h1>${escapeHtmlText(options.heading)}</h1>
152
+ <p>${escapeHtmlText(options.description)}</p>
153
+ ${options.form ?? ""}
154
+ ${options.footer ? `<p class="footer">${escapeHtmlText(options.footer)}</p>` : ""}
155
+ </main>
156
+ </body>
157
+ </html>`;
158
+ }
159
+ async function renderDeviceCodeInput(ctx, form, out, error) {
160
+ const description = error || (out == null ? void 0 : out.error) ? "The code could not be verified. Check the code from your device and try again." : "Enter the code shown in your terminal to continue signing in.";
161
+ ctx.body = renderDevicePage({
162
+ title: "Device sign-in",
163
+ heading: "Device sign-in",
164
+ description,
165
+ form: `${form}<button type="submit" form="op.deviceInputForm">Continue</button>`
166
+ });
167
+ }
168
+ async function renderDeviceCodeConfirmation(ctx, form, client, _deviceInfo, userCode) {
169
+ const clientName = client.clientName || client.clientId || "Application";
170
+ ctx.body = renderDevicePage({
171
+ title: "Confirm device",
172
+ heading: "Confirm device",
173
+ description: `${clientName} is requesting access. Confirm that this code matches the one shown in your terminal.`,
174
+ form: `<p><code>${escapeHtmlText(
175
+ userCode
176
+ )}</code></p>${form}<button autofocus type="submit" form="op.deviceConfirmForm">Continue</button><button type="submit" form="op.deviceConfirmForm" value="yes" name="abort">Cancel</button>`
177
+ });
178
+ }
179
+ async function renderDeviceSuccess(ctx) {
180
+ ctx.body = renderDevicePage({
181
+ title: "Device sign-in complete",
182
+ heading: "Device sign-in complete",
183
+ description: "Authorization is complete. You can return to the terminal.",
184
+ footer: "This browser tab can be closed."
185
+ });
186
+ }
78
187
  class IdpOauthService {
79
188
  constructor(app, bridgeTokenCache) {
80
189
  this.app = app;
@@ -105,6 +214,15 @@ class IdpOauthService {
105
214
  getApiBasePath() {
106
215
  return (0, import_utils2.normalizeBasePath)(process.env.API_BASE_PATH || "/api");
107
216
  }
217
+ getAppPublicPath() {
218
+ const appPublicPath = (0, import_utils2.normalizeBasePath)(process.env.APP_PUBLIC_PATH || "");
219
+ if (appPublicPath !== "/") {
220
+ return appPublicPath;
221
+ }
222
+ const apiBasePath = this.getApiBasePath();
223
+ const inferredPublicPath = apiBasePath.endsWith("/api") ? (0, import_utils2.normalizeBasePath)(apiBasePath.slice(0, -4)) : "";
224
+ return inferredPublicPath === "/" ? "" : inferredPublicPath;
225
+ }
108
226
  getRequestPath(ctx) {
109
227
  var _a, _b;
110
228
  if (typeof ((_a = ctx == null ? void 0 : ctx.req) == null ? void 0 : _a.originalUrl) === "string") {
@@ -154,16 +272,25 @@ class IdpOauthService {
154
272
  return issuerPath !== this.getApiBasePath();
155
273
  }
156
274
  getFrontendInteractionPath(appName, uid, issuerPath = this.getIssuerPath(appName)) {
275
+ const appPublicPath = this.getAppPublicPath();
157
276
  if (!this.shouldUseSubAppPublicPrefix(appName, issuerPath)) {
158
- return `/idp-oauth/interaction/${uid}`;
277
+ return `${appPublicPath}/idp-oauth/interaction/${uid}`;
159
278
  }
160
- return `/apps/${appName}/idp-oauth/interaction/${uid}`;
279
+ return `${appPublicPath}/apps/${appName}/idp-oauth/interaction/${uid}`;
161
280
  }
162
281
  getFrontendErrorPath(appName, issuerPath = this.getIssuerPath(appName)) {
282
+ const appPublicPath = this.getAppPublicPath();
283
+ if (!this.shouldUseSubAppPublicPrefix(appName, issuerPath)) {
284
+ return `${appPublicPath}/idp-oauth/error`;
285
+ }
286
+ return `${appPublicPath}/apps/${appName}/idp-oauth/error`;
287
+ }
288
+ getFrontendDevicePath(appName, issuerPath = this.getIssuerPath(appName)) {
289
+ const appPublicPath = this.getAppPublicPath();
163
290
  if (!this.shouldUseSubAppPublicPrefix(appName, issuerPath)) {
164
- return "/idp-oauth/error";
291
+ return `${appPublicPath}/idpOAuth/device`;
165
292
  }
166
- return `/apps/${appName}/idp-oauth/error`;
293
+ return `${appPublicPath}/apps/${appName}/idpOAuth/device`;
167
294
  }
168
295
  getProviderContext(ctx) {
169
296
  var _a;
@@ -574,6 +701,8 @@ class IdpOauthService {
574
701
  routes: {
575
702
  authorization: "/idpOAuth/authorize",
576
703
  token: "/idpOAuth/token",
704
+ code_verification: "/idpOAuth/device",
705
+ device_authorization: "/idpOAuth/device/auth",
577
706
  jwks: "/idpOAuth/jwks",
578
707
  registration: "/idpOAuth/register",
579
708
  revocation: "/idpOAuth/revoke",
@@ -582,6 +711,12 @@ class IdpOauthService {
582
711
  end_session: "/idpOAuth/end-session"
583
712
  },
584
713
  features: {
714
+ deviceFlow: {
715
+ enabled: true,
716
+ userCodeInputSource: renderDeviceCodeInput,
717
+ userCodeConfirmSource: renderDeviceCodeConfirmation,
718
+ successSource: renderDeviceSuccess
719
+ },
585
720
  devInteractions: { enabled: false },
586
721
  registration: { enabled: true },
587
722
  revocation: { enabled: true },
@@ -619,6 +754,7 @@ class IdpOauthService {
619
754
  ttl: {
620
755
  AccessToken: accessTokenTtl,
621
756
  AuthorizationCode: 60,
757
+ DeviceCode: DEVICE_CODE_TTL_SECONDS,
622
758
  Grant: sessionTtl,
623
759
  IdToken: 60 * 60,
624
760
  RefreshToken: sessionTtl,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/plugin-idp-oauth",
3
- "version": "2.2.0-beta.7",
3
+ "version": "2.2.0-beta.8",
4
4
  "main": "dist/server/index.js",
5
5
  "displayName": "IdP: OAuth",
6
6
  "displayName.zh-CN": "IdP: OAuth",
@@ -22,5 +22,5 @@
22
22
  "keywords": [
23
23
  "Authentication"
24
24
  ],
25
- "gitHead": "e6a3fa8963a73cd9ddfc1273d71b0012483e1ad8"
25
+ "gitHead": "fa2502c1e9faf6d74b3f51b42dbc6546638d46af"
26
26
  }