@omni-co/embed 0.1.0-beta7 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ type EmbedSsoProps = {
2
+ contentId: string;
3
+ domain?: string;
4
+ externalId: string;
5
+ name: string;
6
+ nonce?: string;
7
+ organizationName: string;
8
+ secret: string;
9
+ userAttributes?: Record<string, string>[];
10
+ };
11
+ export declare const embedSsoDashboard: (props: EmbedSsoProps) => string;
12
+ export {};
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.embedSsoDashboard = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const random_str_1 = require("./random-str");
9
+ const hmacSign = (data, secret) => {
10
+ const hmac = crypto_1.default.createHmac("sha256", secret);
11
+ hmac.update(data);
12
+ return hmac.digest("base64url");
13
+ };
14
+ const embedLoginRoute = "/embed/login";
15
+ const embedDashboardPath = "/embed/dashboards";
16
+ const validateProps = (props) => {
17
+ const { contentId, externalId, name, nonce, organizationName, secret, userAttributes, } = props;
18
+ if (!contentId) {
19
+ throw new Error("contentId is required");
20
+ }
21
+ if (!externalId) {
22
+ throw new Error("externalId is required");
23
+ }
24
+ if (!name) {
25
+ throw new Error("name is required");
26
+ }
27
+ if (!organizationName) {
28
+ throw new Error("organizationName is required");
29
+ }
30
+ if (!secret) {
31
+ throw new Error("secret is required");
32
+ }
33
+ if (nonce && nonce.length !== 32) {
34
+ throw new Error("nonce must be 32 characters");
35
+ }
36
+ if (userAttributes) {
37
+ if (!Array.isArray(userAttributes)) {
38
+ throw new Error("userAttributes must be an array");
39
+ }
40
+ }
41
+ };
42
+ const embedSsoDashboard = (props) => {
43
+ validateProps(props);
44
+ let { contentId, domain, externalId, name, nonce, organizationName, secret, userAttributes, } = props;
45
+ // Handle defaults
46
+ nonce = nonce ?? (0, random_str_1.random32ByteString)();
47
+ domain = domain ?? "embed-omniapp.co";
48
+ const encodedUserAttributes = userAttributes
49
+ ? JSON.stringify(userAttributes)
50
+ : "";
51
+ const url = new URL(embedLoginRoute, `https://${organizationName.toLocaleLowerCase()}.${domain}`);
52
+ const contentPath = `${embedDashboardPath}/${contentId}`;
53
+ const validationStr = `
54
+ ${url.hostname}${embedLoginRoute}
55
+ ${contentPath}
56
+ ${externalId}
57
+ ${name}
58
+ ${nonce}
59
+ ${encodedUserAttributes}
60
+ `
61
+ .trim()
62
+ .replace(/\n\s+/g, "\n");
63
+ const signature = hmacSign(validationStr, secret);
64
+ url.searchParams.append("contentPath", contentPath);
65
+ url.searchParams.append("externalId", externalId);
66
+ url.searchParams.append("name", name);
67
+ url.searchParams.append("nonce", nonce);
68
+ url.searchParams.append("signature", signature);
69
+ url.searchParams.append("userAttributes", encodedUserAttributes);
70
+ return url.toString();
71
+ };
72
+ exports.embedSsoDashboard = embedSsoDashboard;
@@ -0,0 +1 @@
1
+ export * from "./embed";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./embed"), exports);
@@ -0,0 +1 @@
1
+ export declare const random32ByteString: (size?: number | undefined) => string;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.random32ByteString = void 0;
4
+ const nanoid_1 = require("nanoid");
5
+ const humanReadableByteSpace = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
6
+ // Generates a random 32 byte, human readable string.
7
+ // Based on math at https://zelark.github.io/nano-id-cc/
8
+ // at 1000 Ids/s it would take more than 1 quadrillion years or
9
+ // 8,730,800,738,924,245T IDs, in order to have a 1% probability
10
+ // of at least one collision.
11
+ exports.random32ByteString = (0, nanoid_1.customAlphabet)(humanReadableByteSpace, 32);
@@ -0,0 +1,12 @@
1
+ type EmbedSsoProps = {
2
+ contentId: string;
3
+ domain?: string;
4
+ externalId: string;
5
+ name: string;
6
+ nonce?: string;
7
+ organizationName: string;
8
+ secret: string;
9
+ userAttributes?: Record<string, string>[];
10
+ };
11
+ export declare const embedSsoDashboard: (props: EmbedSsoProps) => string;
12
+ export {};
@@ -0,0 +1,65 @@
1
+ import crypto from "crypto";
2
+ import { random32ByteString } from "./random-str";
3
+ const hmacSign = (data, secret) => {
4
+ const hmac = crypto.createHmac("sha256", secret);
5
+ hmac.update(data);
6
+ return hmac.digest("base64url");
7
+ };
8
+ const embedLoginRoute = "/embed/login";
9
+ const embedDashboardPath = "/embed/dashboards";
10
+ const validateProps = (props) => {
11
+ const { contentId, externalId, name, nonce, organizationName, secret, userAttributes, } = props;
12
+ if (!contentId) {
13
+ throw new Error("contentId is required");
14
+ }
15
+ if (!externalId) {
16
+ throw new Error("externalId is required");
17
+ }
18
+ if (!name) {
19
+ throw new Error("name is required");
20
+ }
21
+ if (!organizationName) {
22
+ throw new Error("organizationName is required");
23
+ }
24
+ if (!secret) {
25
+ throw new Error("secret is required");
26
+ }
27
+ if (nonce && nonce.length !== 32) {
28
+ throw new Error("nonce must be 32 characters");
29
+ }
30
+ if (userAttributes) {
31
+ if (!Array.isArray(userAttributes)) {
32
+ throw new Error("userAttributes must be an array");
33
+ }
34
+ }
35
+ };
36
+ export const embedSsoDashboard = (props) => {
37
+ validateProps(props);
38
+ let { contentId, domain, externalId, name, nonce, organizationName, secret, userAttributes, } = props;
39
+ // Handle defaults
40
+ nonce = nonce ?? random32ByteString();
41
+ domain = domain ?? "embed-omniapp.co";
42
+ const encodedUserAttributes = userAttributes
43
+ ? JSON.stringify(userAttributes)
44
+ : "";
45
+ const url = new URL(embedLoginRoute, `https://${organizationName.toLocaleLowerCase()}.${domain}`);
46
+ const contentPath = `${embedDashboardPath}/${contentId}`;
47
+ const validationStr = `
48
+ ${url.hostname}${embedLoginRoute}
49
+ ${contentPath}
50
+ ${externalId}
51
+ ${name}
52
+ ${nonce}
53
+ ${encodedUserAttributes}
54
+ `
55
+ .trim()
56
+ .replace(/\n\s+/g, "\n");
57
+ const signature = hmacSign(validationStr, secret);
58
+ url.searchParams.append("contentPath", contentPath);
59
+ url.searchParams.append("externalId", externalId);
60
+ url.searchParams.append("name", name);
61
+ url.searchParams.append("nonce", nonce);
62
+ url.searchParams.append("signature", signature);
63
+ url.searchParams.append("userAttributes", encodedUserAttributes);
64
+ return url.toString();
65
+ };
@@ -0,0 +1 @@
1
+ export * from "./embed";
@@ -0,0 +1 @@
1
+ export * from "./embed";
@@ -0,0 +1 @@
1
+ export declare const random32ByteString: (size?: number | undefined) => string;
@@ -0,0 +1,8 @@
1
+ import { customAlphabet } from "nanoid";
2
+ const humanReadableByteSpace = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
3
+ // Generates a random 32 byte, human readable string.
4
+ // Based on math at https://zelark.github.io/nano-id-cc/
5
+ // at 1000 Ids/s it would take more than 1 quadrillion years or
6
+ // 8,730,800,738,924,245T IDs, in order to have a 1% probability
7
+ // of at least one collision.
8
+ export const random32ByteString = customAlphabet(humanReadableByteSpace, 32);
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.0-beta7",
2
+ "version": "0.1.0",
3
3
  "license": "MIT",
4
4
  "name": "@omni-co/embed",
5
5
  "author": "Nate Agrin <nate@exploreomni.com>",