@tachybase/module-auth 0.23.58 → 1.0.6
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/dist/client/index.js +5 -5
- package/dist/client/interceptors.d.ts +5 -0
- package/dist/client/locale/index.d.ts +1 -0
- package/dist/client/settings/token-policy/components.d.ts +7 -0
- package/dist/client/settings/token-policy/hooks.d.ts +16 -0
- package/dist/client/settings/token-policy/index.d.ts +1 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.js +39 -0
- package/dist/externalVersion.js +12 -9
- package/dist/locale/en-US.json +23 -1
- package/dist/locale/zh-CN.json +22 -1
- package/dist/node_modules/cron/package.json +1 -1
- package/dist/node_modules/ms/index.js +1 -0
- package/dist/node_modules/ms/package.json +1 -0
- package/dist/server/basic-auth.js +3 -3
- package/dist/server/collections/authenticators.js +0 -8
- package/dist/server/collections/issued-tokens.d.ts +2 -0
- package/dist/server/collections/issued-tokens.js +60 -0
- package/dist/server/collections/token-poilcy-config.d.ts +2 -0
- package/dist/server/collections/token-poilcy-config.js +47 -0
- package/dist/server/collections/users-authenticators.js +10 -1
- package/dist/server/locale/en-US.d.ts +1 -0
- package/dist/server/locale/en-US.js +2 -1
- package/dist/server/locale/zh-CN.d.ts +1 -0
- package/dist/server/locale/zh-CN.js +2 -1
- package/dist/server/migrations/20250318163707-create-token-policy.d.ts +6 -0
- package/dist/server/migrations/20250318163707-create-token-policy.js +52 -0
- package/dist/server/plugin.js +133 -26
- package/dist/server/token-controller.d.ts +32 -0
- package/dist/server/token-controller.js +139 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.js +15 -0
- package/package.json +15 -11
package/dist/client/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(u,r){typeof exports=="object"&&typeof module!="undefined"?r(exports,require("@tachybase/client"),require("@tachybase/utils/client"),require("react/jsx-runtime"),require("react"),require("react-router-dom"),require("@tachybase/schema"),require("react-i18next"),require("antd"),require("@ant-design/icons")):typeof define=="function"&&define.amd?define(["exports","@tachybase/client","@tachybase/utils/client","react/jsx-runtime","react","react-router-dom","@tachybase/schema","react-i18next","antd","@ant-design/icons"],r):(u=typeof globalThis!="undefined"?globalThis:u||self,r(u["@tachybase/module-auth"]={},u["@tachybase/client"],u["@tachybase/utils"],u.jsxRuntime,u.react,u["react-router-dom"],u["@tachybase/schema"],u["react-i18next"],u.antd,u["@ant-design/icons"]))})(this,function(u,r,m,c,l,T,f,w,d,k){"use strict";var Tn=Object.defineProperty,vn=Object.defineProperties;var Sn=Object.getOwnPropertyDescriptors;var z=Object.getOwnPropertySymbols;var Se=Object.prototype.hasOwnProperty,Ce=Object.prototype.propertyIsEnumerable;var ve=(u,r,m)=>r in u?Tn(u,r,{enumerable:!0,configurable:!0,writable:!0,value:m}):u[r]=m,C=(u,r)=>{for(var m in r||(r={}))Se.call(r,m)&&ve(u,m,r[m]);if(z)for(var m of z(r))Ce.call(r,m)&&ve(u,m,r[m]);return u},Y=(u,r)=>vn(u,Sn(r));var Ae=(u,r)=>{var m={};for(var c in u)Se.call(u,c)&&r.indexOf(c)<0&&(m[c]=u[c]);if(u!=null&&z)for(var c of z(u))r.indexOf(c)<0&&Ce.call(u,c)&&(m[c]=u[c]);return m};var A=(u,r,m)=>new Promise((c,l)=>{var T=d=>{try{w(m.next(d))}catch(k){l(k)}},f=d=>{try{w(m.throw(d))}catch(k){l(k)}},w=d=>d.done?c(d.value):Promise.resolve(d.value).then(T,f);w((m=m.apply(u,r)).next())});const we="Email/Password",Ee=e=>{const t=T.useLocation(),n=r.useAPIClient();return l.useEffect(()=>{const o=new URLSearchParams(t.search),i=o.get("authenticator"),s=o.get("token");s&&(n.auth.setToken(s),n.auth.setAuthenticator(i))}),c.jsx(c.Fragment,{children:e.children})},E="auth";function v(){return w.useTranslation([E,"core"],{nsMode:"fallback"})}const j=e=>r.tval(e,{ns:E}),B=l.createContext([]);B.displayName="AuthenticatorsContext";const Z=e=>l.useContext(B).find(n=>n.name===e);function Fe(e){var s;const{data:t}=r.useSystemSettings(),n=r.useAPIClient(),{data:o=[],error:i}=r.useRequest(()=>n.resource("authenticators").publicList().then(a=>{var p;return((p=a==null?void 0:a.data)==null?void 0:p.data)||[]}));if(i)throw i;return c.jsxs("div",{style:{maxWidth:320,margin:"0 auto",paddingTop:"20vh"},children:[c.jsx("h1",{children:(s=t==null?void 0:t.data)==null?void 0:s.title}),c.jsx(B.Provider,{value:o,children:c.jsx(T.Outlet,{})}),c.jsx("div",{className:r.css`
|
|
2
2
|
position: absolute;
|
|
3
3
|
bottom: 24px;
|
|
4
4
|
width: 100%;
|
|
5
5
|
left: 0;
|
|
6
6
|
text-align: center;
|
|
7
|
-
`,children:
|
|
7
|
+
`,children:c.jsx(r.PoweredBy,{})})]})}const Ie=()=>{var o;const t=r.usePlugin(I).authTypes.getEntities(),n={};for(const[i,s]of t)(o=s.components)!=null&&o.SignInForm&&(n[i]=s.components.SignInForm);return n},ke=(e=[])=>{var s;const n=r.usePlugin(I).authTypes.getEntities(),o={};for(const[a,p]of n)(s=p.components)!=null&&s.SignInButton&&(o[a]=p.components.SignInButton);const i=Object.keys(o);return e.filter(a=>i.includes(a.authType)).map((a,p)=>l.createElement(o[a.authType],{key:p,authenticator:a}))},Pe=()=>{const{t:e}=v();r.useCurrentDocumentTitle("Signin"),r.useViewport();const t=Ie(),n=l.useContext(B),o=ke(n);if(!n.length)return c.jsx("div",{style:{color:"#ccc"},children:e("No authentication methods available.")});const i=n.map(s=>{const a=t[s.authType];if(!a)return;const p=`${e("Sign-in")} (${e(s.authTypeTitle||s.authType)})`;return C({component:l.createElement(a,{authenticator:s}),tabTitle:s.title||s.name==="basic"?p:`${e(s.name)}`},s)}).filter(s=>s);return c.jsxs(d.Space,{direction:"vertical",className:r.css`
|
|
8
8
|
display: flex;
|
|
9
|
-
`,children:[
|
|
9
|
+
`,children:[i.length>1?c.jsx(d.Tabs,{items:i.map(s=>({label:s.tabTitle,key:s.name,children:s.component}))}):i.length?c.jsx("div",{children:i[0].component}):c.jsx(c.Fragment,{}),c.jsx(d.Space,{direction:"vertical",className:r.css`
|
|
10
10
|
display: flex;
|
|
11
|
-
`,children:
|
|
11
|
+
`,children:o})]})},Oe=l.createContext({});Oe.displayName="SignupPageContext";const ne=()=>{var o;const t=r.usePlugin(I).authTypes.getEntities(),n={};for(const[i,s]of t)(o=s.components)!=null&&o.SignUpForm&&(n[i]=s.components.SignUpForm);return n},Ne=()=>{r.useViewport(),r.useCurrentDocumentTitle("Signup");const e=ne(),[t]=T.useSearchParams(),n=t.get("name"),o=Z(n),{authType:i}=o||{};return e[i]?l.createElement(e[i],{authenticatorName:n}):c.jsx(T.Navigate,{to:"/not-found",replace:!0})};function _e(e="/admin"){const t=T.useNavigate(),[n]=T.useSearchParams();return l.useCallback(()=>{t(n.get("redirect")||"/admin",{replace:!0})},[t,n])}const oe=e=>{const t=f.useForm(),n=r.useAPIClient(),o=_e(),{refreshAsync:i}=r.useCurrentUserContext();return{run(){return A(this,null,function*(){yield t.submit(),yield n.auth.signIn(t.values,e),yield i(),o()})}}},$e={type:"object",name:"passwordForm","x-component":"FormV2",properties:{account:{type:"string","x-component":"Input","x-validator":`{{(value) => {
|
|
12
12
|
if (!value) {
|
|
13
13
|
return t("Please enter your username or email");
|
|
14
14
|
}
|
|
@@ -19,4 +19,4 @@
|
|
|
19
19
|
} else {
|
|
20
20
|
return /^[^@.<>"'/]{2,16}$/.test(value) || t("Please enter a valid username");
|
|
21
21
|
}
|
|
22
|
-
}}}`,"x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Username/Email")}}',style:{}}},password:{type:"string","x-component":"Password",required:!0,"x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Password")}}',style:{}}},actions:{type:"void","x-component":"div",properties:{submit:{title:'{{t("Sign in")}}',type:"void","x-component":"Action","x-component-props":{htmlType:"submit",block:!0,type:"primary",useAction:"{{ useBasicSignIn }}",style:{width:"100%"}}}}},signUp:{type:"void","x-component":"Link","x-component-props":{to:"{{ signUpLink }}"},"x-content":'{{t("Create an account")}}',"x-visible":"{{ allowSignUp }}"}}},z=t=>{const{t:n}=C(),o=t.authenticator,{authType:s,name:r,options:i}=o,l=!!I()[s]&&(i==null?void 0:i.allowSignUp),ce=`/signup?name=${r}`,ue=()=>k(r);return a.jsx(e.SchemaComponent,{schema:_,scope:{useBasicSignIn:ue,allowSignUp:l,signUpLink:ce,t:n}})},K=t=>{const n=y.useNavigate(),o=x.useForm(),s=e.useAPIClient(),{t:r}=h.useTranslation();return{run(){return T(this,null,function*(){var c;yield o.submit(),yield s.auth.signUp(o.values,t==null?void 0:t.authenticator),d.message.success(((c=t==null?void 0:t.message)==null?void 0:c.success)||r("Sign up successfully, and automatically jump to the sign in page")),setTimeout(()=>{n("/signin")},2e3)})}}},Z={type:"object",name:x.uid(),"x-component":"FormV2",properties:{username:{type:"string",required:!0,"x-component":"Input","x-validator":{username:!0},"x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Username")}}',style:{}}},password:{type:"string",required:!0,"x-component":"Password","x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Password")}}',checkStrength:!0,style:{}},"x-reactions":[{dependencies:[".confirm_password"],fulfill:{state:{selfErrors:'{{$deps[0] && $self.value && $self.value !== $deps[0] ? t("Password mismatch") : ""}}'}}}]},confirm_password:{type:"string",required:!0,"x-component":"Password","x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Confirm password")}}',style:{}},"x-reactions":[{dependencies:[".password"],fulfill:{state:{selfErrors:'{{$deps[0] && $self.value && $self.value !== $deps[0] ? t("Password mismatch") : ""}}'}}}]},actions:{type:"void","x-component":"div",properties:{submit:{title:'{{t("Sign up")}}',type:"void","x-component":"Action","x-component-props":{block:!0,type:"primary",htmlType:"submit",useAction:"{{ useBasicSignUp }}",style:{width:"100%"}}}}},link:{type:"void","x-component":"div",properties:{link:{type:"void","x-component":"Link","x-component-props":{to:"/signin"},"x-content":'{{t("Log in with an existing account")}}'}}}}},W=({authenticatorName:t})=>{const{t:n}=C(),o=()=>K({authenticator:t}),s=F(t),{options:r}=s;return r!=null&&r.allowSignUp?a.jsx(e.SchemaComponent,{schema:Z,scope:{useBasicSignUp:o,t:n}}):a.jsx(y.Navigate,{to:"/not-found",replace:!0})},G=()=>{const{t}=C();return a.jsx(e.SchemaComponent,{scope:{t},components:{Alert:d.Alert},schema:{type:"object",properties:{public:{type:"object",properties:{allowSignUp:{"x-decorator":"FormItem",type:"boolean",title:'{{t("Allow to sign up")}}',"x-component":"Checkbox","x-component-props":{defaultChecked:!0}}}},notice:{type:"void","x-component":"Alert","x-component-props":{showIcon:!0,message:'{{t("The authentication allows users to sign in via username or email.")}}'}}}}})},H=()=>{var s;const n=e.usePlugin(g).authTypes.getEntities(),o={};for(const[r,i]of n)(s=i.components)!=null&&s.BindForm&&(o[r]=i.components.BindForm);return o},J=()=>{const t=e.useRecord(),o=H()[t.authType];return u.createElement(o,{authenticator:t})},Q={type:"void",name:"authenticatorBind","x-decorator":"TableBlockProvider","x-decorator-props":{collection:{name:"authenticators",sortable:!1,fields:[{interface:"input",type:"string",name:"authType"},{interface:"input",type:"string",name:"title",uiSchema:{type:"string",title:'{{t("Title")}}',"x-component":"Input"}},{interface:"textarea",type:"string",name:"description",uiSchema:{type:"string",title:'{{t("Description")}}',"x-component":"Input"}},{type:"boolean",name:"bind",uiSchema:{type:"boolean",title:'{{t("Bind")}}',"x-component":"Checkbox"}},{type:"string",name:"nickname",uiSchema:{type:"string",title:'{{t("Nickname")}}',"x-component":"Input"}}]},resource:"authenticators",action:"bindTypes",params:{sort:["sort"]},rowKey:"name",showIndex:!0},"x-component":"div",properties:{table:{type:"array","x-component":"TableV2","x-use-component-props":"useTableBlockProps","x-component-props":{rowKey:"name"},properties:{authType:{title:'{{t("Auth Type")}}',type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{authType:{type:"string","x-component":"Select","x-read-pretty":!0}}},title:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{title:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},description:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{description:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},bind:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{bind:{type:"boolean","x-component":"CollectionField","x-read-pretty":!0}}},nickname:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{nickname:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},actions:{type:"void",title:'{{t("Actions")}}',"x-component":"TableV2.Column",properties:{actions:{type:"void","x-component":"Space","x-component-props":{split:"|"},properties:{unbind:{"x-visible":'{{ $self.query(".bind").value() }}',type:"void",title:'{{ t("Unbind") }}',"x-component":"Action.Link","x-component-props":{confirm:{title:"{{t('Unbind')}}",content:"{{t('Are you sure to unbind this authenticator?')}}"},useAction:"{{ useUnbindAction }}"}},bind:{"x-visible":'{{ !$self.query(".bind").value() }}',type:"void",title:"{{ t('Bind') }}","x-component":"Action.Link",properties:{modal:{type:"void","x-decorator":"Form",title:"{{ t('Bind') }}","x-component":"Action.Modal","x-component-props":{width:800},properties:{form:{type:"void","x-component":"BindForm"}}}}}}}}}}}}},X=()=>{const{refreshCM:t}=e.useCollectionManager_deprecated(),n=e.useAPIClient(),o=e.useRecord();return{run(){return T(this,null,function*(){yield n.resource("authenticators").unbind({authenticator:o.name}),t()})}}},Y=()=>{const{t}=C();return a.jsx(d.Card,{bordered:!1,children:a.jsx(e.SchemaComponent,{schema:Q,components:{BindForm:J},scope:{t,useUnbindAction:X}})})},w=u.createContext({type:""});w.displayName="AuthTypeContext";const P=u.createContext({types:[]});P.displayName="AuthTypesContext";const R=()=>{const{types:t}=u.useContext(P);return t},ee=t=>{const n=e.useRecord(),o=e.useRequest(()=>Promise.resolve({data:v({},n.options)}),S(v({},t),{manual:!0})),{run:s}=o,r=e.useActionContext();return u.useEffect(()=>{r.visible&&s()},[r.visible,s]),o},te=t=>{var s;const o=e.usePlugin(g).authTypes.get(t);return(s=o==null?void 0:o.components)==null?void 0:s.AdminSettingsForm},oe=x.observer(()=>{const t=x.useForm(),n=e.useRecord(),o=te(t.values.authType||n.authType);return o?a.jsx(o,{}):null},{displayName:"Options"}),V={name:"authenticators",sortable:!0,fields:[{name:"id",type:"string",interface:"id"},{interface:"input",type:"string",name:"name",uiSchema:{type:"string",title:'{{t("Auth UID")}}',"x-component":"Input","x-validator":t=>/^[a-zA-Z0-9_-]+$/.test(t)?"":e.i18n.t("a-z, A-Z, 0-9, _, -"),required:!0}},{interface:"input",type:"string",name:"authType",uiSchema:{type:"string",title:'{{t("Auth Type")}}',"x-component":"Select",dataSource:"{{ types }}",required:!0}},{interface:"input",type:"string",name:"title",uiSchema:{type:"string",title:'{{t("Title")}}',"x-component":"Input"}},{interface:"textarea",type:"string",name:"description",uiSchema:{type:"string",title:'{{t("Description")}}',"x-component":"Input"}},{type:"boolean",name:"enabled",uiSchema:{type:"boolean",title:'{{t("Enabled")}}',"x-component":"Checkbox"}}]},ne={type:"object",properties:{drawer:{type:"void","x-component":"Action.Drawer","x-decorator":"Form","x-decorator-props":{useValues(t){const n=e.useActionContext(),{type:o}=u.useContext(w);return e.useRequest(()=>Promise.resolve({data:{name:`s_${x.uid()}`,authType:o}}),S(v({},t),{refreshDeps:[n.visible]}))}},title:'{{t("Add new")}}',properties:{name:{"x-component":"CollectionField","x-decorator":"FormItem"},authType:{"x-component":"CollectionField","x-decorator":"FormItem","x-component-props":{options:"{{ types }}"}},title:{"x-component":"CollectionField","x-decorator":"FormItem"},description:{"x-component":"CollectionField","x-decorator":"FormItem"},enabled:{"x-component":"CollectionField","x-decorator":"FormItem"},options:{type:"object","x-component":"Options"},footer:{type:"void","x-component":"Action.Drawer.Footer",properties:{cancel:{title:'{{ t("Cancel") }}',"x-component":"Action","x-use-component-props":"useCancelActionProps"},create:{title:'{{ t("Submit") }}',"x-action":"submit","x-component":"Action","x-use-component-props":"useCreateDatabaseConnectionAction","x-component-props":{type:"primary"}}}}}}}},re={type:"void",name:"authenticators","x-decorator":"TableBlockProvider","x-decorator-props":{collection:V,dragSort:!0,action:"list",params:{pageSize:50,sort:"sort",appends:[]}},properties:{actions:{type:"void","x-component":"ActionBar","x-component-props":{style:{marginBottom:16}},properties:{delete:{type:"void",title:'{{t("Delete")}}',"x-action":"destroy","x-decorator":"ACLActionProvider","x-component":"Action","x-use-component-props":"useBulkDestroyActionProps","x-component-props":{icon:"DeleteOutlined",confirm:{title:"{{t('Delete')}}",content:"{{t('Are you sure you want to delete it?')}}"}}},create:{type:"void",title:'{{t("Add new")}}',"x-component":"AddNew","x-component-props":{type:"primary"}}}},table:{type:"array","x-uid":"input","x-component":"TableV2","x-use-component-props":"useTableBlockProps","x-component-props":{rowKey:"id",rowSelection:{type:"checkbox"}},properties:{id:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{id:{type:"number","x-component":"CollectionField","x-read-pretty":!0}}},name:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{name:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},authType:{title:'{{t("Auth Type")}}',type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{authType:{type:"string","x-component":"Select","x-read-pretty":!0,enum:"{{ types }}"}}},title:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{title:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},description:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{description:{type:"boolean","x-component":"CollectionField","x-read-pretty":!0}}},enabled:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{enabled:{type:"boolean","x-component":"CollectionField","x-read-pretty":!0}}},actions:{type:"void",title:'{{t("Actions")}}',"x-component":"TableV2.Column",properties:{actions:{type:"void","x-component":"Space","x-component-props":{split:"|"},properties:{updateAuthenticator:{type:"void",title:'{{ t("Edit") }}',"x-action":"update","x-component":"Action.Link","x-component-props":{openMode:"drawer",icon:"EditOutlined"},"x-decorator":"ACLActionProvider",properties:{drawer:{type:"void",title:'{{ t("Edit record") }}',"x-component":"Action.Container","x-component-props":{className:"tb-action-popup"},properties:{card:{type:"void","x-acl-action-props":{skipScopeCheck:!1},"x-acl-action":"authenticators:update","x-decorator":"FormBlockProvider","x-use-decorator-props":"useEditFormBlockDecoratorProps","x-decorator-props":{action:"get",dataSource:"main",collection:V},"x-component":"CardItem",properties:{form:{type:"void","x-component":"FormV2","x-use-component-props":"useEditFormBlockProps",properties:{actionBar:{type:"void","x-component":"ActionBar","x-component-props":{style:{marginBottom:24}},properties:{cancel:{title:'{{ t("Cancel") }}',"x-component":"Action","x-use-component-props":"useCancelActionProps"},submit:{title:'{{ t("Submit") }}',"x-component":"Action","x-use-component-props":"useUpdateActionProps","x-component-props":{type:"primary"}}}},name:{"x-component":"CollectionField","x-decorator":"FormItem"},authType:{"x-component":"CollectionField","x-decorator":"FormItem","x-component-props":{options:"{{ types }}"}},title:{"x-component":"CollectionField","x-decorator":"FormItem"},description:{"x-component":"CollectionField","x-decorator":"FormItem"},enabled:{"x-component":"CollectionField","x-decorator":"FormItem"},options:{type:"object","x-component":"Options"}}}}}}}}},delete:{type:"void",title:'{{ t("Delete") }}',"x-action":"destroy","x-component":"Action.Link","x-use-component-props":"useDestroyActionProps","x-component-props":{confirm:{title:"{{t('Delete record')}}",content:"{{t('Are you sure you want to delete it?')}}"}},"x-disabled":"{{ useCanNotDelete() }}"}}}}}}}}},se=()=>{const{setVisible:t}=e.useActionContext();return{run(){return T(this,null,function*(){t(!1)})}}},ie=()=>{const{t}=h.useTranslation(),[n,o]=u.useState(!1),[s,r]=u.useState(""),i=R(),c=i.map(l=>S(v({},l),{onClick:()=>{o(!0),r(l.value)}}));return a.jsx(e.ActionContextProvider,{value:{visible:n,setVisible:o},children:a.jsxs(w.Provider,{value:{type:s},children:[a.jsx(d.Dropdown,{menu:{items:c},children:a.jsxs(d.Button,{icon:a.jsx(b.PlusOutlined,{}),type:"primary",children:[t("Add new")," ",a.jsx(b.DownOutlined,{})]})}),a.jsx(e.SchemaComponent,{scope:{useCloseAction:se,types:i,setType:r},schema:ne})]})})},ae=()=>(e.useAsyncData(),!1),pe=()=>{const{t}=C(),[n,o]=u.useState([]),s=e.useAPIClient();return e.useRequest(()=>s.resource("authenticators").listTypes().then(r=>{var c;return(((c=r==null?void 0:r.data)==null?void 0:c.data)||[]).map(l=>({key:l.name,label:t(l.title||l.name),value:l.name}))}),{onSuccess:r=>{o(r)}}),a.jsx(d.Card,{bordered:!1,children:a.jsx(P.Provider,{value:{types:n},children:a.jsx(e.SchemaComponent,{schema:re,components:{AddNew:ie,Options:oe},scope:{types:n,useValuesFromOptions:ee,useCanNotDelete:ae,t}})})})};class g extends e.Plugin{constructor(){super(...arguments),this.authTypes=new m.Registry}registerType(n,o){this.authTypes.register(n,o)}load(){return T(this,null,function*(){this.app.systemSettingsManager.add("system-services."+f,{icon:"LoginOutlined",title:`{{t("Authentication", { ns: "${f}" })}}`,Component:pe,aclSnippet:"pm.auth.authenticators"}),this.app.userSettingsManager.add(f,{icon:"LoginOutlined",title:`{{t("Authentication login bind", { ns: "${f}" })}}`,Component:Y,aclSnippet:"pm.auth.authenticators"}),this.router.add("auth",{Component:"AuthLayout"}),this.router.add("auth.signin",{path:"/signin",Component:"SignInPage"}),this.router.add("auth.signup",{path:"/signup",Component:"SignUpPage"}),this.app.addComponents({AuthLayout:E,SignInPage:L,SignUpPage:j}),this.app.providers.unshift([$,{}]),this.registerType(D,{components:{SignInForm:z,SignUpForm:W,AdminSettingsForm:G}})})}}p.AuthenticatorsContext=A,p.PluginAuthClient=g,p.default=g,p.useAuthenticator=F,p.useSignIn=k,Object.defineProperties(p,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
|
22
|
+
}}}`,"x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Username/Email")}}',style:{}}},password:{type:"string","x-component":"Password",required:!0,"x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Password")}}',style:{}}},actions:{type:"void","x-component":"div",properties:{submit:{title:'{{t("Sign in")}}',type:"void","x-component":"Action","x-component-props":{htmlType:"submit",block:!0,type:"primary",useAction:"{{ useBasicSignIn }}",style:{width:"100%"}}}}},signUp:{type:"void","x-component":"Link","x-component-props":{to:"{{ signUpLink }}"},"x-content":'{{t("Create an account")}}',"x-visible":"{{ allowSignUp }}"}}},je=e=>{const{t}=v(),n=e.authenticator,{authType:o,name:i,options:s}=n,p=!!ne()[o]&&(s==null?void 0:s.allowSignUp),y=`/signup?name=${i}`,x=()=>oe(i);return c.jsx(r.SchemaComponent,{schema:$e,scope:{useBasicSignIn:x,allowSignUp:p,signUpLink:y,t}})},Be=e=>{const t=T.useNavigate(),n=f.useForm(),o=r.useAPIClient(),{t:i}=w.useTranslation();return{run(){return A(this,null,function*(){var a;yield n.submit(),yield o.auth.signUp(n.values,e==null?void 0:e.authenticator),d.message.success(((a=e==null?void 0:e.message)==null?void 0:a.success)||i("Sign up successfully, and automatically jump to the sign in page")),setTimeout(()=>{t("/signin")},2e3)})}}},De={type:"object",name:f.uid(),"x-component":"FormV2",properties:{username:{type:"string",required:!0,"x-component":"Input","x-validator":{username:!0},"x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Username")}}',style:{}}},password:{type:"string",required:!0,"x-component":"Password","x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Password")}}',checkStrength:!0,style:{}},"x-reactions":[{dependencies:[".confirm_password"],fulfill:{state:{selfErrors:'{{$deps[0] && $self.value && $self.value !== $deps[0] ? t("Password mismatch") : ""}}'}}}]},confirm_password:{type:"string",required:!0,"x-component":"Password","x-decorator":"FormItem","x-component-props":{placeholder:'{{t("Confirm password")}}',style:{}},"x-reactions":[{dependencies:[".password"],fulfill:{state:{selfErrors:'{{$deps[0] && $self.value && $self.value !== $deps[0] ? t("Password mismatch") : ""}}'}}}]},actions:{type:"void","x-component":"div",properties:{submit:{title:'{{t("Sign up")}}',type:"void","x-component":"Action","x-component-props":{block:!0,type:"primary",htmlType:"submit",useAction:"{{ useBasicSignUp }}",style:{width:"100%"}}}}},link:{type:"void","x-component":"div",properties:{link:{type:"void","x-component":"Link","x-component-props":{to:"/signin"},"x-content":'{{t("Log in with an existing account")}}'}}}}},Ue=({authenticatorName:e})=>{const{t}=v(),n=()=>Be({authenticator:e}),o=Z(e),{options:i}=o;return i!=null&&i.allowSignUp?c.jsx(r.SchemaComponent,{schema:De,scope:{useBasicSignUp:n,t}}):c.jsx(T.Navigate,{to:"/not-found",replace:!0})},Ve=()=>{const{t:e}=v();return c.jsx(r.SchemaComponent,{scope:{t:e},components:{Alert:d.Alert},schema:{type:"object",properties:{public:{type:"object",properties:{allowSignUp:{"x-decorator":"FormItem",type:"boolean",title:'{{t("Allow to sign up")}}',"x-component":"Checkbox","x-component-props":{defaultChecked:!0}}}},notice:{type:"void","x-component":"Alert","x-component-props":{showIcon:!0,message:'{{t("The authentication allows users to sign in via username or email.")}}'}}}}})},Le=()=>{var o;const t=r.usePlugin(I).authTypes.getEntities(),n={};for(const[i,s]of t)(o=s.components)!=null&&o.BindForm&&(n[i]=s.components.BindForm);return n},Me=()=>{const e=r.useRecord(),n=Le()[e.authType];return l.createElement(n,{authenticator:e})},qe={type:"void",name:"authenticatorBind","x-decorator":"TableBlockProvider","x-decorator-props":{collection:{name:"authenticators",sortable:!1,fields:[{interface:"input",type:"string",name:"authType"},{interface:"input",type:"string",name:"title",uiSchema:{type:"string",title:'{{t("Title")}}',"x-component":"Input"}},{interface:"textarea",type:"string",name:"description",uiSchema:{type:"string",title:'{{t("Description")}}',"x-component":"Input"}},{type:"boolean",name:"bind",uiSchema:{type:"boolean",title:'{{t("Bind")}}',"x-component":"Checkbox"}},{type:"string",name:"nickname",uiSchema:{type:"string",title:'{{t("Nickname")}}',"x-component":"Input"}}]},resource:"authenticators",action:"bindTypes",params:{sort:["sort"]},rowKey:"name",showIndex:!0},"x-component":"div",properties:{table:{type:"array","x-component":"TableV2","x-use-component-props":"useTableBlockProps","x-component-props":{rowKey:"name"},properties:{authType:{title:'{{t("Auth Type")}}',type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{authType:{type:"string","x-component":"Select","x-read-pretty":!0}}},title:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{title:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},description:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{description:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},bind:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{bind:{type:"boolean","x-component":"CollectionField","x-read-pretty":!0}}},nickname:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{nickname:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},actions:{type:"void",title:'{{t("Actions")}}',"x-component":"TableV2.Column",properties:{actions:{type:"void","x-component":"Space","x-component-props":{split:"|"},properties:{unbind:{"x-visible":'{{ $self.query(".bind").value() }}',type:"void",title:'{{ t("Unbind") }}',"x-component":"Action.Link","x-component-props":{confirm:{title:"{{t('Unbind')}}",content:"{{t('Are you sure to unbind this authenticator?')}}"},useAction:"{{ useUnbindAction }}"}},bind:{"x-visible":'{{ !$self.query(".bind").value() }}',type:"void",title:"{{ t('Bind') }}","x-component":"Action.Link",properties:{modal:{type:"void","x-decorator":"Form",title:"{{ t('Bind') }}","x-component":"Action.Modal","x-component-props":{width:800},properties:{form:{type:"void","x-component":"BindForm"}}}}}}}}}}}}},Ke=()=>{const{refreshCM:e}=r.useCollectionManager_deprecated(),t=r.useAPIClient(),n=r.useRecord();return{run(){return A(this,null,function*(){yield t.resource("authenticators").unbind({authenticator:n.name}),e()})}}},We=()=>{const{t:e}=v();return c.jsx(d.Card,{bordered:!1,children:c.jsx(r.SchemaComponent,{schema:qe,components:{BindForm:Me},scope:{t:e,useUnbindAction:Ke}})})};var V=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{};function re(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function He(e){var t=typeof e;return e!=null&&(t=="object"||t=="function")}var ie=He,Ge=typeof V=="object"&&V&&V.Object===Object&&V,Xe=Ge,ze=Xe,Ye=typeof self=="object"&&self&&self.Object===Object&&self,Ze=ze||Ye||Function("return this")(),se=Ze,Je=se,Qe=function(){return Je.Date.now()},Re=Qe,et=/\s/;function tt(e){for(var t=e.length;t--&&et.test(e.charAt(t)););return t}var nt=tt,ot=nt,rt=/^\s+/;function it(e){return e&&e.slice(0,ot(e)+1).replace(rt,"")}var st=it,at=se,ct=at.Symbol,ae=ct,ce=ae,pe=Object.prototype,pt=pe.hasOwnProperty,ut=pe.toString,D=ce?ce.toStringTag:void 0;function lt(e){var t=pt.call(e,D),n=e[D];try{e[D]=void 0;var o=!0}catch(s){}var i=ut.call(e);return o&&(t?e[D]=n:delete e[D]),i}var dt=lt,mt=Object.prototype,yt=mt.toString;function ht(e){return yt.call(e)}var xt=ht,ue=ae,ft=dt,gt=xt,bt="[object Null]",Tt="[object Undefined]",le=ue?ue.toStringTag:void 0;function vt(e){return e==null?e===void 0?Tt:bt:le&&le in Object(e)?ft(e):gt(e)}var St=vt;function Ct(e){return e!=null&&typeof e=="object"}var At=Ct,wt=St,Et=At,Ft="[object Symbol]";function It(e){return typeof e=="symbol"||Et(e)&&wt(e)==Ft}var kt=It,Pt=st,de=ie,Ot=kt,me=NaN,Nt=/^[-+]0x[0-9a-f]+$/i,_t=/^0b[01]+$/i,$t=/^0o[0-7]+$/i,jt=parseInt;function Bt(e){if(typeof e=="number")return e;if(Ot(e))return me;if(de(e)){var t=typeof e.valueOf=="function"?e.valueOf():e;e=de(t)?t+"":t}if(typeof e!="string")return e===0?e:+e;e=Pt(e);var n=_t.test(e);return n||$t.test(e)?jt(e.slice(2),n?2:8):Nt.test(e)?me:+e}var Dt=Bt,Ut=ie,J=Re,ye=Dt,Vt="Expected a function",Lt=Math.max,Mt=Math.min;function qt(e,t,n){var o,i,s,a,p,y,x=0,_=!1,b=!1,g=!0;if(typeof e!="function")throw new TypeError(Vt);t=ye(t)||0,Ut(n)&&(_=!!n.leading,b="maxWait"in n,s=b?Lt(ye(n.maxWait)||0,t):s,g="trailing"in n?!!n.trailing:g);function $(h){var S=o,U=i;return o=i=void 0,x=h,a=e.apply(U,S),a}function W(h){return x=h,p=setTimeout(X,t),_?$(h):a}function H(h){var S=h-y,U=h-x,Te=t-S;return b?Mt(Te,s-U):Te}function G(h){var S=h-y,U=h-x;return y===void 0||S>=t||S<0||b&&U>=s}function X(){var h=J();if(G(h))return be(h);p=setTimeout(X,H(h))}function be(h){return p=void 0,g&&o?$(h):(o=i=void 0,a)}function gn(){p!==void 0&&clearTimeout(p),x=0,o=y=i=p=void 0}function bn(){return p===void 0?a:be(J())}function te(){var h=J(),S=G(h);if(o=arguments,i=this,y=h,S){if(p===void 0)return W(y);if(b)return clearTimeout(p),p=setTimeout(X,t),$(y)}return p===void 0&&(p=setTimeout(X,t)),a}return te.cancel=gn,te.flush=bn,te}var Kt=qt;const Wt=re(Kt),L={EMPTY_TOKEN:"EMPTY_TOKEN",EXPIRED_TOKEN:"EXPIRED_TOKEN",INVALID_TOKEN:"INVALID_TOKEN",TOKEN_RENEW_FAILED:"TOKEN_RENEW_FAILED",BLOCKED_TOKEN:"BLOCKED_TOKEN",EXPIRED_SESSION:"EXPIRED_SESSION",NOT_EXIST_USER:"NOT_EXIST_USER",SKIP_TOKEN_RENEW:"SKIP_TOKEN_RENEW",USER_HAS_NO_ROLES_ERR:"USER_HAS_NO_ROLES_ERR"};function Ht(e,t){const n=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o=new RegExp(`^${n.replace(/\/?$/,"")}(\\/|$)`);return e.replace(o,"/")||e}const Gt=Wt(e=>{e()},3e3,{leading:!0,trailing:!1});function Xt({app:e}){return e.apiClient.axios,[o=>{var s;const i=(s=o==null?void 0:o.headers)==null?void 0:s["x-new-token"];return i&&e.apiClient.auth.setToken(i),o},o=>{var b,g,$,W,H;const i=(g=(b=o==null?void 0:o.response)==null?void 0:b.headers)==null?void 0:g["x-new-token"],s=(W=($=o==null?void 0:o.response)==null?void 0:$.data)==null?void 0:W.errors,a=Array.isArray(s)?s[0]:null,p=e.router.state,{pathname:y,search:x}=p.location,_=e.router.basename;if(i&&e.apiClient.auth.setToken(i),o.status===401&&(a!=null&&a.code)&&L[a.code]&&(e.apiClient.auth.setToken(""),y===e.getHref("signin")&&(a==null?void 0:a.code)!==L.EMPTY_TOKEN&&o.config&&(o.config.skipNotify=!1),(a==null?void 0:a.code)==="USER_HAS_NO_ROLES_ERR"&&(o.config.skipNotify=!0,e.error=a)),o.status===401&&!((H=o.config)!=null&&H.skipAuth)&&(a!=null&&a.code)&&L[a.code]){if(!a||(a==null?void 0:a.code)===L.SKIP_TOKEN_RENEW)throw o;if(y!==e.getHref("signin")){const G=Ht(y,_);Gt(()=>{e.apiClient.auth.setToken(null),e.router.navigate(`/signin?redirect=${G}${x}`,{replace:!0})})}}throw o}]}const Q=l.createContext({type:""});Q.displayName="AuthTypeContext";const R=l.createContext({types:[]});R.displayName="AuthTypesContext";const zt=()=>{const{types:e}=l.useContext(R);return e},Yt=e=>{const t=r.useRecord(),n=r.useRequest(()=>Promise.resolve({data:C({},t.options)}),Y(C({},e),{manual:!0})),{run:o}=n,i=r.useActionContext();return l.useEffect(()=>{i.visible&&o()},[i.visible,o]),n},Zt=e=>{var o;const n=r.usePlugin(I).authTypes.get(e);return(o=n==null?void 0:n.components)==null?void 0:o.AdminSettingsForm},Jt=f.observer(()=>{const e=f.useForm(),t=r.useRecord(),n=Zt(e.values.authType||t.authType);return n?c.jsx(n,{}):null},{displayName:"Options"}),he={name:"authenticators",sortable:!0,fields:[{name:"id",type:"string",interface:"id"},{interface:"input",type:"string",name:"name",uiSchema:{type:"string",title:'{{t("Auth UID")}}',"x-component":"Input","x-validator":e=>/^[a-zA-Z0-9_-]+$/.test(e)?"":r.i18n.t("a-z, A-Z, 0-9, _, -"),required:!0}},{interface:"input",type:"string",name:"authType",uiSchema:{type:"string",title:'{{t("Auth Type")}}',"x-component":"Select",dataSource:"{{ types }}",required:!0}},{interface:"input",type:"string",name:"title",uiSchema:{type:"string",title:'{{t("Title")}}',"x-component":"Input"}},{interface:"textarea",type:"string",name:"description",uiSchema:{type:"string",title:'{{t("Description")}}',"x-component":"Input"}},{type:"boolean",name:"enabled",uiSchema:{type:"boolean",title:'{{t("Enabled")}}',"x-component":"Checkbox"}}]},Qt={type:"object",properties:{drawer:{type:"void","x-component":"Action.Drawer","x-decorator":"Form","x-decorator-props":{useValues(e){const t=r.useActionContext(),{type:n}=l.useContext(Q);return r.useRequest(()=>Promise.resolve({data:{name:`s_${f.uid()}`,authType:n}}),Y(C({},e),{refreshDeps:[t.visible]}))}},title:'{{t("Add new")}}',properties:{name:{"x-component":"CollectionField","x-decorator":"FormItem"},authType:{"x-component":"CollectionField","x-decorator":"FormItem","x-component-props":{options:"{{ types }}"}},title:{"x-component":"CollectionField","x-decorator":"FormItem"},description:{"x-component":"CollectionField","x-decorator":"FormItem"},enabled:{"x-component":"CollectionField","x-decorator":"FormItem"},options:{type:"object","x-component":"Options"},footer:{type:"void","x-component":"Action.Drawer.Footer",properties:{cancel:{title:'{{ t("Cancel") }}',"x-component":"Action","x-use-component-props":"useCancelActionProps"},create:{title:'{{ t("Submit") }}',"x-action":"submit","x-component":"Action","x-use-component-props":"useCreateDatabaseConnectionAction","x-component-props":{type:"primary"}}}}}}}},Rt={type:"void",name:"authenticators","x-decorator":"TableBlockProvider","x-decorator-props":{collection:he,dragSort:!0,action:"list",params:{pageSize:50,sort:"sort",appends:[]}},properties:{actions:{type:"void","x-component":"ActionBar","x-component-props":{style:{marginBottom:16}},properties:{delete:{type:"void",title:'{{t("Delete")}}',"x-action":"destroy","x-decorator":"ACLActionProvider","x-component":"Action","x-use-component-props":"useBulkDestroyActionProps","x-component-props":{icon:"DeleteOutlined",confirm:{title:"{{t('Delete')}}",content:"{{t('Are you sure you want to delete it?')}}"}}},create:{type:"void",title:'{{t("Add new")}}',"x-component":"AddNew","x-component-props":{type:"primary"}}}},table:{type:"array","x-uid":"input","x-component":"TableV2","x-use-component-props":"useTableBlockProps","x-component-props":{rowKey:"id",rowSelection:{type:"checkbox"}},properties:{id:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{id:{type:"number","x-component":"CollectionField","x-read-pretty":!0}}},name:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{name:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},authType:{title:'{{t("Auth Type")}}',type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{authType:{type:"string","x-component":"Select","x-read-pretty":!0,enum:"{{ types }}"}}},title:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{title:{type:"string","x-component":"CollectionField","x-read-pretty":!0}}},description:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{description:{type:"boolean","x-component":"CollectionField","x-read-pretty":!0}}},enabled:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{enabled:{type:"boolean","x-component":"CollectionField","x-read-pretty":!0}}},actions:{type:"void",title:'{{t("Actions")}}',"x-component":"TableV2.Column",properties:{actions:{type:"void","x-component":"Space","x-component-props":{split:"|"},properties:{updateAuthenticator:{type:"void",title:'{{ t("Edit") }}',"x-action":"update","x-component":"Action.Link","x-component-props":{openMode:"drawer",icon:"EditOutlined"},"x-decorator":"ACLActionProvider",properties:{drawer:{type:"void",title:'{{ t("Edit record") }}',"x-component":"Action.Container","x-component-props":{className:"tb-action-popup"},properties:{card:{type:"void","x-acl-action-props":{skipScopeCheck:!1},"x-acl-action":"authenticators:update","x-decorator":"FormBlockProvider","x-use-decorator-props":"useEditFormBlockDecoratorProps","x-decorator-props":{action:"get",dataSource:"main",collection:he},"x-component":"CardItem",properties:{form:{type:"void","x-component":"FormV2","x-use-component-props":"useEditFormBlockProps",properties:{actionBar:{type:"void","x-component":"ActionBar","x-component-props":{style:{marginBottom:24}},properties:{cancel:{title:'{{ t("Cancel") }}',"x-component":"Action","x-use-component-props":"useCancelActionProps"},submit:{title:'{{ t("Submit") }}',"x-component":"Action","x-use-component-props":"useUpdateActionProps","x-component-props":{type:"primary"}}}},name:{"x-component":"CollectionField","x-decorator":"FormItem"},authType:{"x-component":"CollectionField","x-decorator":"FormItem","x-component-props":{options:"{{ types }}"}},title:{"x-component":"CollectionField","x-decorator":"FormItem"},description:{"x-component":"CollectionField","x-decorator":"FormItem"},enabled:{"x-component":"CollectionField","x-decorator":"FormItem"},options:{type:"object","x-component":"Options"}}}}}}}}},delete:{type:"void",title:'{{ t("Delete") }}',"x-action":"destroy","x-component":"Action.Link","x-use-component-props":"useDestroyActionProps","x-component-props":{confirm:{title:"{{t('Delete record')}}",content:"{{t('Are you sure you want to delete it?')}}"}},"x-disabled":"{{ useCanNotDelete() }}"}}}}}}}}},en=()=>{const{setVisible:e}=r.useActionContext();return{run(){return A(this,null,function*(){e(!1)})}}},tn=()=>{const{t:e}=w.useTranslation(),[t,n]=l.useState(!1),[o,i]=l.useState(""),s=zt(),a=s.map(p=>Y(C({},p),{onClick:()=>{n(!0),i(p.value)}}));return c.jsx(r.ActionContextProvider,{value:{visible:t,setVisible:n},children:c.jsxs(Q.Provider,{value:{type:o},children:[c.jsx(d.Dropdown,{menu:{items:a},children:c.jsxs(d.Button,{icon:c.jsx(k.PlusOutlined,{}),type:"primary",children:[e("Add new")," ",c.jsx(k.DownOutlined,{})]})}),c.jsx(r.SchemaComponent,{scope:{useCloseAction:en,types:s,setType:i},schema:Qt})]})})},nn=()=>(r.useAsyncData(),!1),on=()=>{const{t:e}=v(),[t,n]=l.useState([]),o=r.useAPIClient();return r.useRequest(()=>o.resource("authenticators").listTypes().then(i=>{var a;return(((a=i==null?void 0:i.data)==null?void 0:a.data)||[]).map(p=>({key:p.name,label:e(p.title||p.name),value:p.name}))}),{onSuccess:i=>{n(i)}}),c.jsx(d.Card,{bordered:!1,children:c.jsx(R.Provider,{value:{types:t},children:c.jsx(r.SchemaComponent,{schema:Rt,components:{AddNew:tn,Options:Jt},scope:{types:t,useValuesFromOptions:Yt,useCanNotDelete:nn,t:e}})})})},{Option:ee}=d.Select,rn=f.connect(e=>{const{t}=v(),b=e,{value:n,onChange:o,minNum:i=1}=b,s=Ae(b,["value","onChange","minNum"]),a=/^(\d*)([a-zA-Z]*)$/,p=n?n.match(a):null;l.useEffect(()=>{p||o("10m")},[p,o]);const[y,x]=p?[parseInt(p[1]),p[2]]:[10,"m"],_=c.jsxs(d.Select,{value:x,onChange:g=>o(`${y}${g}`),style:{width:120},children:[c.jsx(ee,{value:"m",children:t("Minutes")}),c.jsx(ee,{value:"h",children:t("Hours")}),c.jsx(ee,{value:"d",children:t("Days")})]});return c.jsx(d.InputNumber,C({value:y,addonAfter:_,min:i,onChange:g=>o(`${g!=null?g:1}${x}`)},s))},f.mapProps({onInput:"onChange"})),M={InputTime:"InputTime"},sn={[M.InputTime]:rn};var P=1e3,O=P*60,N=O*60,F=N*24,an=F*7,cn=F*365.25,pn=function(e,t){t=t||{};var n=typeof e;if(n==="string"&&e.length>0)return un(e);if(n==="number"&&isFinite(e))return t.long?dn(e):ln(e);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))};function un(e){if(e=String(e),!(e.length>100)){var t=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(t){var n=parseFloat(t[1]),o=(t[2]||"ms").toLowerCase();switch(o){case"years":case"year":case"yrs":case"yr":case"y":return n*cn;case"weeks":case"week":case"w":return n*an;case"days":case"day":case"d":return n*F;case"hours":case"hour":case"hrs":case"hr":case"h":return n*N;case"minutes":case"minute":case"mins":case"min":case"m":return n*O;case"seconds":case"second":case"secs":case"sec":case"s":return n*P;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return n;default:return}}}}function ln(e){var t=Math.abs(e);return t>=F?Math.round(e/F)+"d":t>=N?Math.round(e/N)+"h":t>=O?Math.round(e/O)+"m":t>=P?Math.round(e/P)+"s":e+"ms"}function dn(e){var t=Math.abs(e);return t>=F?q(e,t,F,"day"):t>=N?q(e,t,N,"hour"):t>=O?q(e,t,O,"minute"):t>=P?q(e,t,P,"second"):e+" ms"}function q(e,t,n,o){var i=t>=n*1.5;return Math.round(e/n)+" "+o+(i?"s":"")}const xe=re(pn),fe="token-policy-config",ge="tokenControlConfig",mn=()=>{const e=r.useAPIClient(),t=l.useMemo(()=>f.createForm(),[]);return l.useEffect(()=>{A(this,null,function*(){var o;try{const{data:i}=yield e.resource(ge).get({filterByTk:fe});(o=i==null?void 0:i.data)!=null&&o.config&&t.setValues(i.data.config)}catch(i){console.error(i)}})},[t,e]),{form:t}},yn=()=>{const{message:e}=d.App.useApp(),t=r.useAPIClient(),n=f.useForm(),{t:o}=v();return{type:"primary",onClick(){return A(this,null,function*(){n.clearErrors("*");const{tokenExpirationTime:s,sessionExpirationTime:a,expiredTokenRenewLimit:p}=n.values;if(xe(s)>=xe(a)){n.setFieldState("tokenExpirationTime",x=>{x.feedbacks=[{type:"error",code:"ValidateError",messages:[o("Token validity period must be less than session validity period!")]}]});return}yield n.submit();const y=yield t.resource(ge).update({values:{config:n.values},filterByTk:fe});y&&y.status===200&&e.success(o("Saved successfully!"))})}}},K={useSubmitActionProps:"useSubmitActionProps",useEditForm:"useEditForm"},hn={[K.useEditForm]:mn,[K.useSubmitActionProps]:yn},xn={name:f.uid(),"x-component":"FormV2","x-use-component-props":K.useEditForm,type:"object",properties:{sessionExpirationTime:{type:"string",title:j("Session validity period"),"x-decorator":"FormItem","x-component":M.InputTime,required:!0,description:j("The maximum valid time for each user login. During the session validity, the Token will be automatically updated. After the timeout, the user is required to log in again.")},tokenExpirationTime:{type:"string",title:j("Token validity period"),"x-decorator":"FormItem","x-component":M.InputTime,required:!0,description:j("The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)")},expiredTokenRenewLimit:{type:"string",title:"{{t('Expired token refresh limit')}}","x-decorator":"FormItem","x-component":M.InputTime,"x-component-props":{minNum:0},required:!0,description:j("The maximum time limit allowed for refreshing a Token after it expires. After this time limit, the token cannot be automatically renewed, and the user needs to log in again.")},footer:{type:"void","x-component":"ActionBar","x-component-props":{layout:"one-column"},properties:{submit:{title:'{{t("Submit")}}',"x-component":"Action","x-use-component-props":K.useSubmitActionProps}}}}},fn=()=>{const{t:e}=v();return c.jsx(d.Card,{bordered:!1,children:c.jsx(r.SchemaComponent,{schema:xn,scope:C({t:e},hn),components:sn})})};class I extends r.Plugin{constructor(){super(...arguments),this.authTypes=new m.Registry}registerType(t,n){this.authTypes.register(t,n)}load(){return A(this,null,function*(){this.app.systemSettingsManager.add("system-services."+E,{icon:"LoginOutlined",title:`{{t("Authentication", { ns: "${E}" })}}`,Component:on,aclSnippet:"pm.auth.authenticators"}),this.app.userSettingsManager.add(E,{icon:"LoginOutlined",title:`{{t("Authentication login bind", { ns: "${E}" })}}`,Component:We,aclSnippet:"pm.auth.authenticators"}),this.router.add("auth",{Component:"AuthLayout"}),this.router.add("auth.signin",{path:"/signin",Component:"SignInPage"}),this.router.add("auth.signup",{path:"/signup",Component:"SignUpPage"}),this.app.addComponents({AuthLayout:Fe,SignInPage:Pe,SignUpPage:Ne}),this.app.providers.unshift([Ee,{}]),this.registerType(we,{components:{SignInForm:je,SignUpForm:Ue,AdminSettingsForm:Ve}}),this.app.systemSettingsManager.add("security.token-policy",{title:`{{t("Token policy", { ns: "${E}" })}}`,Component:fn,aclSnippet:"pm.security.token-policy",icon:"ApiOutlined",sort:0});const[t,n]=Xt({app:this.app});this.app.apiClient.axios.interceptors.response.handlers.unshift({fulfilled:t,rejected:n,synchronous:!1,runWhen:null})})}}u.AuthenticatorsContext=B,u.PluginAuthClient=I,u.default=I,u.useAuthenticator=Z,u.useSignIn=oe,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const useSubmitActionProps: () => {
|
|
2
|
+
type: string;
|
|
3
|
+
onClick(): Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
export declare const hooksNameMap: {
|
|
6
|
+
useSubmitActionProps: string;
|
|
7
|
+
useEditForm: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const hooksMap: {
|
|
10
|
+
[x: string]: (() => {
|
|
11
|
+
form: import("@tachybase/schema").Form<any>;
|
|
12
|
+
}) | (() => {
|
|
13
|
+
type: string;
|
|
14
|
+
onClick(): Promise<void>;
|
|
15
|
+
});
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const TokenPolicySettings: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const tokenPolicyRecordKey = "token-policy-config";
|
|
2
|
+
export declare const tokenPolicyCacheKey: string;
|
|
3
|
+
export declare const tokenPolicyCollectionName = "tokenControlConfig";
|
|
4
|
+
export declare const issuedTokensCollectionName = "issuedTokens";
|
|
5
|
+
export declare const RENEWED_JTI_CACHE_MS = 10000;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var constants_exports = {};
|
|
19
|
+
__export(constants_exports, {
|
|
20
|
+
RENEWED_JTI_CACHE_MS: () => RENEWED_JTI_CACHE_MS,
|
|
21
|
+
issuedTokensCollectionName: () => issuedTokensCollectionName,
|
|
22
|
+
tokenPolicyCacheKey: () => tokenPolicyCacheKey,
|
|
23
|
+
tokenPolicyCollectionName: () => tokenPolicyCollectionName,
|
|
24
|
+
tokenPolicyRecordKey: () => tokenPolicyRecordKey
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(constants_exports);
|
|
27
|
+
const tokenPolicyRecordKey = "token-policy-config";
|
|
28
|
+
const tokenPolicyCacheKey = "auth:" + tokenPolicyRecordKey;
|
|
29
|
+
const tokenPolicyCollectionName = "tokenControlConfig";
|
|
30
|
+
const issuedTokensCollectionName = "issuedTokens";
|
|
31
|
+
const RENEWED_JTI_CACHE_MS = 1e4;
|
|
32
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
33
|
+
0 && (module.exports = {
|
|
34
|
+
RENEWED_JTI_CACHE_MS,
|
|
35
|
+
issuedTokensCollectionName,
|
|
36
|
+
tokenPolicyCacheKey,
|
|
37
|
+
tokenPolicyCollectionName,
|
|
38
|
+
tokenPolicyRecordKey
|
|
39
|
+
});
|
package/dist/externalVersion.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
"react": "18.3.1",
|
|
3
|
-
"@tachybase/client": "0.
|
|
3
|
+
"@tachybase/client": "1.0.6",
|
|
4
4
|
"react-router-dom": "6.28.1",
|
|
5
|
-
"@tachybase/utils": "0.
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"@tachybase/
|
|
9
|
-
"@tachybase/
|
|
10
|
-
"@tachybase/
|
|
5
|
+
"@tachybase/utils": "1.0.6",
|
|
6
|
+
"axios": "1.7.7",
|
|
7
|
+
"lodash": "4.17.21",
|
|
8
|
+
"@tachybase/auth": "1.0.6",
|
|
9
|
+
"@tachybase/database": "1.0.6",
|
|
10
|
+
"@tachybase/cache": "1.0.6",
|
|
11
|
+
"@tachybase/server": "1.0.6",
|
|
12
|
+
"@tachybase/logger": "1.0.6",
|
|
13
|
+
"@tachybase/test": "1.0.6",
|
|
11
14
|
"antd": "5.22.5",
|
|
12
|
-
"@tachybase/schema": "0.
|
|
15
|
+
"@tachybase/schema": "1.0.6",
|
|
13
16
|
"react-i18next": "15.2.0",
|
|
14
17
|
"@ant-design/icons": "5.3.7",
|
|
15
|
-
"@tachybase/actions": "0.
|
|
18
|
+
"@tachybase/actions": "1.0.6"
|
|
16
19
|
};
|
package/dist/locale/en-US.json
CHANGED
|
@@ -8,24 +8,46 @@
|
|
|
8
8
|
"Authentication login bind": "Authentication login bind",
|
|
9
9
|
"Authenticators": "Authenticators",
|
|
10
10
|
"Bind": "Bind",
|
|
11
|
+
"Days": "Days",
|
|
12
|
+
"Expired token refresh limit": "Expired token refresh limit",
|
|
13
|
+
"Hours": "Hours",
|
|
14
|
+
"In configuration mode, the entire column becomes transparent. In non-configuration mode, the entire column will be hidden. Even if the entire column is hidden, its configured default values and other settings will still take effect.": "In configuration mode, the entire column becomes transparent. In non-configuration mode, the entire column will be hidden. Even if the entire column is hidden, its configured default values and other settings will still take effect.",
|
|
15
|
+
"Minutes": "Minutes",
|
|
11
16
|
"No authentication methods available.": "No authentication methods available.",
|
|
12
17
|
"Not a valid cellphone number, please re-enter": "Not a valid cellphone number, please re-enter",
|
|
13
18
|
"Not allowed to sign up": "Not allowed to sign up",
|
|
19
|
+
"Password is not allowed to be changed": "Password is not allowed to be changed",
|
|
14
20
|
"Please enter a valid email": "Please enter a valid email",
|
|
15
21
|
"Please enter a valid username": "Please enter a valid username",
|
|
16
22
|
"Please enter your username or email": "Please enter your username or email",
|
|
17
23
|
"Please keep and enable at least one authenticator": "Please keep and enable at least one authenticator",
|
|
18
24
|
"SMS": "SMS",
|
|
25
|
+
"Saved successfully!": "Saved successfully!",
|
|
26
|
+
"Seconds": "Seconds",
|
|
27
|
+
"Session validity period": "Session validity period",
|
|
19
28
|
"Sign in via email": "Sign in via email",
|
|
20
29
|
"Sign in via password": "Sign in via password",
|
|
21
30
|
"Sign-in": "Sign-in",
|
|
22
31
|
"The authentication allows users to sign in via username or email.": "The authentication allows users to sign in via username or email.",
|
|
32
|
+
"The maximum time limit allowed for refreshing a Token after it expires. After this time limit, the token cannot be automatically renewed, and the user needs to log in again.": "The maximum time limit allowed for refreshing a Token after it expires. After this time limit, the token cannot be automatically renewed, and the user needs to log in again.",
|
|
33
|
+
"The maximum valid time for each user login. During the session validity, the Token will be automatically updated. After the timeout, the user is required to log in again.": "The maximum valid time for each user login. During the session validity, the Token will be automatically updated. After the timeout, the user is required to log in again.",
|
|
23
34
|
"The password is inconsistent, please re-enter": "The password is inconsistent, please re-enter",
|
|
24
35
|
"The password is incorrect, please re-enter": "The password is incorrect, please re-enter",
|
|
25
36
|
"The phone number has been registered, please login directly": "The phone number has been registered, please login directly",
|
|
26
37
|
"The phone number is not registered, please register first": "The phone number is not registered, please register first",
|
|
27
38
|
"The username or email is incorrect, please re-enter": "The username or email is incorrect, please re-enter",
|
|
39
|
+
"The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)": "The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)",
|
|
40
|
+
"Token policy": "Token policy",
|
|
41
|
+
"Token validity period": "Token validity period",
|
|
42
|
+
"Token validity period must be less than session validity period!": "Token validity period must be less than session validity period!",
|
|
43
|
+
"Unauthenticated. Please sign in to continue.": "Unauthenticated. Please sign in to continue.",
|
|
28
44
|
"Unbind": "Unbind",
|
|
29
45
|
"User can bind or unbind the sign in type": "User can bind or unbind the sign in type",
|
|
30
|
-
"
|
|
46
|
+
"User not found. Please sign in again to continue.": "User not found. Please sign in again to continue.",
|
|
47
|
+
"Username/Email": "Username/Email",
|
|
48
|
+
"Your session has expired. Please sign in again.": "Your session has expired. Please sign in again.",
|
|
49
|
+
"gitea": "Gitea",
|
|
50
|
+
"sms": "SMS",
|
|
51
|
+
"wechat": "WeChat",
|
|
52
|
+
"work-wechat": "WeCom"
|
|
31
53
|
}
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -8,24 +8,45 @@
|
|
|
8
8
|
"Authentication login bind": "认证登录绑定",
|
|
9
9
|
"Authenticators": "认证器",
|
|
10
10
|
"Bind": "绑定",
|
|
11
|
+
"Days": "天",
|
|
12
|
+
"Expired token refresh limit": "过期 Token 刷新时限",
|
|
13
|
+
"Hours": "小时",
|
|
14
|
+
"Minutes": "分钟",
|
|
11
15
|
"No authentication methods available.": "没有可用的认证方式。",
|
|
12
16
|
"Not a valid cellphone number, please re-enter": "不是有效的手机号,请重新输入",
|
|
13
17
|
"Not allowed to sign up": "禁止注册",
|
|
18
|
+
"Password is not allowed to be changed": "密码不允许修改",
|
|
14
19
|
"Please enter a valid email": "请输入有效的邮箱",
|
|
15
20
|
"Please enter a valid username": "请输入有效的用户名",
|
|
16
21
|
"Please enter your username or email": "请输入用户名或邮箱",
|
|
17
22
|
"Please keep and enable at least one authenticator": "请至少保留并启用一个认证器",
|
|
18
23
|
"SMS": "短信",
|
|
24
|
+
"Saved successfully!": "保存成功!",
|
|
25
|
+
"Seconds": "秒",
|
|
26
|
+
"Session validity period": "会话有效期",
|
|
19
27
|
"Sign in via email": "邮箱登录",
|
|
20
28
|
"Sign in via password": "密码登录",
|
|
21
29
|
"Sign-in": "登录",
|
|
22
30
|
"The authentication allows users to sign in via username or email.": "该认证方式支持用户通过用户名或邮箱登录。",
|
|
31
|
+
"The maximum time limit allowed for refreshing a Token after it expires. After this time limit, the token cannot be automatically renewed, and the user needs to log in again.": "Token 过期后允许刷新的最大时限,超过此时限后,Token 无法自动更新,用户需重新登录。",
|
|
32
|
+
"The maximum valid time for each user login. During the session validity, the Token will be automatically updated. After the timeout, the user is required to log in again.": "用户每次登录的最长有效时间,在会话有效期内,Token 会自动更新,超时后要求用户重新登录。",
|
|
23
33
|
"The password is inconsistent, please re-enter": "密码不一致,请重新输入",
|
|
24
34
|
"The password is incorrect, please re-enter": "密码有误,请重新输入",
|
|
25
35
|
"The phone number has been registered, please login directly": "手机号已注册,请直接登录",
|
|
26
36
|
"The phone number is not registered, please register first": "手机号未注册,请先注册",
|
|
27
37
|
"The username or email is incorrect, please re-enter": "用户名或邮箱有误,请重新输入",
|
|
38
|
+
"The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)": "每次签发的 API Token 的有效期。Token 过期后,如果处于会话有效期内,并且没有超过刷新时限,服务端将自动签发新 Token 以保持用户会话,否则要求用户重新登录。(每个 Token 只能被刷新一次)",
|
|
39
|
+
"Token policy": "Token 策略",
|
|
40
|
+
"Token validity period": "Token 有效期",
|
|
41
|
+
"Token validity period must be less than session validity period!": "Token 有效期必须小于会话有效期!",
|
|
42
|
+
"Unauthenticated. Please sign in to continue.": "未认证。请登录以继续。",
|
|
28
43
|
"Unbind": "解绑",
|
|
29
44
|
"User can bind or unbind the sign in type": "用户可以绑定或解绑登录方式",
|
|
30
|
-
"
|
|
45
|
+
"User not found. Please sign in again to continue.": "用户不存在。请重新登录以继续。",
|
|
46
|
+
"Username/Email": "用户名/邮箱",
|
|
47
|
+
"Your session has expired. Please sign in again.": "您的会话已过期,请重新登录。",
|
|
48
|
+
"gitea": "Gitea 验证登录",
|
|
49
|
+
"sms": "短信验证",
|
|
50
|
+
"wechat": "微信登录",
|
|
51
|
+
"work-wechat": "企业微信登录"
|
|
31
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"cron","description":"Cron jobs for your node","version":"3.3.1","author":"Nick Campbell <nicholas.j.campbell@gmail.com> (https://github.com/ncb000gt)","bugs":{"url":"https://github.com/kelektiv/node-cron/issues"},"repository":{"type":"git","url":"https://github.com/kelektiv/node-cron.git"},"main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc -b tsconfig.build.json","lint:eslint":"eslint src/ tests/","lint:prettier":"prettier ./**/*.{json,md,yml} --check","lint":"npm run lint:eslint && npm run lint:prettier","lint:fix":"npm run lint:eslint -- --fix && npm run lint:prettier -- --write","test":"jest --coverage","test:watch":"jest --watch --coverage","test:fuzz":"jest --testMatch='**/*.fuzz.ts' --coverage=false --testTimeout=120000","prepare":"husky"},"dependencies":{"@types/luxon":"~3.4.0","luxon":"~3.5.0"},"devDependencies":{"@commitlint/cli":"19.6.0","@eslint/js":"^9.14.0","@fast-check/jest":"2.0.3","@insurgent/commitlint-config":"20.0.0","@insurgent/conventional-changelog-preset":"10.0.0","@semantic-release/changelog":"6.0.3","@semantic-release/commit-analyzer":"13.0.0","@semantic-release/git":"10.0.1","@semantic-release/github":"11.0.1","@semantic-release/npm":"12.0.1","@semantic-release/release-notes-generator":"14.0.1","@types/jest":"29.5.14","@types/node":"20.17.9","@types/sinon":"17.0.3","chai":"4.5.0","eslint":"8.57.1","eslint-config-prettier":"9.1.0","eslint-plugin-jest":"27.9.0","eslint-plugin-prettier":"5.2.1","husky":"9.1.7","jest":"29.7.0","lint-staged":"15.2.10","prettier":"3.3.3","semantic-release":"24.2.0","sinon":"17.0.2","ts-jest":"29.2.5","typescript":"5.7.2","typescript-eslint":"^7.2.0"},"keywords":["cron","node cron","node-cron","schedule","scheduler","cronjob","cron job"],"license":"MIT","contributors":["Brandon der Blätter <https://interlucid.com/contact/> (https://github.com/intcreator)","Pierre Cavin <me@sherlox.io> (https://github.com/sheerlox)","Romain Beauxis <toots@rastageeks.org> (https://github.com/toots)","James Padolsey <> (https://github.com/jamespadolsey)","Finn Herpich <fh@three-heads.de> (https://github.com/ErrorProne)","Clifton Cunningham <clifton.cunningham@gmail.com> (https://github.com/cliftonc)","Eric Abouaf <eric.abouaf@gmail.com> (https://github.com/neyric)","humanchimp <morphcham@gmail.com> (https://github.com/humanchimp)","Craig Condon <craig@spiceapps.com> (https://github.com/spiceapps)","Dan Bear <daniel@hulu.com> (https://github.com/danhbear)","Vadim Baryshev <vadimbaryshev@gmail.com> (https://github.com/baryshev)","Leandro Ferrari <lfthomaz@gmail.com> (https://github.com/lfthomaz)","Gregg Zigler <greggzigler@gmail.com> (https://github.com/greggzigler)","Jordan Abderrachid <jabderrachid@gmail.com> (https://github.com/jordanabderrachid)","Masakazu Matsushita <matsukaz@gmail.com> (matsukaz)","Christopher Lunt <me@kirisu.co.uk> (https://github.com/kirisu)"],"files":["dist/**/*.js","dist/**/*.d.ts","CHANGELOG.md","LICENSE","README.md"],"lint-staged":{"*.ts":"eslint src/ tests/ --fix","*.{json,md,yml}":"prettier ./**/*.{json,md,yml} --check --write"},"_lastModified":"2025-
|
|
1
|
+
{"name":"cron","description":"Cron jobs for your node","version":"3.3.1","author":"Nick Campbell <nicholas.j.campbell@gmail.com> (https://github.com/ncb000gt)","bugs":{"url":"https://github.com/kelektiv/node-cron/issues"},"repository":{"type":"git","url":"https://github.com/kelektiv/node-cron.git"},"main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc -b tsconfig.build.json","lint:eslint":"eslint src/ tests/","lint:prettier":"prettier ./**/*.{json,md,yml} --check","lint":"npm run lint:eslint && npm run lint:prettier","lint:fix":"npm run lint:eslint -- --fix && npm run lint:prettier -- --write","test":"jest --coverage","test:watch":"jest --watch --coverage","test:fuzz":"jest --testMatch='**/*.fuzz.ts' --coverage=false --testTimeout=120000","prepare":"husky"},"dependencies":{"@types/luxon":"~3.4.0","luxon":"~3.5.0"},"devDependencies":{"@commitlint/cli":"19.6.0","@eslint/js":"^9.14.0","@fast-check/jest":"2.0.3","@insurgent/commitlint-config":"20.0.0","@insurgent/conventional-changelog-preset":"10.0.0","@semantic-release/changelog":"6.0.3","@semantic-release/commit-analyzer":"13.0.0","@semantic-release/git":"10.0.1","@semantic-release/github":"11.0.1","@semantic-release/npm":"12.0.1","@semantic-release/release-notes-generator":"14.0.1","@types/jest":"29.5.14","@types/node":"20.17.9","@types/sinon":"17.0.3","chai":"4.5.0","eslint":"8.57.1","eslint-config-prettier":"9.1.0","eslint-plugin-jest":"27.9.0","eslint-plugin-prettier":"5.2.1","husky":"9.1.7","jest":"29.7.0","lint-staged":"15.2.10","prettier":"3.3.3","semantic-release":"24.2.0","sinon":"17.0.2","ts-jest":"29.2.5","typescript":"5.7.2","typescript-eslint":"^7.2.0"},"keywords":["cron","node cron","node-cron","schedule","scheduler","cronjob","cron job"],"license":"MIT","contributors":["Brandon der Blätter <https://interlucid.com/contact/> (https://github.com/intcreator)","Pierre Cavin <me@sherlox.io> (https://github.com/sheerlox)","Romain Beauxis <toots@rastageeks.org> (https://github.com/toots)","James Padolsey <> (https://github.com/jamespadolsey)","Finn Herpich <fh@three-heads.de> (https://github.com/ErrorProne)","Clifton Cunningham <clifton.cunningham@gmail.com> (https://github.com/cliftonc)","Eric Abouaf <eric.abouaf@gmail.com> (https://github.com/neyric)","humanchimp <morphcham@gmail.com> (https://github.com/humanchimp)","Craig Condon <craig@spiceapps.com> (https://github.com/spiceapps)","Dan Bear <daniel@hulu.com> (https://github.com/danhbear)","Vadim Baryshev <vadimbaryshev@gmail.com> (https://github.com/baryshev)","Leandro Ferrari <lfthomaz@gmail.com> (https://github.com/lfthomaz)","Gregg Zigler <greggzigler@gmail.com> (https://github.com/greggzigler)","Jordan Abderrachid <jabderrachid@gmail.com> (https://github.com/jordanabderrachid)","Masakazu Matsushita <matsukaz@gmail.com> (matsukaz)","Christopher Lunt <me@kirisu.co.uk> (https://github.com/kirisu)"],"files":["dist/**/*.js","dist/**/*.d.ts","CHANGELOG.md","LICENSE","README.md"],"lint-staged":{"*.ts":"eslint src/ tests/ --fix","*.{json,md,yml}":"prettier ./**/*.{json,md,yml} --check --write"},"_lastModified":"2025-04-02T02:55:46.942Z"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){var e={134:function(e){var r=1e3;var s=r*60;var a=s*60;var n=a*24;var t=n*7;var u=n*365.25;e.exports=function(e,r){r=r||{};var s=typeof e;if(s==="string"&&e.length>0){return parse(e)}else if(s==="number"&&isFinite(e)){return r.long?fmtLong(e):fmtShort(e)}throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(e))};function parse(e){e=String(e);if(e.length>100){return}var c=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(e);if(!c){return}var i=parseFloat(c[1]);var o=(c[2]||"ms").toLowerCase();switch(o){case"years":case"year":case"yrs":case"yr":case"y":return i*u;case"weeks":case"week":case"w":return i*t;case"days":case"day":case"d":return i*n;case"hours":case"hour":case"hrs":case"hr":case"h":return i*a;case"minutes":case"minute":case"mins":case"min":case"m":return i*s;case"seconds":case"second":case"secs":case"sec":case"s":return i*r;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return i;default:return undefined}}function fmtShort(e){var t=Math.abs(e);if(t>=n){return Math.round(e/n)+"d"}if(t>=a){return Math.round(e/a)+"h"}if(t>=s){return Math.round(e/s)+"m"}if(t>=r){return Math.round(e/r)+"s"}return e+"ms"}function fmtLong(e){var t=Math.abs(e);if(t>=n){return plural(e,t,n,"day")}if(t>=a){return plural(e,t,a,"hour")}if(t>=s){return plural(e,t,s,"minute")}if(t>=r){return plural(e,t,r,"second")}return e+" ms"}function plural(e,r,s,a){var n=r>=s*1.5;return Math.round(e/s)+" "+a+(n?"s":"")}}};var r={};function __nccwpck_require__(s){var a=r[s];if(a!==undefined){return a.exports}var n=r[s]={exports:{}};var t=true;try{e[s](n,n.exports,__nccwpck_require__);t=false}finally{if(t)delete r[s]}return n.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var s=__nccwpck_require__(134);module.exports=s})();
|
|
@@ -0,0 +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":"2025-04-02T02:55:47.034Z"}
|
|
@@ -59,12 +59,12 @@ class BasicAuth extends import_auth.BaseAuth {
|
|
|
59
59
|
filter
|
|
60
60
|
});
|
|
61
61
|
if (!user) {
|
|
62
|
-
ctx.throw(401, ctx.t("The username or
|
|
62
|
+
ctx.throw(401, ctx.t("The username, email or password is incorrect, please re-enter", { ns: import_preset.namespace }));
|
|
63
63
|
}
|
|
64
64
|
const field = this.userCollection.getField("password");
|
|
65
65
|
const valid = await field.verify(password, user.password);
|
|
66
66
|
if (!valid) {
|
|
67
|
-
ctx.throw(401, ctx.t("The password is incorrect, please re-enter", { ns: import_preset.namespace }));
|
|
67
|
+
ctx.throw(401, ctx.t("The username, email or password is incorrect, please re-enter", { ns: import_preset.namespace }));
|
|
68
68
|
}
|
|
69
69
|
return user;
|
|
70
70
|
}
|
|
@@ -163,7 +163,7 @@ class BasicAuth extends import_auth.BaseAuth {
|
|
|
163
163
|
const pwd = this.userCollection.getField("password");
|
|
164
164
|
const isValid = await pwd.verify(oldPassword, user.password);
|
|
165
165
|
if (!isValid) {
|
|
166
|
-
ctx.throw(401, ctx.t("The password is incorrect, please re-enter", { ns: import_preset.namespace }));
|
|
166
|
+
ctx.throw(401, ctx.t("The username, email or password is incorrect, please re-enter", { ns: import_preset.namespace }));
|
|
167
167
|
}
|
|
168
168
|
user.password = newPassword;
|
|
169
169
|
await user.save();
|
|
@@ -33,14 +33,6 @@ var authenticators_default = (0, import_database.defineCollection)({
|
|
|
33
33
|
updatedBy: true,
|
|
34
34
|
logging: true,
|
|
35
35
|
fields: [
|
|
36
|
-
{
|
|
37
|
-
name: "id",
|
|
38
|
-
type: "bigInt",
|
|
39
|
-
autoIncrement: true,
|
|
40
|
-
primaryKey: true,
|
|
41
|
-
allowNull: false,
|
|
42
|
-
interface: "id"
|
|
43
|
-
},
|
|
44
36
|
{
|
|
45
37
|
interface: "input",
|
|
46
38
|
type: "string",
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var issued_tokens_exports = {};
|
|
19
|
+
__export(issued_tokens_exports, {
|
|
20
|
+
default: () => issued_tokens_default
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(issued_tokens_exports);
|
|
23
|
+
var import_database = require("@tachybase/database");
|
|
24
|
+
var import_constants = require("../../constants");
|
|
25
|
+
var issued_tokens_default = (0, import_database.defineCollection)({
|
|
26
|
+
name: import_constants.issuedTokensCollectionName,
|
|
27
|
+
autoGenId: false,
|
|
28
|
+
createdAt: true,
|
|
29
|
+
updatedAt: true,
|
|
30
|
+
fields: [
|
|
31
|
+
{
|
|
32
|
+
name: "id",
|
|
33
|
+
type: "uuid",
|
|
34
|
+
primaryKey: true,
|
|
35
|
+
allowNull: false,
|
|
36
|
+
interface: "input"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
type: "bigInt",
|
|
40
|
+
name: "signInTime",
|
|
41
|
+
allowNull: false
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "jti",
|
|
45
|
+
type: "uuid",
|
|
46
|
+
allowNull: false,
|
|
47
|
+
index: true
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: "bigInt",
|
|
51
|
+
name: "issuedTime",
|
|
52
|
+
allowNull: false
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: "bigInt",
|
|
56
|
+
name: "userId",
|
|
57
|
+
allowNull: false
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var token_poilcy_config_exports = {};
|
|
19
|
+
__export(token_poilcy_config_exports, {
|
|
20
|
+
default: () => token_poilcy_config_default
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(token_poilcy_config_exports);
|
|
23
|
+
var import_database = require("@tachybase/database");
|
|
24
|
+
var import_constants = require("../../constants");
|
|
25
|
+
var token_poilcy_config_default = (0, import_database.defineCollection)({
|
|
26
|
+
name: import_constants.tokenPolicyCollectionName,
|
|
27
|
+
autoGenId: false,
|
|
28
|
+
createdAt: true,
|
|
29
|
+
createdBy: true,
|
|
30
|
+
updatedAt: true,
|
|
31
|
+
updatedBy: true,
|
|
32
|
+
fields: [
|
|
33
|
+
{
|
|
34
|
+
name: "key",
|
|
35
|
+
type: "string",
|
|
36
|
+
primaryKey: true,
|
|
37
|
+
allowNull: false,
|
|
38
|
+
interface: "input"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: "json",
|
|
42
|
+
name: "config",
|
|
43
|
+
allowNull: false,
|
|
44
|
+
defaultValue: {}
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
});
|
|
@@ -36,7 +36,6 @@ var users_authenticators_default = (0, import_database.defineCollection)({
|
|
|
36
36
|
name: "id",
|
|
37
37
|
type: "bigInt",
|
|
38
38
|
autoIncrement: true,
|
|
39
|
-
primaryKey: true,
|
|
40
39
|
allowNull: false
|
|
41
40
|
},
|
|
42
41
|
/**
|
|
@@ -87,6 +86,16 @@ var users_authenticators_default = (0, import_database.defineCollection)({
|
|
|
87
86
|
type: "json",
|
|
88
87
|
name: "meta",
|
|
89
88
|
defaultValue: {}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
type: "bigInt",
|
|
92
|
+
name: "userId",
|
|
93
|
+
primaryKey: true
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: "string",
|
|
97
|
+
name: "authenticator",
|
|
98
|
+
primaryKey: true
|
|
90
99
|
}
|
|
91
100
|
]
|
|
92
101
|
});
|
|
@@ -5,5 +5,6 @@ declare const _default: {
|
|
|
5
5
|
'Not a valid cellphone number, please re-enter': string;
|
|
6
6
|
'The phone number has been registered, please login directly': string;
|
|
7
7
|
'The phone number is not registered, please register first': string;
|
|
8
|
+
'The username, email or password is incorrect, please re-enter': string;
|
|
8
9
|
};
|
|
9
10
|
export default _default;
|
|
@@ -26,5 +26,6 @@ var en_US_default = {
|
|
|
26
26
|
"The password is incorrect, please re-enter": "The password is incorrect, please re-enter",
|
|
27
27
|
"Not a valid cellphone number, please re-enter": "Not a valid cellphone number, please re-enter",
|
|
28
28
|
"The phone number has been registered, please login directly": "The phone number has been registered, please login directly",
|
|
29
|
-
"The phone number is not registered, please register first": "The phone number is not registered, please register first"
|
|
29
|
+
"The phone number is not registered, please register first": "The phone number is not registered, please register first",
|
|
30
|
+
"The username, email or password is incorrect, please re-enter": "The username, email or password is incorrect, please re-enter"
|
|
30
31
|
};
|
|
@@ -7,5 +7,6 @@ declare const _default: {
|
|
|
7
7
|
'Please keep and enable at least one authenticator': string;
|
|
8
8
|
'Please enter your username or email': string;
|
|
9
9
|
'Please enter a valid username': string;
|
|
10
|
+
'The username, email or password is incorrect, please re-enter': string;
|
|
10
11
|
};
|
|
11
12
|
export default _default;
|
|
@@ -28,5 +28,6 @@ var zh_CN_default = {
|
|
|
28
28
|
"The phone number is not registered, please register first": "\u624B\u673A\u53F7\u672A\u6CE8\u518C\uFF0C\u8BF7\u5148\u6CE8\u518C",
|
|
29
29
|
"Please keep and enable at least one authenticator": "\u8BF7\u81F3\u5C11\u4FDD\u7559\u5E76\u542F\u7528\u4E00\u4E2A\u8BA4\u8BC1\u5668",
|
|
30
30
|
"Please enter your username or email": "\u8BF7\u8F93\u5165\u7528\u6237\u540D\u6216\u90AE\u7BB1",
|
|
31
|
-
"Please enter a valid username": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u7528\u6237\u540D"
|
|
31
|
+
"Please enter a valid username": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u7528\u6237\u540D",
|
|
32
|
+
"The username, email or password is incorrect, please re-enter": "\u7528\u6237\u540D\u90AE\u7BB1\u6216\u8005\u5BC6\u7801\u6709\u8BEF,\u8BF7\u91CD\u65B0\u8F93\u5165"
|
|
32
33
|
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var create_token_policy_exports = {};
|
|
19
|
+
__export(create_token_policy_exports, {
|
|
20
|
+
default: () => create_token_policy_default
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(create_token_policy_exports);
|
|
23
|
+
var import_server = require("@tachybase/server");
|
|
24
|
+
var import_constants = require("../../constants");
|
|
25
|
+
class create_token_policy_default extends import_server.Migration {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(...arguments);
|
|
28
|
+
this.on = "afterLoad";
|
|
29
|
+
// 'beforeLoad' or 'afterLoad'
|
|
30
|
+
this.appVersion = "<0.23.65";
|
|
31
|
+
}
|
|
32
|
+
async up() {
|
|
33
|
+
const tokenPolicyRepo = this.app.db.getRepository(import_constants.tokenPolicyCollectionName);
|
|
34
|
+
const tokenPolicy = await tokenPolicyRepo.findOne({ filterByTk: import_constants.tokenPolicyRecordKey });
|
|
35
|
+
if (tokenPolicy) {
|
|
36
|
+
this.app.authManager.tokenController.setConfig(tokenPolicy.config);
|
|
37
|
+
} else {
|
|
38
|
+
const config = {
|
|
39
|
+
tokenExpirationTime: "1d",
|
|
40
|
+
sessionExpirationTime: "7d",
|
|
41
|
+
expiredTokenRenewLimit: "1d"
|
|
42
|
+
};
|
|
43
|
+
await tokenPolicyRepo.create({
|
|
44
|
+
values: {
|
|
45
|
+
key: import_constants.tokenPolicyRecordKey,
|
|
46
|
+
config
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
this.app.authManager.tokenController.setConfig(config);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
package/dist/server/plugin.js
CHANGED
|
@@ -31,8 +31,8 @@ __export(plugin_exports, {
|
|
|
31
31
|
default: () => plugin_default
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(plugin_exports);
|
|
34
|
-
var import_path = require("path");
|
|
35
34
|
var import_server = require("@tachybase/server");
|
|
35
|
+
var import_constants = require("../constants");
|
|
36
36
|
var import_preset = require("../preset");
|
|
37
37
|
var import_auth = __toESM(require("./actions/auth"));
|
|
38
38
|
var import_authenticators = __toESM(require("./actions/authenticators"));
|
|
@@ -41,8 +41,29 @@ var import_locale = require("./locale");
|
|
|
41
41
|
var import_authenticator = require("./model/authenticator");
|
|
42
42
|
var import_storer = require("./storer");
|
|
43
43
|
var import_token_blacklist = require("./token-blacklist");
|
|
44
|
+
var import_token_controller = require("./token-controller");
|
|
44
45
|
class PluginAuthServer extends import_server.Plugin {
|
|
45
46
|
afterAdd() {
|
|
47
|
+
this.app.on("afterLoad", async () => {
|
|
48
|
+
if (this.app.authManager.tokenController) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const cache = await this.app.cacheManager.createCache({
|
|
52
|
+
name: "auth-token-controller",
|
|
53
|
+
prefix: "auth-token-controller"
|
|
54
|
+
});
|
|
55
|
+
const tokenController = new import_token_controller.TokenController({ cache, app: this.app, logger: this.app.log });
|
|
56
|
+
this.app.authManager.setTokenControlService(tokenController);
|
|
57
|
+
const tokenPolicyRepo = this.app.db.getRepository(import_constants.tokenPolicyCollectionName);
|
|
58
|
+
try {
|
|
59
|
+
const res = await tokenPolicyRepo.findOne({ filterByTk: import_constants.tokenPolicyRecordKey });
|
|
60
|
+
if (res) {
|
|
61
|
+
this.app.authManager.tokenController.setConfig(res.config);
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
this.app.logger.warn("access control config not exist, use default value");
|
|
65
|
+
}
|
|
66
|
+
});
|
|
46
67
|
}
|
|
47
68
|
async beforeLoad() {
|
|
48
69
|
this.app.i18n.addResources("zh-CN", import_preset.namespace, import_locale.zhCN);
|
|
@@ -50,14 +71,6 @@ class PluginAuthServer extends import_server.Plugin {
|
|
|
50
71
|
this.app.db.registerModels({ AuthModel: import_authenticator.AuthModel });
|
|
51
72
|
}
|
|
52
73
|
async load() {
|
|
53
|
-
await this.importCollections((0, import_path.resolve)(__dirname, "collections"));
|
|
54
|
-
this.db.addMigrations({
|
|
55
|
-
namespace: "auth",
|
|
56
|
-
directory: (0, import_path.resolve)(__dirname, "migrations"),
|
|
57
|
-
context: {
|
|
58
|
-
plugin: this
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
74
|
this.cache = await this.app.cacheManager.createCache({
|
|
62
75
|
name: "auth",
|
|
63
76
|
prefix: "auth",
|
|
@@ -75,7 +88,33 @@ class PluginAuthServer extends import_server.Plugin {
|
|
|
75
88
|
}
|
|
76
89
|
this.app.authManager.registerTypes(import_preset.presetAuthType, {
|
|
77
90
|
auth: import_basic_auth.BasicAuth,
|
|
78
|
-
title: "Password"
|
|
91
|
+
title: "Password",
|
|
92
|
+
getPublicOptions: (options) => {
|
|
93
|
+
var _a;
|
|
94
|
+
const usersCollection = this.db.getCollection("users");
|
|
95
|
+
let signupForm = ((_a = options == null ? void 0 : options.public) == null ? void 0 : _a.signupForm) || [];
|
|
96
|
+
signupForm = signupForm.filter((item) => item.show);
|
|
97
|
+
if (!(signupForm.length && signupForm.some(
|
|
98
|
+
(item) => ["username", "email"].includes(item.field) && item.show && item.required
|
|
99
|
+
))) {
|
|
100
|
+
signupForm.unshift({ field: "username", show: true, required: true });
|
|
101
|
+
}
|
|
102
|
+
signupForm = signupForm.filter((field) => field.show).map((item) => {
|
|
103
|
+
var _a2;
|
|
104
|
+
const field = usersCollection.getField(item.field);
|
|
105
|
+
return {
|
|
106
|
+
...item,
|
|
107
|
+
uiSchema: {
|
|
108
|
+
...(_a2 = field.options) == null ? void 0 : _a2.uiSchema,
|
|
109
|
+
required: item.required
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
...options == null ? void 0 : options.public,
|
|
115
|
+
signupForm
|
|
116
|
+
};
|
|
117
|
+
}
|
|
79
118
|
});
|
|
80
119
|
Object.entries(import_auth.default).forEach(
|
|
81
120
|
([action, handler]) => {
|
|
@@ -86,10 +125,9 @@ class PluginAuthServer extends import_server.Plugin {
|
|
|
86
125
|
Object.entries(import_authenticators.default).forEach(
|
|
87
126
|
([action, handler]) => this.app.resourcer.registerAction(`authenticators:${action}`, handler)
|
|
88
127
|
);
|
|
89
|
-
["
|
|
90
|
-
["signOut", "changePassword"].forEach((action) => this.app.acl.allow("auth", action, "loggedIn"));
|
|
128
|
+
["signIn", "signUp"].forEach((action) => this.app.acl.allow("auth", action));
|
|
129
|
+
["check", "signOut", "changePassword"].forEach((action) => this.app.acl.allow("auth", action, "loggedIn"));
|
|
91
130
|
this.app.acl.allow("authenticators", "publicList");
|
|
92
|
-
this.app.acl.allow("authenticators", "bindTypes", "loggedIn");
|
|
93
131
|
this.app.acl.registerSnippet({
|
|
94
132
|
name: `pm.${this.name}.authenticators`,
|
|
95
133
|
actions: ["authenticators:*"]
|
|
@@ -102,24 +140,93 @@ class PluginAuthServer extends import_server.Plugin {
|
|
|
102
140
|
const cache = this.app.cache;
|
|
103
141
|
await cache.del(`auth:${user.id}`);
|
|
104
142
|
});
|
|
143
|
+
this.app.on("cache:del:auth", async ({ userId }) => {
|
|
144
|
+
await this.cache.del(`auth:${userId}`);
|
|
145
|
+
});
|
|
146
|
+
this.app.on("ws:message:auth:token", async ({ clientId, payload }) => {
|
|
147
|
+
if (!payload || !payload.token || !payload.authenticator) {
|
|
148
|
+
this.app.emit(`ws:removeTag`, {
|
|
149
|
+
clientId,
|
|
150
|
+
tagKey: "userId"
|
|
151
|
+
});
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const auth = await this.app.authManager.get(payload.authenticator, {
|
|
155
|
+
getBearerToken: () => payload.token,
|
|
156
|
+
app: this.app,
|
|
157
|
+
db: this.app.db,
|
|
158
|
+
cache: this.app.cache,
|
|
159
|
+
logger: this.app.logger,
|
|
160
|
+
log: this.app.log,
|
|
161
|
+
throw: (...args) => {
|
|
162
|
+
throw new Error(...args);
|
|
163
|
+
},
|
|
164
|
+
t: this.app.i18n.t
|
|
165
|
+
});
|
|
166
|
+
let user;
|
|
167
|
+
try {
|
|
168
|
+
user = (await auth.checkToken()).user;
|
|
169
|
+
} catch (error) {
|
|
170
|
+
if (!user) {
|
|
171
|
+
this.app.logger.error(error);
|
|
172
|
+
this.app.emit(`ws:removeTag`, {
|
|
173
|
+
clientId,
|
|
174
|
+
tagKey: "userId"
|
|
175
|
+
});
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
this.app.emit(`ws:setTag`, {
|
|
180
|
+
clientId,
|
|
181
|
+
tagKey: "userId",
|
|
182
|
+
tagValue: user.id
|
|
183
|
+
});
|
|
184
|
+
this.app.emit(`ws:authorized`, {
|
|
185
|
+
clientId,
|
|
186
|
+
userId: user.id
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
this.app.acl.registerSnippet({
|
|
190
|
+
name: `pm.security.token-policy`,
|
|
191
|
+
actions: [`${import_constants.tokenPolicyCollectionName}:*`]
|
|
192
|
+
});
|
|
193
|
+
this.app.db.on(`${import_constants.tokenPolicyCollectionName}.afterSave`, async (model) => {
|
|
194
|
+
var _a;
|
|
195
|
+
(_a = this.app.authManager.tokenController) == null ? void 0 : _a.setConfig(model.config);
|
|
196
|
+
});
|
|
105
197
|
}
|
|
106
198
|
async install(options) {
|
|
107
|
-
const
|
|
108
|
-
const exist = await
|
|
109
|
-
if (exist) {
|
|
199
|
+
const authRepository = this.db.getRepository("authenticators");
|
|
200
|
+
const exist = await authRepository.findOne({ filter: { name: import_preset.presetAuthenticator } });
|
|
201
|
+
if (!exist) {
|
|
202
|
+
await authRepository.create({
|
|
203
|
+
values: {
|
|
204
|
+
name: import_preset.presetAuthenticator,
|
|
205
|
+
authType: import_preset.presetAuthType,
|
|
206
|
+
description: "Sign in with username/email.",
|
|
207
|
+
enabled: true,
|
|
208
|
+
options: {
|
|
209
|
+
public: {
|
|
210
|
+
allowSignUp: true
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const tokenPolicyRepo = this.app.db.getRepository(import_constants.tokenPolicyCollectionName);
|
|
217
|
+
const res = await tokenPolicyRepo.findOne({ filterByTk: import_constants.tokenPolicyRecordKey });
|
|
218
|
+
if (res) {
|
|
110
219
|
return;
|
|
111
220
|
}
|
|
112
|
-
|
|
221
|
+
const config = {
|
|
222
|
+
tokenExpirationTime: "1d",
|
|
223
|
+
sessionExpirationTime: "7d",
|
|
224
|
+
expiredTokenRenewLimit: "1d"
|
|
225
|
+
};
|
|
226
|
+
await tokenPolicyRepo.create({
|
|
113
227
|
values: {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
description: "Sign in with username/email.",
|
|
117
|
-
enabled: true,
|
|
118
|
-
options: {
|
|
119
|
-
public: {
|
|
120
|
-
allowSignUp: true
|
|
121
|
-
}
|
|
122
|
-
}
|
|
228
|
+
key: import_constants.tokenPolicyRecordKey,
|
|
229
|
+
config
|
|
123
230
|
}
|
|
124
231
|
});
|
|
125
232
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ITokenControlService, NumericTokenPolicyConfig, TokenInfo, TokenPolicyConfig } from '@tachybase/auth';
|
|
2
|
+
import { Cache } from '@tachybase/cache';
|
|
3
|
+
import Database from '@tachybase/database';
|
|
4
|
+
import type { SystemLogger } from '@tachybase/logger';
|
|
5
|
+
import Application from '@tachybase/server';
|
|
6
|
+
type TokenControlService = ITokenControlService;
|
|
7
|
+
export declare class TokenController implements TokenControlService {
|
|
8
|
+
cache: Cache;
|
|
9
|
+
app: Application;
|
|
10
|
+
db: Database;
|
|
11
|
+
logger: SystemLogger;
|
|
12
|
+
constructor({ cache, app, logger }: {
|
|
13
|
+
cache: Cache;
|
|
14
|
+
app: Application;
|
|
15
|
+
logger: SystemLogger;
|
|
16
|
+
});
|
|
17
|
+
setTokenInfo(id: string, value: TokenInfo): Promise<void>;
|
|
18
|
+
getConfig(): Promise<NumericTokenPolicyConfig>;
|
|
19
|
+
setConfig(config: TokenPolicyConfig): Promise<void>;
|
|
20
|
+
removeSessionExpiredTokens(userId: number): Promise<any>;
|
|
21
|
+
add({ userId }: {
|
|
22
|
+
userId: number;
|
|
23
|
+
}): Promise<{
|
|
24
|
+
jti: `${string}-${string}-${string}-${string}-${string}`;
|
|
25
|
+
issuedTime: number;
|
|
26
|
+
signInTime: number;
|
|
27
|
+
renewed: boolean;
|
|
28
|
+
userId: number;
|
|
29
|
+
}>;
|
|
30
|
+
renew: TokenControlService['renew'];
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var token_controller_exports = {};
|
|
29
|
+
__export(token_controller_exports, {
|
|
30
|
+
TokenController: () => TokenController
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(token_controller_exports);
|
|
33
|
+
var import_crypto = require("crypto");
|
|
34
|
+
var import_auth = require("@tachybase/auth");
|
|
35
|
+
var import_ms = __toESM(require("ms"));
|
|
36
|
+
var import_constants = require("../constants");
|
|
37
|
+
const JTICACHEKEY = "token-jti";
|
|
38
|
+
class TokenController {
|
|
39
|
+
constructor({ cache, app, logger }) {
|
|
40
|
+
this.renew = async (jti) => {
|
|
41
|
+
const repo = this.app.db.getRepository(import_constants.issuedTokensCollectionName);
|
|
42
|
+
const model = this.app.db.getModel(import_constants.issuedTokensCollectionName);
|
|
43
|
+
const newId = (0, import_crypto.randomUUID)();
|
|
44
|
+
const issuedTime = Date.now();
|
|
45
|
+
const [count] = await model.update(
|
|
46
|
+
{ jti: newId, issuedTime },
|
|
47
|
+
{ where: { jti } }
|
|
48
|
+
);
|
|
49
|
+
if (count === 1) {
|
|
50
|
+
await this.cache.set(`jti-renewed-cahce:${jti}`, { jti: newId, issuedTime }, import_constants.RENEWED_JTI_CACHE_MS);
|
|
51
|
+
this.logger.info("jti renewed", { oldJti: jti, newJti: newId, issuedTime });
|
|
52
|
+
return { jti: newId, issuedTime };
|
|
53
|
+
} else {
|
|
54
|
+
const cachedJtiData = await this.cache.get(`jti-renewed-cahce:${jti}`);
|
|
55
|
+
if (cachedJtiData) {
|
|
56
|
+
return cachedJtiData;
|
|
57
|
+
}
|
|
58
|
+
this.logger.error("jti renew failed", {
|
|
59
|
+
module: "auth",
|
|
60
|
+
submodule: "token-controller",
|
|
61
|
+
method: "renew",
|
|
62
|
+
jti,
|
|
63
|
+
code: import_auth.AuthErrorCode.TOKEN_RENEW_FAILED
|
|
64
|
+
});
|
|
65
|
+
throw new import_auth.AuthError({
|
|
66
|
+
message: "Your session has expired. Please sign in again.",
|
|
67
|
+
code: import_auth.AuthErrorCode.TOKEN_RENEW_FAILED
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
this.cache = cache;
|
|
72
|
+
this.app = app;
|
|
73
|
+
this.logger = logger;
|
|
74
|
+
}
|
|
75
|
+
async setTokenInfo(id, value) {
|
|
76
|
+
const repo = this.app.db.getRepository(import_constants.issuedTokensCollectionName);
|
|
77
|
+
await repo.updateOrCreate({ filterKeys: ["id"], values: value });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
getConfig() {
|
|
81
|
+
return this.cache.wrap("config", async () => {
|
|
82
|
+
const repo = this.app.db.getRepository(import_constants.tokenPolicyCollectionName);
|
|
83
|
+
const configRecord = await repo.findOne({ filterByTk: import_constants.tokenPolicyRecordKey });
|
|
84
|
+
if (!configRecord) return null;
|
|
85
|
+
const config = configRecord.config;
|
|
86
|
+
return {
|
|
87
|
+
tokenExpirationTime: (0, import_ms.default)(config.tokenExpirationTime),
|
|
88
|
+
sessionExpirationTime: (0, import_ms.default)(config.sessionExpirationTime),
|
|
89
|
+
expiredTokenRenewLimit: (0, import_ms.default)(config.expiredTokenRenewLimit)
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
setConfig(config) {
|
|
94
|
+
return this.cache.set("config", {
|
|
95
|
+
tokenExpirationTime: (0, import_ms.default)(config.tokenExpirationTime),
|
|
96
|
+
sessionExpirationTime: (0, import_ms.default)(config.sessionExpirationTime),
|
|
97
|
+
expiredTokenRenewLimit: (0, import_ms.default)(config.expiredTokenRenewLimit)
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async removeSessionExpiredTokens(userId) {
|
|
101
|
+
const config = await this.getConfig();
|
|
102
|
+
const issuedTokenRepo = this.app.db.getRepository(import_constants.issuedTokensCollectionName);
|
|
103
|
+
const currTS = Date.now();
|
|
104
|
+
return issuedTokenRepo.destroy({
|
|
105
|
+
filter: {
|
|
106
|
+
userId,
|
|
107
|
+
signInTime: {
|
|
108
|
+
$lt: currTS - config.sessionExpirationTime
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
async add({ userId }) {
|
|
114
|
+
const jti = (0, import_crypto.randomUUID)();
|
|
115
|
+
const currTS = Date.now();
|
|
116
|
+
const data = {
|
|
117
|
+
jti,
|
|
118
|
+
issuedTime: currTS,
|
|
119
|
+
signInTime: currTS,
|
|
120
|
+
renewed: false,
|
|
121
|
+
userId
|
|
122
|
+
};
|
|
123
|
+
await this.setTokenInfo(jti, data);
|
|
124
|
+
try {
|
|
125
|
+
if (process.env.DB_DIALECT === "sqlite") {
|
|
126
|
+
await this.removeSessionExpiredTokens(userId);
|
|
127
|
+
} else {
|
|
128
|
+
this.removeSessionExpiredTokens(userId);
|
|
129
|
+
}
|
|
130
|
+
} catch (err) {
|
|
131
|
+
this.logger.error(err, { module: "auth", submodule: "token-controller", method: "removeSessionExpiredTokens" });
|
|
132
|
+
}
|
|
133
|
+
return data;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
137
|
+
0 && (module.exports = {
|
|
138
|
+
TokenController
|
|
139
|
+
});
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { TokenPolicyConfig as TokenPolicyConfig } from '@tachybase/auth';
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __copyProps = (to, from, except, desc) => {
|
|
6
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
7
|
+
for (let key of __getOwnPropNames(from))
|
|
8
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
9
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
10
|
+
}
|
|
11
|
+
return to;
|
|
12
|
+
};
|
|
13
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
14
|
+
var types_exports = {};
|
|
15
|
+
module.exports = __toCommonJS(types_exports);
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tachybase/module-auth",
|
|
3
3
|
"displayName": "Authentication",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.6",
|
|
5
5
|
"description": "User authentication management, including password, SMS, and support for Single Sign-On (SSO) protocols, with extensibility.",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"Authentication"
|
|
7
|
+
"Authentication",
|
|
8
|
+
"Security"
|
|
8
9
|
],
|
|
9
10
|
"main": "./dist/server/index.js",
|
|
10
11
|
"dependencies": {},
|
|
@@ -12,20 +13,23 @@
|
|
|
12
13
|
"@ant-design/icons": "~5.3.7",
|
|
13
14
|
"antd": "5.22.5",
|
|
14
15
|
"cron": "^3.3.1",
|
|
16
|
+
"lodash": "^4.17.21",
|
|
17
|
+
"ms": "^2.1.3",
|
|
15
18
|
"react": "^18.3.1",
|
|
16
19
|
"react-i18next": "^15.2.0",
|
|
17
20
|
"react-router-dom": "6.28.1",
|
|
18
|
-
"@tachybase/schema": "0.
|
|
21
|
+
"@tachybase/schema": "1.0.6"
|
|
19
22
|
},
|
|
20
23
|
"peerDependencies": {
|
|
21
|
-
"@tachybase/actions": "0.
|
|
22
|
-
"@tachybase/auth": "0.
|
|
23
|
-
"@tachybase/
|
|
24
|
-
"@tachybase/
|
|
25
|
-
"@tachybase/
|
|
26
|
-
"@tachybase/
|
|
27
|
-
"@tachybase/
|
|
28
|
-
"@tachybase/
|
|
24
|
+
"@tachybase/actions": "1.0.6",
|
|
25
|
+
"@tachybase/auth": "1.0.6",
|
|
26
|
+
"@tachybase/client": "1.0.6",
|
|
27
|
+
"@tachybase/server": "1.0.6",
|
|
28
|
+
"@tachybase/cache": "1.0.6",
|
|
29
|
+
"@tachybase/logger": "1.0.6",
|
|
30
|
+
"@tachybase/database": "1.0.6",
|
|
31
|
+
"@tachybase/test": "1.0.6",
|
|
32
|
+
"@tachybase/utils": "1.0.6"
|
|
29
33
|
},
|
|
30
34
|
"description.zh-CN": "用户认证管理,包括基础的密码认证、短信认证、SSO 协议的认证等,可扩展。",
|
|
31
35
|
"displayName.zh-CN": "用户认证",
|