@webiny/app-security 0.0.0-mt-2 → 0.0.0-unstable.06b2ede40f
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/README.md +6 -3
- package/Security.d.ts +2 -0
- package/Security.js +20 -0
- package/Security.js.map +1 -0
- package/components/HasPermission.d.ts +9 -0
- package/components/HasPermission.js +30 -0
- package/components/HasPermission.js.map +1 -0
- package/components/SecureRoute.d.ts +5 -4
- package/components/SecureRoute.js +22 -17
- package/components/SecureRoute.js.map +1 -0
- package/components/SecureView.d.ts +4 -4
- package/components/SecureView.js +15 -18
- package/components/SecureView.js.map +1 -0
- package/components/index.d.ts +1 -0
- package/components/index.js +4 -1
- package/components/index.js.map +1 -0
- package/contexts/Security.d.ts +16 -7
- package/contexts/Security.js +50 -28
- package/contexts/Security.js.map +1 -0
- package/hooks/usePermission.d.ts +2 -0
- package/hooks/usePermission.js +9 -0
- package/hooks/usePermission.js.map +1 -0
- package/hooks/useSecurity.d.ts +2 -2
- package/hooks/useSecurity.js +8 -2
- package/hooks/useSecurity.js.map +1 -0
- package/index.d.ts +3 -0
- package/index.js +6 -1
- package/index.js.map +1 -0
- package/package.json +13 -28
- package/types.d.ts +23 -3
- package/types.js +3 -1
- package/types.js.map +1 -0
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ A simple `Authenticator` React component (uses Amazon Cognito and AWS Amplify's
|
|
|
51
51
|
|
|
52
52
|
```tsx
|
|
53
53
|
import React, { useEffect } from "react";
|
|
54
|
-
import Auth from "@aws-amplify/auth";
|
|
54
|
+
import { Auth } from "@aws-amplify/auth";
|
|
55
55
|
import { useSecurity, SecurityIdentity } from "@webiny/app-security";
|
|
56
56
|
|
|
57
57
|
// Apart from the React component, we also configure the Auth class here.
|
|
@@ -67,8 +67,11 @@ Auth.configure({
|
|
|
67
67
|
}
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
+
interface AuthenticatorProps {
|
|
71
|
+
children: React.ReactNode;
|
|
72
|
+
}
|
|
70
73
|
// The `Authenticator` component.
|
|
71
|
-
const Authenticator
|
|
74
|
+
const Authenticator = (props: AuthenticatorProps) => {
|
|
72
75
|
const { setIdentity } = useSecurity();
|
|
73
76
|
|
|
74
77
|
useEffect(() => {
|
|
@@ -101,7 +104,7 @@ Finally, use the `useSecurity` React hook in any of your components:
|
|
|
101
104
|
import React from "react";
|
|
102
105
|
import { useSecurity } from "@webiny/app-security";
|
|
103
106
|
|
|
104
|
-
const MyComponent
|
|
107
|
+
const MyComponent = () => {
|
|
105
108
|
const { identity } = useSecurity();
|
|
106
109
|
|
|
107
110
|
if (identity) {
|
package/Security.d.ts
ADDED
package/Security.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Importing from `app-core` and NOT from `app-admin`, to avoid circular dependency.
|
|
2
|
+
// This can be resolved in a different way, by changing the location of `AppInstaller` component (currently in `app-admin`).
|
|
3
|
+
// But this is a faster solution, as I'm really short on time :)
|
|
4
|
+
import React from "react";
|
|
5
|
+
import { Provider } from "@webiny/app";
|
|
6
|
+
import { SecurityProvider as ContextProvider } from "./contexts/Security";
|
|
7
|
+
const SecurityProviderHOC = Component => {
|
|
8
|
+
return function SecurityProvider({
|
|
9
|
+
children
|
|
10
|
+
}) {
|
|
11
|
+
return /*#__PURE__*/React.createElement(ContextProvider, null, /*#__PURE__*/React.createElement(Component, null, children));
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export const Security = () => {
|
|
15
|
+
return /*#__PURE__*/React.createElement(Provider, {
|
|
16
|
+
hoc: SecurityProviderHOC
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=Security.js.map
|
package/Security.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","Provider","SecurityProvider","ContextProvider","SecurityProviderHOC","Component","children","createElement","Security","hoc"],"sources":["Security.tsx"],"sourcesContent":["// Importing from `app-core` and NOT from `app-admin`, to avoid circular dependency.\n// This can be resolved in a different way, by changing the location of `AppInstaller` component (currently in `app-admin`).\n// But this is a faster solution, as I'm really short on time :)\nimport React from \"react\";\nimport { Provider } from \"@webiny/app\";\nimport { SecurityProvider as ContextProvider } from \"./contexts/Security\";\n\ninterface SecurityProviderProps {\n children: React.ReactNode;\n}\n\nconst SecurityProviderHOC = (Component: React.ComponentType<SecurityProviderProps>) => {\n return function SecurityProvider({ children }: SecurityProviderProps) {\n return (\n <ContextProvider>\n <Component>{children}</Component>\n </ContextProvider>\n );\n };\n};\n\nexport const Security = () => {\n return <Provider hoc={SecurityProviderHOC} />;\n};\n"],"mappings":"AAAA;AACA;AACA;AACA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,QAAQ,QAAQ,aAAa;AACtC,SAASC,gBAAgB,IAAIC,eAAe;AAM5C,MAAMC,mBAAmB,GAAIC,SAAqD,IAAK;EACnF,OAAO,SAASH,gBAAgBA,CAAC;IAAEI;EAAgC,CAAC,EAAE;IAClE,oBACIN,KAAA,CAAAO,aAAA,CAACJ,eAAe,qBACZH,KAAA,CAAAO,aAAA,CAACF,SAAS,QAAEC,QAAoB,CACnB,CAAC;EAE1B,CAAC;AACL,CAAC;AAED,OAAO,MAAME,QAAQ,GAAGA,CAAA,KAAM;EAC1B,oBAAOR,KAAA,CAAAO,aAAA,CAACN,QAAQ;IAACQ,GAAG,EAAEL;EAAoB,CAAE,CAAC;AACjD,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
interface HasPermissionProps {
|
|
3
|
+
any?: string[];
|
|
4
|
+
all?: string[];
|
|
5
|
+
name?: string;
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare const HasPermission: ({ children, ...props }: HasPermissionProps) => React.JSX.Element | null;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { Fragment } from "react";
|
|
2
|
+
import { useSecurity } from "../hooks/useSecurity";
|
|
3
|
+
export const HasPermission = ({
|
|
4
|
+
children,
|
|
5
|
+
...props
|
|
6
|
+
}) => {
|
|
7
|
+
const {
|
|
8
|
+
getPermissions
|
|
9
|
+
} = useSecurity();
|
|
10
|
+
if (props.name) {
|
|
11
|
+
const permissionsCollections = getPermissions(props.name);
|
|
12
|
+
const hasPermission = permissionsCollections.length > 0;
|
|
13
|
+
if (hasPermission) {
|
|
14
|
+
return /*#__PURE__*/React.createElement(Fragment, null, children);
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
if (props.any && props.all) {
|
|
19
|
+
throw new Error(`You can use either "any" or "all", but not both at the same time.`);
|
|
20
|
+
}
|
|
21
|
+
const anyAllPermissions = props.any || props.all || [];
|
|
22
|
+
const permissionsCollections = anyAllPermissions.map(name => getPermissions(name));
|
|
23
|
+
const hasPermission = props.any ? permissionsCollections.some(collection => collection.length > 0) : permissionsCollections.every(collection => collection.length > 0);
|
|
24
|
+
if (hasPermission) {
|
|
25
|
+
return /*#__PURE__*/React.createElement(Fragment, null, children);
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=HasPermission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","Fragment","useSecurity","HasPermission","children","props","getPermissions","name","permissionsCollections","hasPermission","length","createElement","any","all","Error","anyAllPermissions","map","some","collection","every"],"sources":["HasPermission.tsx"],"sourcesContent":["import React, { Fragment } from \"react\";\nimport { useSecurity } from \"~/hooks/useSecurity\";\n\ninterface HasPermissionProps {\n any?: string[];\n all?: string[];\n name?: string;\n children: React.ReactNode;\n}\n\nexport const HasPermission = ({ children, ...props }: HasPermissionProps) => {\n const { getPermissions } = useSecurity();\n\n if (props.name) {\n const permissionsCollections = getPermissions(props.name);\n const hasPermission = permissionsCollections.length > 0;\n if (hasPermission) {\n return <Fragment>{children}</Fragment>;\n }\n\n return null;\n }\n\n if (props.any && props.all) {\n throw new Error(`You can use either \"any\" or \"all\", but not both at the same time.`);\n }\n\n const anyAllPermissions = props.any || props.all || [];\n\n const permissionsCollections = anyAllPermissions.map(name => getPermissions(name));\n\n const hasPermission = props.any\n ? permissionsCollections.some(collection => collection.length > 0)\n : permissionsCollections.every(collection => collection.length > 0);\n\n if (hasPermission) {\n return <Fragment>{children}</Fragment>;\n }\n\n return null;\n};\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,QAAQ,QAAQ,OAAO;AACvC,SAASC,WAAW;AASpB,OAAO,MAAMC,aAAa,GAAGA,CAAC;EAAEC,QAAQ;EAAE,GAAGC;AAA0B,CAAC,KAAK;EACzE,MAAM;IAAEC;EAAe,CAAC,GAAGJ,WAAW,CAAC,CAAC;EAExC,IAAIG,KAAK,CAACE,IAAI,EAAE;IACZ,MAAMC,sBAAsB,GAAGF,cAAc,CAACD,KAAK,CAACE,IAAI,CAAC;IACzD,MAAME,aAAa,GAAGD,sBAAsB,CAACE,MAAM,GAAG,CAAC;IACvD,IAAID,aAAa,EAAE;MACf,oBAAOT,KAAA,CAAAW,aAAA,CAACV,QAAQ,QAAEG,QAAmB,CAAC;IAC1C;IAEA,OAAO,IAAI;EACf;EAEA,IAAIC,KAAK,CAACO,GAAG,IAAIP,KAAK,CAACQ,GAAG,EAAE;IACxB,MAAM,IAAIC,KAAK,CAAC,mEAAmE,CAAC;EACxF;EAEA,MAAMC,iBAAiB,GAAGV,KAAK,CAACO,GAAG,IAAIP,KAAK,CAACQ,GAAG,IAAI,EAAE;EAEtD,MAAML,sBAAsB,GAAGO,iBAAiB,CAACC,GAAG,CAACT,IAAI,IAAID,cAAc,CAACC,IAAI,CAAC,CAAC;EAElF,MAAME,aAAa,GAAGJ,KAAK,CAACO,GAAG,GACzBJ,sBAAsB,CAACS,IAAI,CAACC,UAAU,IAAIA,UAAU,CAACR,MAAM,GAAG,CAAC,CAAC,GAChEF,sBAAsB,CAACW,KAAK,CAACD,UAAU,IAAIA,UAAU,CAACR,MAAM,GAAG,CAAC,CAAC;EAEvE,IAAID,aAAa,EAAE;IACf,oBAAOT,KAAA,CAAAW,aAAA,CAACV,QAAQ,QAAEG,QAAmB,CAAC;EAC1C;EAEA,OAAO,IAAI;AACf,CAAC","ignoreList":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
children:
|
|
1
|
+
import type React from "react";
|
|
2
|
+
interface SecureRouteProps {
|
|
3
|
+
children: React.ReactNode;
|
|
4
4
|
permission?: string;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
6
|
+
declare const _default: ({ children, permission }: SecureRouteProps) => React.ReactElement | null;
|
|
6
7
|
export default _default;
|
|
@@ -1,27 +1,32 @@
|
|
|
1
|
-
import { useSecurity } from "
|
|
1
|
+
import { useSecurity } from "../hooks/useSecurity";
|
|
2
2
|
import { plugins } from "@webiny/plugins";
|
|
3
|
-
export default (
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
export default ({
|
|
4
|
+
children,
|
|
5
|
+
permission
|
|
6
|
+
}) => {
|
|
7
|
+
const security = useSecurity();
|
|
8
|
+
if (!security) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const {
|
|
12
|
+
identity,
|
|
13
|
+
getPermission
|
|
14
|
+
} = security;
|
|
15
|
+
if (!identity) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
let hasPermission = false;
|
|
12
19
|
if (identity) {
|
|
13
|
-
hasPermission = permission ? Boolean(
|
|
20
|
+
hasPermission = permission ? Boolean(getPermission(permission)) : true;
|
|
14
21
|
}
|
|
15
|
-
|
|
16
22
|
if (hasPermission) {
|
|
17
23
|
return children;
|
|
18
24
|
}
|
|
19
|
-
|
|
20
|
-
var plugin = plugins.byName("secure-route-error");
|
|
21
|
-
|
|
25
|
+
const plugin = plugins.byName("secure-route-error");
|
|
22
26
|
if (!plugin) {
|
|
23
27
|
return null;
|
|
24
28
|
}
|
|
25
|
-
|
|
26
29
|
return plugin.render();
|
|
27
|
-
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=SecureRoute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useSecurity","plugins","children","permission","security","identity","getPermission","hasPermission","Boolean","plugin","byName","render"],"sources":["SecureRoute.tsx"],"sourcesContent":["import type React from \"react\";\nimport { useSecurity } from \"~/hooks/useSecurity\";\nimport type { SecureRouteErrorPlugin } from \"~/types\";\nimport { plugins } from \"@webiny/plugins\";\n\ninterface SecureRouteProps {\n children: React.ReactNode;\n permission?: string;\n}\nexport default ({ children, permission }: SecureRouteProps): React.ReactElement | null => {\n const security = useSecurity();\n\n if (!security) {\n return null;\n }\n\n const { identity, getPermission } = security;\n\n if (!identity) {\n return null;\n }\n\n let hasPermission = false;\n if (identity) {\n hasPermission = permission ? Boolean(getPermission(permission)) : true;\n }\n\n if (hasPermission) {\n return children as unknown as React.ReactElement;\n }\n\n const plugin = plugins.byName<SecureRouteErrorPlugin>(\"secure-route-error\");\n if (!plugin) {\n return null;\n }\n\n return plugin.render();\n};\n"],"mappings":"AACA,SAASA,WAAW;AAEpB,SAASC,OAAO,QAAQ,iBAAiB;AAMzC,eAAe,CAAC;EAAEC,QAAQ;EAAEC;AAA6B,CAAC,KAAgC;EACtF,MAAMC,QAAQ,GAAGJ,WAAW,CAAC,CAAC;EAE9B,IAAI,CAACI,QAAQ,EAAE;IACX,OAAO,IAAI;EACf;EAEA,MAAM;IAAEC,QAAQ;IAAEC;EAAc,CAAC,GAAGF,QAAQ;EAE5C,IAAI,CAACC,QAAQ,EAAE;IACX,OAAO,IAAI;EACf;EAEA,IAAIE,aAAa,GAAG,KAAK;EACzB,IAAIF,QAAQ,EAAE;IACVE,aAAa,GAAGJ,UAAU,GAAGK,OAAO,CAACF,aAAa,CAACH,UAAU,CAAC,CAAC,GAAG,IAAI;EAC1E;EAEA,IAAII,aAAa,EAAE;IACf,OAAOL,QAAQ;EACnB;EAEA,MAAMO,MAAM,GAAGR,OAAO,CAACS,MAAM,CAAyB,oBAAoB,CAAC;EAC3E,IAAI,CAACD,MAAM,EAAE;IACT,OAAO,IAAI;EACf;EAEA,OAAOA,MAAM,CAACE,MAAM,CAAC,CAAC;AAC1B,CAAC","ignoreList":[]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { SecurityPermission } from "../types";
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import type { SecurityPermission } from "../types";
|
|
3
3
|
interface ChildrenRenderFunctionArgs<T extends SecurityPermission> {
|
|
4
4
|
hasPermission: boolean;
|
|
5
|
-
permission: T;
|
|
5
|
+
permission: T | null;
|
|
6
6
|
}
|
|
7
7
|
interface Props<T extends SecurityPermission> {
|
|
8
8
|
children: ((args: ChildrenRenderFunctionArgs<T>) => React.ReactElement) | React.ReactElement;
|
|
9
9
|
permission?: string;
|
|
10
10
|
}
|
|
11
|
-
declare function SecureView<T extends SecurityPermission>({ children, permission }: Props<T>): React.ReactElement;
|
|
11
|
+
declare function SecureView<T extends SecurityPermission>({ children, permission }: Props<T>): React.ReactElement | null;
|
|
12
12
|
export default SecureView;
|
package/components/SecureView.js
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
import { useSecurity } from "
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (identity) {
|
|
14
|
-
matchedPermission = identity.getPermission(permission);
|
|
1
|
+
import { useSecurity } from "../hooks/useSecurity";
|
|
2
|
+
function SecureView({
|
|
3
|
+
children,
|
|
4
|
+
permission
|
|
5
|
+
}) {
|
|
6
|
+
const {
|
|
7
|
+
getPermission
|
|
8
|
+
} = useSecurity();
|
|
9
|
+
let hasPermission = false;
|
|
10
|
+
let matchedPermission = null;
|
|
11
|
+
if (permission) {
|
|
12
|
+
matchedPermission = getPermission(permission);
|
|
15
13
|
hasPermission = Boolean(matchedPermission);
|
|
16
14
|
}
|
|
17
|
-
|
|
18
15
|
if (typeof children === "function") {
|
|
19
16
|
return children({
|
|
20
|
-
hasPermission
|
|
17
|
+
hasPermission,
|
|
21
18
|
permission: matchedPermission
|
|
22
19
|
});
|
|
23
20
|
}
|
|
24
|
-
|
|
25
21
|
return hasPermission ? children : null;
|
|
26
22
|
}
|
|
23
|
+
export default SecureView;
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
//# sourceMappingURL=SecureView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useSecurity","SecureView","children","permission","getPermission","hasPermission","matchedPermission","Boolean"],"sources":["SecureView.tsx"],"sourcesContent":["import type * as React from \"react\";\nimport { useSecurity } from \"~/hooks/useSecurity\";\nimport type { SecurityPermission } from \"~/types\";\n\ninterface ChildrenRenderFunctionArgs<T extends SecurityPermission> {\n hasPermission: boolean;\n permission: T | null;\n}\n\ninterface Props<T extends SecurityPermission> {\n children: ((args: ChildrenRenderFunctionArgs<T>) => React.ReactElement) | React.ReactElement;\n permission?: string;\n}\n\nfunction SecureView<T extends SecurityPermission>({\n children,\n permission\n}: Props<T>): React.ReactElement | null {\n const { getPermission } = useSecurity();\n\n let hasPermission = false;\n let matchedPermission: T | null = null;\n if (permission) {\n matchedPermission = getPermission<T>(permission);\n hasPermission = Boolean(matchedPermission);\n }\n\n if (typeof children === \"function\") {\n return children({\n hasPermission,\n permission: matchedPermission\n });\n }\n\n return hasPermission ? children : null;\n}\n\nexport default SecureView;\n"],"mappings":"AACA,SAASA,WAAW;AAapB,SAASC,UAAUA,CAA+B;EAC9CC,QAAQ;EACRC;AACM,CAAC,EAA6B;EACpC,MAAM;IAAEC;EAAc,CAAC,GAAGJ,WAAW,CAAC,CAAC;EAEvC,IAAIK,aAAa,GAAG,KAAK;EACzB,IAAIC,iBAA2B,GAAG,IAAI;EACtC,IAAIH,UAAU,EAAE;IACZG,iBAAiB,GAAGF,aAAa,CAAID,UAAU,CAAC;IAChDE,aAAa,GAAGE,OAAO,CAACD,iBAAiB,CAAC;EAC9C;EAEA,IAAI,OAAOJ,QAAQ,KAAK,UAAU,EAAE;IAChC,OAAOA,QAAQ,CAAC;MACZG,aAAa;MACbF,UAAU,EAAEG;IAChB,CAAC,CAAC;EACN;EAEA,OAAOD,aAAa,GAAGH,QAAQ,GAAG,IAAI;AAC1C;AAEA,eAAeD,UAAU","ignoreList":[]}
|
package/components/index.d.ts
CHANGED
package/components/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["default","SecureView","SecureRoute","HasPermission"],"sources":["index.ts"],"sourcesContent":["export { default as SecureView } from \"./SecureView\";\nexport { default as SecureRoute } from \"./SecureRoute\";\nexport { HasPermission } from \"./HasPermission\";\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,UAAU;AAC9B,SAASD,OAAO,IAAIE,WAAW;AAC/B,SAASC,aAAa","ignoreList":[]}
|
package/contexts/Security.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
export interface
|
|
1
|
+
import type { Dispatch, SetStateAction } from "react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import type { IdTokenProvider, SecurityIdentity, SecurityPermission } from "../types";
|
|
4
|
+
export interface SecurityContext {
|
|
5
5
|
identity: SecurityIdentity | null;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
getIdentityId: () => string | null;
|
|
7
|
+
setIdentity: Dispatch<SetStateAction<SecurityIdentity | null>>;
|
|
8
|
+
getPermission<T extends SecurityPermission = SecurityPermission>(name: string, exact?: boolean): T | null;
|
|
9
|
+
getPermissions<T extends SecurityPermission = SecurityPermission>(name: string): T[];
|
|
10
|
+
setIdTokenProvider: (provider: IdTokenProvider) => void;
|
|
11
|
+
getIdToken: IdTokenProvider;
|
|
8
12
|
}
|
|
9
|
-
|
|
13
|
+
interface SecurityProviderProps {
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
export declare const SecurityContext: React.Context<SecurityContext | undefined>;
|
|
17
|
+
export declare const SecurityProvider: (props: SecurityProviderProps) => React.JSX.Element;
|
|
18
|
+
export {};
|
package/contexts/Security.js
CHANGED
|
@@ -1,44 +1,66 @@
|
|
|
1
|
-
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
|
|
2
|
-
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
1
|
import minimatch from "minimatch";
|
|
4
|
-
import React, {
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
var getPermission = useCallback(function (name) {
|
|
2
|
+
import React, { useCallback, useMemo, useState } from "react";
|
|
3
|
+
const defaultIdTokenProvider = () => undefined;
|
|
4
|
+
export const SecurityContext = /*#__PURE__*/React.createContext(undefined);
|
|
5
|
+
export const SecurityProvider = props => {
|
|
6
|
+
const [identity, setIdentity] = useState(null);
|
|
7
|
+
const [idTokenProvider, setIdTokenProvider] = useState(() => defaultIdTokenProvider);
|
|
8
|
+
const getPermission = useCallback((name, exact) => {
|
|
13
9
|
if (!identity) {
|
|
14
10
|
return null;
|
|
15
11
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
var exactMatch = perms.find(function (p) {
|
|
19
|
-
return p.name === name;
|
|
20
|
-
});
|
|
21
|
-
|
|
12
|
+
const perms = identity.permissions || [];
|
|
13
|
+
const exactMatch = perms.find(p => p.name === name);
|
|
22
14
|
if (exactMatch) {
|
|
23
15
|
return exactMatch;
|
|
24
|
-
}
|
|
16
|
+
} else if (exact) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
25
19
|
|
|
20
|
+
// Try matching using patterns
|
|
21
|
+
return perms.find(p => minimatch(name, p.name)) || null;
|
|
22
|
+
}, [identity]);
|
|
23
|
+
const getPermissions = useCallback(name => {
|
|
24
|
+
if (!identity) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const permissions = identity.permissions || [];
|
|
28
|
+
return permissions.filter(current => {
|
|
29
|
+
const exactMatch = current.name === name;
|
|
30
|
+
if (exactMatch) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
26
33
|
|
|
27
|
-
|
|
28
|
-
return minimatch(name,
|
|
34
|
+
// Try matching using patterns.
|
|
35
|
+
return minimatch(name, current.name);
|
|
29
36
|
});
|
|
30
37
|
}, [identity]);
|
|
31
|
-
|
|
38
|
+
const getIdentityId = useCallback(() => {
|
|
39
|
+
if (!identity) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return identity.id || identity.login || null;
|
|
43
|
+
}, [identity]);
|
|
44
|
+
const value = useMemo(() => {
|
|
32
45
|
return {
|
|
33
|
-
identity: identity ?
|
|
46
|
+
identity: identity ? {
|
|
47
|
+
...identity,
|
|
34
48
|
// For backwards compatibility, expose the `getPermission` method on the `identity` object.
|
|
35
|
-
getPermission
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
49
|
+
getPermission
|
|
50
|
+
} : null,
|
|
51
|
+
getIdentityId,
|
|
52
|
+
setIdentity,
|
|
53
|
+
getPermission,
|
|
54
|
+
getPermissions,
|
|
55
|
+
getIdToken: idTokenProvider,
|
|
56
|
+
setIdTokenProvider: provider => {
|
|
57
|
+
setIdTokenProvider(() => provider);
|
|
58
|
+
}
|
|
39
59
|
};
|
|
40
|
-
}, [identity]);
|
|
60
|
+
}, [idTokenProvider, identity]);
|
|
41
61
|
return /*#__PURE__*/React.createElement(SecurityContext.Provider, {
|
|
42
62
|
value: value
|
|
43
63
|
}, props.children);
|
|
44
|
-
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=Security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["minimatch","React","useCallback","useMemo","useState","defaultIdTokenProvider","undefined","SecurityContext","createContext","SecurityProvider","props","identity","setIdentity","idTokenProvider","setIdTokenProvider","getPermission","name","exact","perms","permissions","exactMatch","find","p","getPermissions","filter","current","getIdentityId","id","login","value","getIdToken","provider","createElement","Provider","children"],"sources":["Security.tsx"],"sourcesContent":["import minimatch from \"minimatch\";\nimport type { Dispatch, SetStateAction } from \"react\";\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport type { IdTokenProvider, SecurityIdentity, SecurityPermission } from \"~/types\";\n\nexport interface SecurityContext {\n identity: SecurityIdentity | null;\n getIdentityId: () => string | null;\n setIdentity: Dispatch<SetStateAction<SecurityIdentity | null>>;\n getPermission<T extends SecurityPermission = SecurityPermission>(\n name: string,\n exact?: boolean\n ): T | null;\n getPermissions<T extends SecurityPermission = SecurityPermission>(name: string): T[];\n setIdTokenProvider: (provider: IdTokenProvider) => void;\n getIdToken: IdTokenProvider;\n}\n\ninterface SecurityProviderProps {\n children: React.ReactNode;\n}\n\nconst defaultIdTokenProvider: IdTokenProvider = () => undefined;\n\nexport const SecurityContext = React.createContext<SecurityContext | undefined>(undefined);\n\nexport const SecurityProvider = (props: SecurityProviderProps) => {\n const [identity, setIdentity] = useState<SecurityIdentity | null>(null);\n const [idTokenProvider, setIdTokenProvider] = useState<IdTokenProvider>(\n () => defaultIdTokenProvider\n );\n\n const getPermission = useCallback(\n <T extends SecurityPermission = SecurityPermission>(\n name: string,\n exact?: boolean\n ): T | null => {\n if (!identity) {\n return null;\n }\n\n const perms = (identity.permissions || []) as T[];\n const exactMatch = perms.find(p => p.name === name);\n if (exactMatch) {\n return exactMatch as T;\n } else if (exact) {\n return null;\n }\n\n // Try matching using patterns\n return perms.find(p => minimatch(name, p.name)) || null;\n },\n [identity]\n );\n\n const getPermissions = useCallback(\n <T extends SecurityPermission = SecurityPermission>(name: string): Array<T> => {\n if (!identity) {\n return [];\n }\n\n const permissions = identity.permissions || [];\n\n return permissions.filter(current => {\n const exactMatch = current.name === name;\n if (exactMatch) {\n return true;\n }\n\n // Try matching using patterns.\n return minimatch(name, current.name);\n }) as T[];\n },\n [identity]\n );\n\n const getIdentityId = useCallback(() => {\n if (!identity) {\n return null;\n }\n return identity.id || identity.login || null;\n }, [identity]);\n\n const value: SecurityContext = useMemo(() => {\n return {\n identity: identity\n ? {\n ...identity,\n // For backwards compatibility, expose the `getPermission` method on the `identity` object.\n getPermission\n }\n : null,\n getIdentityId,\n setIdentity,\n getPermission,\n getPermissions,\n getIdToken: idTokenProvider,\n setIdTokenProvider: provider => {\n setIdTokenProvider(() => provider);\n }\n };\n }, [idTokenProvider, identity]);\n\n return <SecurityContext.Provider value={value}>{props.children}</SecurityContext.Provider>;\n};\n"],"mappings":"AAAA,OAAOA,SAAS,MAAM,WAAW;AAEjC,OAAOC,KAAK,IAAIC,WAAW,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,OAAO;AAoB7D,MAAMC,sBAAuC,GAAGA,CAAA,KAAMC,SAAS;AAE/D,OAAO,MAAMC,eAAe,gBAAGN,KAAK,CAACO,aAAa,CAA8BF,SAAS,CAAC;AAE1F,OAAO,MAAMG,gBAAgB,GAAIC,KAA4B,IAAK;EAC9D,MAAM,CAACC,QAAQ,EAAEC,WAAW,CAAC,GAAGR,QAAQ,CAA0B,IAAI,CAAC;EACvE,MAAM,CAACS,eAAe,EAAEC,kBAAkB,CAAC,GAAGV,QAAQ,CAClD,MAAMC,sBACV,CAAC;EAED,MAAMU,aAAa,GAAGb,WAAW,CAC7B,CACIc,IAAY,EACZC,KAAe,KACJ;IACX,IAAI,CAACN,QAAQ,EAAE;MACX,OAAO,IAAI;IACf;IAEA,MAAMO,KAAK,GAAIP,QAAQ,CAACQ,WAAW,IAAI,EAAU;IACjD,MAAMC,UAAU,GAAGF,KAAK,CAACG,IAAI,CAACC,CAAC,IAAIA,CAAC,CAACN,IAAI,KAAKA,IAAI,CAAC;IACnD,IAAII,UAAU,EAAE;MACZ,OAAOA,UAAU;IACrB,CAAC,MAAM,IAAIH,KAAK,EAAE;MACd,OAAO,IAAI;IACf;;IAEA;IACA,OAAOC,KAAK,CAACG,IAAI,CAACC,CAAC,IAAItB,SAAS,CAACgB,IAAI,EAAEM,CAAC,CAACN,IAAI,CAAC,CAAC,IAAI,IAAI;EAC3D,CAAC,EACD,CAACL,QAAQ,CACb,CAAC;EAED,MAAMY,cAAc,GAAGrB,WAAW,CACsBc,IAAY,IAAe;IAC3E,IAAI,CAACL,QAAQ,EAAE;MACX,OAAO,EAAE;IACb;IAEA,MAAMQ,WAAW,GAAGR,QAAQ,CAACQ,WAAW,IAAI,EAAE;IAE9C,OAAOA,WAAW,CAACK,MAAM,CAACC,OAAO,IAAI;MACjC,MAAML,UAAU,GAAGK,OAAO,CAACT,IAAI,KAAKA,IAAI;MACxC,IAAII,UAAU,EAAE;QACZ,OAAO,IAAI;MACf;;MAEA;MACA,OAAOpB,SAAS,CAACgB,IAAI,EAAES,OAAO,CAACT,IAAI,CAAC;IACxC,CAAC,CAAC;EACN,CAAC,EACD,CAACL,QAAQ,CACb,CAAC;EAED,MAAMe,aAAa,GAAGxB,WAAW,CAAC,MAAM;IACpC,IAAI,CAACS,QAAQ,EAAE;MACX,OAAO,IAAI;IACf;IACA,OAAOA,QAAQ,CAACgB,EAAE,IAAIhB,QAAQ,CAACiB,KAAK,IAAI,IAAI;EAChD,CAAC,EAAE,CAACjB,QAAQ,CAAC,CAAC;EAEd,MAAMkB,KAAsB,GAAG1B,OAAO,CAAC,MAAM;IACzC,OAAO;MACHQ,QAAQ,EAAEA,QAAQ,GACZ;QACI,GAAGA,QAAQ;QACX;QACAI;MACJ,CAAC,GACD,IAAI;MACVW,aAAa;MACbd,WAAW;MACXG,aAAa;MACbQ,cAAc;MACdO,UAAU,EAAEjB,eAAe;MAC3BC,kBAAkB,EAAEiB,QAAQ,IAAI;QAC5BjB,kBAAkB,CAAC,MAAMiB,QAAQ,CAAC;MACtC;IACJ,CAAC;EACL,CAAC,EAAE,CAAClB,eAAe,EAAEF,QAAQ,CAAC,CAAC;EAE/B,oBAAOV,KAAA,CAAA+B,aAAA,CAACzB,eAAe,CAAC0B,QAAQ;IAACJ,KAAK,EAAEA;EAAM,GAAEnB,KAAK,CAACwB,QAAmC,CAAC;AAC9F,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useSecurity","usePermission","name","getPermission"],"sources":["usePermission.ts"],"sourcesContent":["import { useSecurity } from \"~/hooks/useSecurity\";\nimport type { SecurityPermission } from \"~/types\";\n\nexport function usePermission<T extends SecurityPermission = SecurityPermission>(name: string) {\n const { getPermission } = useSecurity();\n return getPermission<T>(name);\n}\n"],"mappings":"AAAA,SAASA,WAAW;AAGpB,OAAO,SAASC,aAAaA,CAAoDC,IAAY,EAAE;EAC3F,MAAM;IAAEC;EAAc,CAAC,GAAGH,WAAW,CAAC,CAAC;EACvC,OAAOG,aAAa,CAAID,IAAI,CAAC;AACjC","ignoreList":[]}
|
package/hooks/useSecurity.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function useSecurity():
|
|
1
|
+
import { SecurityContext } from "../contexts/Security";
|
|
2
|
+
export declare function useSecurity(): SecurityContext;
|
package/hooks/useSecurity.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { useContext } from "react";
|
|
2
2
|
import { SecurityContext } from "../contexts/Security";
|
|
3
3
|
export function useSecurity() {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const context = useContext(SecurityContext);
|
|
5
|
+
if (!context) {
|
|
6
|
+
throw Error(`Missing <SecurityProvider> in the component hierarchy!`);
|
|
7
|
+
}
|
|
8
|
+
return context;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=useSecurity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useContext","SecurityContext","useSecurity","context","Error"],"sources":["useSecurity.ts"],"sourcesContent":["import { useContext } from \"react\";\nimport { SecurityContext } from \"~/contexts/Security\";\n\nexport function useSecurity() {\n const context = useContext(SecurityContext);\n\n if (!context) {\n throw Error(`Missing <SecurityProvider> in the component hierarchy!`);\n }\n\n return context;\n}\n"],"mappings":"AAAA,SAASA,UAAU,QAAQ,OAAO;AAClC,SAASC,eAAe;AAExB,OAAO,SAASC,WAAWA,CAAA,EAAG;EAC1B,MAAMC,OAAO,GAAGH,UAAU,CAACC,eAAe,CAAC;EAE3C,IAAI,CAACE,OAAO,EAAE;IACV,MAAMC,KAAK,CAAC,wDAAwD,CAAC;EACzE;EAEA,OAAOD,OAAO;AAClB","ignoreList":[]}
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
export * from "./components";
|
|
2
2
|
export * from "./contexts/Security";
|
|
3
|
-
export
|
|
3
|
+
export { SecurityContext } from "./contexts/Security";
|
|
4
|
+
export * from "./hooks/useSecurity";
|
|
5
|
+
export * from "./hooks/usePermission";
|
|
6
|
+
export * from "./Security";
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["SecurityContext"],"sources":["index.ts"],"sourcesContent":["export * from \"./components\";\nexport * from \"./contexts/Security\";\nexport { SecurityContext } from \"./contexts/Security\";\nexport * from \"./hooks/useSecurity\";\nexport * from \"./hooks/usePermission\";\nexport * from \"./Security\";\n"],"mappings":"AAAA;AACA;AACA,SAASA,eAAe;AACxB;AACA;AACA","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/app-security",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-unstable.06b2ede40f",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,40 +13,25 @@
|
|
|
13
13
|
],
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@webiny/app": "0.0.0-
|
|
17
|
-
"@webiny/plugins": "0.0.0-
|
|
18
|
-
"minimatch": "
|
|
19
|
-
"react": "
|
|
20
|
-
"react-dom": "
|
|
16
|
+
"@webiny/app": "0.0.0-unstable.06b2ede40f",
|
|
17
|
+
"@webiny/plugins": "0.0.0-unstable.06b2ede40f",
|
|
18
|
+
"minimatch": "5.1.6",
|
|
19
|
+
"react": "18.2.0",
|
|
20
|
+
"react-dom": "18.2.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@babel
|
|
24
|
-
"@
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"@babel/preset-react": "^7.0.0",
|
|
28
|
-
"@babel/preset-typescript": "^7.8.3",
|
|
29
|
-
"@webiny/cli": "^0.0.0-mt-2",
|
|
30
|
-
"@webiny/project-utils": "^0.0.0-mt-2",
|
|
31
|
-
"babel-plugin-emotion": "^9.2.8",
|
|
32
|
-
"babel-plugin-lodash": "^3.3.4",
|
|
33
|
-
"babel-plugin-named-asset-import": "^1.0.0-next.3e165448",
|
|
34
|
-
"rimraf": "^3.0.2",
|
|
35
|
-
"ttypescript": "^1.5.12",
|
|
36
|
-
"typescript": "^4.1.3"
|
|
23
|
+
"@emotion/babel-plugin": "11.11.0",
|
|
24
|
+
"@webiny/project-utils": "0.0.0-unstable.06b2ede40f",
|
|
25
|
+
"rimraf": "6.0.1",
|
|
26
|
+
"typescript": "5.3.3"
|
|
37
27
|
},
|
|
38
28
|
"publishConfig": {
|
|
39
29
|
"access": "public",
|
|
40
30
|
"directory": "dist"
|
|
41
31
|
},
|
|
42
32
|
"scripts": {
|
|
43
|
-
"build": "
|
|
44
|
-
"watch": "
|
|
45
|
-
},
|
|
46
|
-
"svgo": {
|
|
47
|
-
"plugins": {
|
|
48
|
-
"removeViewBox": false
|
|
49
|
-
}
|
|
33
|
+
"build": "node ../cli/bin.js run build",
|
|
34
|
+
"watch": "node ../cli/bin.js run watch"
|
|
50
35
|
},
|
|
51
36
|
"adio": {
|
|
52
37
|
"ignore": {
|
|
@@ -55,5 +40,5 @@
|
|
|
55
40
|
]
|
|
56
41
|
}
|
|
57
42
|
},
|
|
58
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "06b2ede40fc2212a70eeafd74afd50b56fb0ce82"
|
|
59
44
|
}
|
package/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { Plugin } from "@webiny/app/types";
|
|
3
|
-
export
|
|
2
|
+
import type { Plugin } from "@webiny/app/types";
|
|
3
|
+
export type SecureRouteErrorPlugin = Plugin & {
|
|
4
4
|
render(): React.ReactElement;
|
|
5
5
|
};
|
|
6
6
|
export interface FullAccessPermission {
|
|
@@ -15,7 +15,27 @@ export interface SecurityIdentity {
|
|
|
15
15
|
type: string;
|
|
16
16
|
displayName: string;
|
|
17
17
|
permissions?: SecurityPermission[];
|
|
18
|
+
/**
|
|
19
|
+
* TODO @ts-refactor @pavel
|
|
20
|
+
* Verify that login can be present in here.
|
|
21
|
+
*/
|
|
22
|
+
login?: string;
|
|
23
|
+
/**
|
|
24
|
+
* TODO @ts-refactor @pavel
|
|
25
|
+
* Verify that profile can be present in here.
|
|
26
|
+
*/
|
|
27
|
+
profile?: {
|
|
28
|
+
email?: string;
|
|
29
|
+
firstName?: string;
|
|
30
|
+
lastName?: string;
|
|
31
|
+
avatar?: {
|
|
32
|
+
src?: string;
|
|
33
|
+
};
|
|
34
|
+
gravatar?: string;
|
|
35
|
+
};
|
|
18
36
|
logout(): void;
|
|
19
|
-
getPermission?<T extends SecurityPermission = SecurityPermission>(name: string): T;
|
|
37
|
+
getPermission?<T extends SecurityPermission = SecurityPermission>(name: string): T | null;
|
|
20
38
|
[key: string]: any;
|
|
21
39
|
}
|
|
40
|
+
export type IdToken = string;
|
|
41
|
+
export type IdTokenProvider = () => Promise<IdToken | undefined> | IdToken | undefined;
|
package/types.js
CHANGED
package/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { Plugin } from \"@webiny/app/types\";\n\nexport type SecureRouteErrorPlugin = Plugin & {\n render(): React.ReactElement;\n};\n\nexport interface FullAccessPermission {\n name: \"*\";\n}\n\nexport interface SecurityPermission {\n name: string;\n [key: string]: any;\n}\n\nexport interface SecurityIdentity {\n id: string;\n type: string;\n displayName: string;\n permissions?: SecurityPermission[];\n /**\n * TODO @ts-refactor @pavel\n * Verify that login can be present in here.\n */\n login?: string;\n /**\n * TODO @ts-refactor @pavel\n * Verify that profile can be present in here.\n */\n profile?: {\n email?: string;\n firstName?: string;\n lastName?: string;\n avatar?: {\n src?: string;\n };\n gravatar?: string;\n };\n logout(): void;\n // For backwards compatibility, expose the `getPermission` method on the `identity` object.\n getPermission?<T extends SecurityPermission = SecurityPermission>(name: string): T | null;\n [key: string]: any;\n}\n\nexport type IdToken = string;\n\nexport type IdTokenProvider = () => Promise<IdToken | undefined> | IdToken | undefined;\n"],"mappings":"","ignoreList":[]}
|