Skip to content

Commit de3b6a1

Browse files
committed
wip
1 parent badfccc commit de3b6a1

8 files changed

Lines changed: 115 additions & 51 deletions

File tree

.node-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
24.14.0
1+
24.14.1

office/.env.example

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ IO_BRIDGE_LICENSE_KEY=
1515
###############################################################################
1616

1717
## The PORT for io.Bridge server to bind on (Optional, default is 8084)
18-
#IO_BRIDGE_SERVER_PORT=8385
18+
#IO_BRIDGE_SERVER_PORT=8084
1919

2020
## The host for io.Bridge server to bind on (Optional, default is '0.0.0.0' i.e. any local IP)
2121
#IO_BRIDGE_SERVER_HOST=127.0.0.1
@@ -38,17 +38,6 @@ IO_BRIDGE_SERVER_AUTH_BASIC_REALM=interop.io
3838

3939
##
4040
IO_BRIDGE_SERVER_AUTH_OAUTH2_JWT_AUDIENCE=
41-
## Same as the one above, but exposed to the client
42-
VITE_AUTH0_AUDIENCE=
43-
44-
## Client ID for Auth0 SPA application
45-
#VITE_AUTH0_CLIENT_ID=
46-
47-
## Domain for Auth0 tenant
48-
#VITE_AUTH0_DOMAIN=
49-
50-
##
51-
#VITE_AUTH0_SCOPES=openid email
5241

5342
###############################################################################
5443
## Mesh ##
@@ -124,7 +113,6 @@ LOGGING_LEVEL_GATEWAY=info
124113

125114
## License key for io.Connect Browser Platform (Required for web app)
126115
## Note: This is a DIFFERENT license than IO_BRIDGE_LICENSE_KEY above.
127-
## - IO_BRIDGE_LICENSE_KEY is for the io.Bridge server (Node.js)
128116
## - VITE_IO_CB_LICENSE_KEY is for the browser platform (client-side)
129117
VITE_IO_CB_LICENSE_KEY=
130118

@@ -133,3 +121,6 @@ VITE_IO_CB_LICENSE_KEY=
133121
VITE_AUTH0_DOMAIN=
134122
VITE_AUTH0_CLIENT_ID=
135123
VITE_AUTH0_AUDIENCE=
124+
125+
##
126+
#VITE_AUTH0_SCOPES=openid email

office/auth0/app.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import type { ServerConfigurer } from '@interopio/gateway-server/web/server';
2-
import type { Logger } from '@interopio/gateway/logging/api';
3-
import { randomUUID } from 'node:crypto';
4-
import { readFileSync } from 'node:fs';
5-
import { resolve } from 'node:path';
1+
import type { ServerConfigurer } from "@interopio/gateway-server/web/server";
2+
import type { Logger } from "@interopio/gateway/logging/api";
3+
import { randomUUID } from "node:crypto";
4+
import { readFileSync } from "node:fs";
5+
import { resolve } from "node:path";
66

77
export type AuthInfo = {
88
user: string
@@ -16,8 +16,8 @@ const successPage = readFileSync(resolve(import.meta.dirname, './success.html'))
1616
// ---------------------------------------------------------------------------
1717
// Auth0 integration — Implicit Flow with response_mode=form_post
1818
//
19-
// GET /login/auth0 → redirects to Auth0 Universal Login
20-
// POST /api/webhooks/auth0/callback → Auth0 POSTs tokens back here
19+
// GET /login/auth0 → redirects to Auth0 Universal Login
20+
// POST /login/oauth2/code/auth0 → Auth0 POSTs tokens back here
2121
// ---------------------------------------------------------------------------
2222
export const app = async (
2323
config: {
@@ -33,9 +33,9 @@ export const app = async (
3333
}: ServerConfigurer
3434
) => {
3535
const { logger, issuerUrl, clientId } = config;
36-
const scopes = config.scopes ?? 'openid email';
37-
const loginCallbackPath = '/login/oauth2/code/auth0';
38-
const loginUrlPath = '/login/auth0';
36+
const scopes = config.scopes ?? "openid email";
37+
const loginCallbackPath = "/login/oauth2/code/auth0";
38+
const loginUrlPath = "/login/auth0";
3939

4040
logger.info(`auth0 login endpoint registered on [${loginUrlPath}]`);
4141
logger.info(`auth0 callback endpoint registered on [${loginCallbackPath}]`);
@@ -46,13 +46,13 @@ export const app = async (
4646
// ---------------------------------------------------------------
4747
{
4848
request: { method: 'GET', path: loginUrlPath },
49-
options: { authorize: { access: 'permitted' } },
49+
options: { authorize: { access: "permitted" } },
5050
handler: async ({ request, response }) => {
5151

5252
const nonce = randomUUID();
5353
const state = randomUUID();
5454
const redirectUri = `${request.protocol}://${request.host}${loginCallbackPath}`;
55-
logger.info('initiating Auth0 implicit login flow', { redirectUri });
55+
logger.info(`initiating Auth0 implicit login flow ${redirectUri}`);
5656

5757
const authorizeUrl = `${issuerUrl}/authorize?` + new URLSearchParams({
5858
response_type: 'id_token token',

office/gateway-server.config.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,17 @@ import type { ServerConfigurer } from "@interopio/gateway-server/web/server";
99
import type { AuthInfo } from "./auth0/app.ts";
1010
import { app } from "./auth0/app.ts";
1111

12-
process.loadEnvFile();
12+
try {
13+
process.loadEnvFile();
14+
}
15+
catch (e) {
16+
if (e.code === "ENOENT") {
17+
// fine, no .env file
18+
}
19+
else {
20+
throw e;
21+
}
22+
}
1323

1424
const BRIDGE_URL = process.env["VITE_IO_BRIDGE_URL"] ?? "https://gw-bridge-examples.interop.io";
1525

office/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"scripts": {
77
"build": "tsc && vite build",
88
"clean": "rimraf dist",
9-
"start:bridge": "npx @interopio/bridge --server-port 8084",
10-
"start:gateway": "npx @interopio/gateway-server run --debug",
9+
"start:bridge": "npx @interopio/bridge",
10+
"start:gateway": "npx @interopio/gateway-server run",
1111
"start:web": "vite --host",
1212
"start": "concurrently \"npm:start:bridge\" \"npm:start:gateway\" \"npm:start:web\"",
1313
"start:no-gateway": "concurrently \"npm:start:bridge\" \"npm:start:web\"",

office/src/App.tsx

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import IOBrowserPlatform from "@interopio/browser-platform";
2-
import { IOConnectHome, type UserData } from "@interopio/home-ui-react";
2+
import { IOConnectHome, type UserData, type Auth0User } from "@interopio/home-ui-react";
33
import type { IOConnectInitSettings } from "@interopio/react-hooks";
44
import IOModals from "@interopio/modals-api";
55
import IOSearch from "@interopio/search-api";
@@ -25,7 +25,7 @@ const getConfig = (userData: UserData): IOConnectInitSettings => {
2525
const licenseKey = (userData.type === "auth0" ? userData.user["https://interop.io/io_cb_license_key"] as string : undefined) ?? import.meta.env.VITE_IO_CB_LICENSE_KEY as string;
2626

2727
// Extract user details from login
28-
const user = userData.user;
28+
const user: Auth0User = userData.user as Auth0User;
2929

3030
// Platform configuration
3131
return {
@@ -60,7 +60,7 @@ const getConfig = (userData: UserData): IOConnectInitSettings => {
6060
type: "window",
6161
"title": "Excel Playground",
6262
details: {
63-
url: 'https://interopio.github.io/excel-playground/'
63+
url: "https://interopio.github.io/excel-playground/"
6464
},
6565
customProperties: {
6666
includeInWorkspaces: true
@@ -69,7 +69,67 @@ const getConfig = (userData: UserData): IOConnectInitSettings => {
6969
]
7070
},
7171
layouts: {
72-
mode: "idb"
72+
mode: "idb",
73+
local: [{
74+
name: "Welcome",
75+
type: "Global",
76+
components: [{
77+
type: "workspaceFrame",
78+
componentType: "application",
79+
application: "workspaces-demo",
80+
state: {
81+
bounds: {
82+
top: 0,
83+
left: 0,
84+
height: 0,
85+
width: 0,
86+
},
87+
context: {
88+
isPlatform: true,
89+
},
90+
instanceId: "g42-welcome",
91+
selectedWorkspace: 0,
92+
workspaces: [{
93+
children: [{
94+
type: "row",
95+
config: {},
96+
children: [
97+
{
98+
type: "group",
99+
config: {},
100+
children: [{
101+
type: "window",
102+
config: {
103+
title: "Outlook",
104+
appName: 'outlook-demo',
105+
url: `${outlookAppUrl}`
106+
}
107+
}]
108+
},
109+
{
110+
type: "group",
111+
config: {},
112+
children: [
113+
{
114+
type: "window",
115+
config: {
116+
title: "Excel",
117+
appName: "excel-playground",
118+
url: "https://interopio.github.io/excel-playground/"
119+
}
120+
}
121+
]
122+
}],
123+
}],
124+
config: {
125+
name: "Office"
126+
},
127+
context: {}
128+
}]
129+
}
130+
}]
131+
}
132+
]
73133
},
74134
channels: {
75135
definitions: config.channels
@@ -85,7 +145,7 @@ const getConfig = (userData: UserData): IOConnectInitSettings => {
85145
}
86146
},
87147
systemLogger: {
88-
level: "debug"
148+
level: "warn"
89149
},
90150
intentResolver: {
91151
enable: true
@@ -102,10 +162,10 @@ const getConfig = (userData: UserData): IOConnectInitSettings => {
102162
// Gateway configuration - connect to local io.Bridge
103163
gateway: {
104164
logging: {
105-
level: 'warn',
106-
appender: (info) => {
107-
console.log(`[${info.namespace}]: ${info.message}`);
108-
},
165+
level: "warn",
166+
appender: (info) => {
167+
console.log(`[${info.namespace}]: ${info.message}`);
168+
},
109169
},
110170
bridge: {
111171
url: bridgeUrl,
@@ -117,7 +177,7 @@ const getConfig = (userData: UserData): IOConnectInitSettings => {
117177
visibility: [
118178
{
119179
restrictions: "cluster",
120-
identity: { application: new RegExp(/(Outlook|IOXLAddin)/)}
180+
identity: { application: new RegExp(/(Outlook|IOXLAddin)/) }
121181
},
122182
]
123183
},
@@ -139,8 +199,11 @@ const getConfig = (userData: UserData): IOConnectInitSettings => {
139199
},
140200
// User details required when connecting to io.Bridge
141201
user: {
142-
id: user?.id || 'anonymous',
143-
username: user?.username || 'anonymous'
202+
id: user.id,
203+
username: user.name,
204+
firstName: user.given_name,
205+
lastName: user.family_name,
206+
email: user.email
144207
},
145208
// Workspaces App configuration
146209
workspaces: {
@@ -159,11 +222,11 @@ const homeConfig = {
159222
login: {
160223
type: "auth0" as const,
161224
providerOptions: {
162-
domain: requireNonEmptyString(import.meta.env.VITE_AUTH0_DOMAIN, 'VITE_AUTH0_DOMAIN'),
163-
clientId: requireNonEmptyString(import.meta.env.VITE_AUTH0_CLIENT_ID, 'VITE_AUTH0_CLIENT_ID'),
225+
domain: requireNonEmptyString(import.meta.env.VITE_AUTH0_DOMAIN, "VITE_AUTH0_DOMAIN"),
226+
clientId: requireNonEmptyString(import.meta.env.VITE_AUTH0_CLIENT_ID, "VITE_AUTH0_CLIENT_ID"),
164227
authorizationParams: {
165-
audience: requireNonEmptyString(import.meta.env.VITE_AUTH0_AUDIENCE, 'VITE_AUTH0_AUDIENCE'),
166-
scope: import.meta.env.VITE_AUTH0_SCOPE ?? 'openid profile email',
228+
audience: requireNonEmptyString(import.meta.env.VITE_AUTH0_AUDIENCE, "VITE_AUTH0_AUDIENCE"),
229+
scope: import.meta.env.VITE_AUTH0_SCOPE ?? "openid profile email",
167230
redirect_uri: appBaseUrl.toString(),
168231
}
169232
},

office/src/main.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import ReactDOM from 'react-dom/client';
2-
import App from './App';
3-
import './index.css';
1+
import ReactDOM from "react-dom/client";
2+
import App from "./App";
3+
import "./index.css";
44

5-
ReactDOM.createRoot(document.getElementById('root')!).render(
5+
ReactDOM.createRoot(document.getElementById("root")!).render(
66
<App />
77
);

office/tsconfig.dev.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"compilerOptions": {
3-
"target": "ES2023",
4-
"lib": ["ES2023"],
3+
"target": "ES2024",
4+
"lib": ["ES2024"],
55
"module": "ESNext",
66
"types": ["node"],
77
"moduleResolution": "bundler",

0 commit comments

Comments
 (0)