-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
976265e
commit b12ebe3
Showing
9 changed files
with
421 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,60 @@ | ||
import React, { useState } from 'react'; | ||
import { Box, ChakraProvider, Heading, HStack } from '@chakra-ui/react'; | ||
import React from 'react'; | ||
import { useAppState } from '../state/store'; | ||
import ModelDropdown from './ModelDropdown'; | ||
import SetAPIKey from './SetAPIKey'; | ||
import TaskUI from './TaskUI'; | ||
import OptionsDropdown from './OptionsDropdown'; | ||
import logo from '../assets/img/icon-128.png'; | ||
import FormComponent from '../pages/Popup/FormComponent'; // Import the FormComponent | ||
|
||
const App = () => { | ||
const App: React.FC = () => { | ||
const openAIKey = useAppState((state) => state.settings.openAIKey); | ||
const [formSubmitted, setFormSubmitted] = useState(false); | ||
|
||
const handleFormSubmit = () => { | ||
setFormSubmitted(true); | ||
}; | ||
|
||
return ( | ||
<ChakraProvider> | ||
<Box p="8" fontSize="lg" w="full"> | ||
<HStack mb={4} alignItems="center"> | ||
<img | ||
src={logo} | ||
width={32} | ||
height={32} | ||
className="App-logo" | ||
alt="logo" | ||
/> | ||
|
||
<Heading as="h1" size="lg" flex={1}> | ||
Autosurf | ||
</Heading> | ||
<HStack spacing={2}> | ||
<ModelDropdown /> | ||
<OptionsDropdown /> | ||
</HStack> | ||
</HStack> | ||
{openAIKey ? <TaskUI /> : <SetAPIKey />} | ||
{/* {formSubmitted ? ( | ||
<AppUI /> | ||
) : ( | ||
<FormComponent onFormSubmit={handleFormSubmit} /> | ||
)} */} | ||
<AppUI/> | ||
</Box> | ||
</ChakraProvider> | ||
); | ||
}; | ||
|
||
const AppUI: React.FC = () => { | ||
const openAIKey = useAppState((state) => state.settings.openAIKey); | ||
|
||
return ( | ||
<> | ||
<HStack mb={4} alignItems="center"> | ||
<img | ||
src={logo} | ||
width={32} | ||
height={32} | ||
className="App-logo" | ||
alt="logo" | ||
/> | ||
|
||
<Heading as="h1" size="lg" flex={1}> | ||
Autosurf | ||
</Heading> | ||
<HStack spacing={2}> | ||
<ModelDropdown /> | ||
<OptionsDropdown /> | ||
</HStack> | ||
</HStack> | ||
{openAIKey ? <TaskUI /> : <SetAPIKey />} | ||
</> | ||
); | ||
}; | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React, { useEffect } from 'react'; | ||
|
||
interface FormComponentProps { | ||
onFormSubmit: () => void; | ||
} | ||
|
||
const FormComponent: React.FC<FormComponentProps> = ({ onFormSubmit }) => { | ||
useEffect(() => { | ||
const handleSignInCompletion = (event: MessageEvent) => { | ||
// Check if the message indicates sign-in completion | ||
if (event.data === 'signInCompleted') { | ||
// If sign-in completed, trigger the parent's callback | ||
onFormSubmit(); | ||
} | ||
}; | ||
|
||
// Add event listener to listen for messages from the child window | ||
window.addEventListener('message', handleSignInCompletion); | ||
|
||
// Load the specified URL in the child window | ||
const childWindow = window.open('https://cubesigner-backend-production.up.railway.app/', '_blank'); | ||
|
||
return () => { | ||
// Cleanup: remove event listener when the component unmounts | ||
window.removeEventListener('message', handleSignInCompletion); | ||
|
||
// Close the child window if it exists | ||
if (childWindow) { | ||
childWindow.close(); | ||
} | ||
}; | ||
}, [onFormSubmit]); | ||
|
||
return ( | ||
<form> | ||
{/* This form will be hidden */} | ||
</form> | ||
); | ||
}; | ||
|
||
export default FormComponent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import * as cs from "@cubist-labs/cubesigner-sdk"; | ||
import * as csFs from "@cubist-labs/cubesigner-sdk-fs-storage"; | ||
import * as dotenv from "dotenv"; | ||
import bodyParser from "body-parser"; | ||
import express from "express"; | ||
import { engine } from "express-handlebars"; | ||
import assert from "assert"; | ||
|
||
dotenv.config(); | ||
|
||
const PORT = process.env["PORT"] ?? 3000; | ||
const GOOGLE_CLIENT_ID = process.env["GOOGLE_CLIENT_ID"]; | ||
const TWITTER_CLIENT_ID = process.env["TWITTER_CLIENT_ID"]; | ||
const FACEBOOK_CLIENT_ID = process.env["FACEBOOK_CLIENT_ID"]; | ||
const ORG_ID = process.env["ORG_ID"]!; | ||
const API_ROOT = process.env["CS_API_ROOT"] ?? "https://gamma.signer.cubist.dev"; | ||
const TWITTER_COOKIE_NAME = "twitterCookie"; | ||
|
||
const app = express(); | ||
|
||
app.engine("handlebars", engine()); | ||
app.set("view engine", "handlebars"); | ||
app.set("views", "./views"); | ||
|
||
app.use(express.static("public")); | ||
app.use(bodyParser.urlencoded({ extended: true })); | ||
app.use(express.json()); | ||
|
||
// Render landing page | ||
app.get("/", (_, res) => { | ||
res.render("index", { | ||
googleClientId: GOOGLE_CLIENT_ID, | ||
twitterClientId: TWITTER_CLIENT_ID, | ||
twitterCookieName: TWITTER_COOKIE_NAME, | ||
facebookClientId: FACEBOOK_CLIENT_ID, | ||
orgId: ORG_ID, | ||
apiRoot: API_ROOT, | ||
port: PORT, | ||
}); | ||
}); | ||
|
||
app.use((req, res, next) => { | ||
res.setHeader('Content-Security-Policy', "script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost:* http://127.0.0.1:* https://accounts.google.com;"); | ||
next(); | ||
}); | ||
|
||
|
||
app.get("/oauthCallback", (_, res) => { | ||
res.render("oauthCallback") | ||
}); | ||
|
||
app.post("/createUser", async (req, res) => { | ||
try { | ||
// In practice we would require the OIDC token and validate it. | ||
// For this demo we just trust the client. | ||
const id = req.body; | ||
console.log(`Creating user ${id.email} with iss=${id.iss} and sub=${id.sub}`); | ||
await createUser(id); | ||
res.contentType("application/json").status(200).send(); | ||
} catch (e) { | ||
console.error(`Failed to create user: ${e}`); | ||
res.contentType("application/json").status(500).send(); | ||
} | ||
}); | ||
|
||
app.listen(PORT); | ||
console.log(`Listening on http://localhost:${PORT}`); | ||
|
||
/** | ||
* Create a user with the given OIDC claims. | ||
* @param {cs.IdentityProof} proof The proof of identity | ||
*/ | ||
async function createUser(proof: cs.IdentityProof) { | ||
// Create a management session | ||
console.log("Loading CubeSigner management session"); | ||
console.log(`Using org ${ORG_ID}`); | ||
|
||
const cubesigner = await csFs.loadManagementSession(); | ||
const org = new cs.Org(cubesigner); | ||
|
||
console.log("Verifying identity", proof); | ||
try { | ||
await org.verifyIdentity(proof); | ||
console.log("Verified"); | ||
} catch (e) { | ||
console.log(`Not verified: ${e}`); | ||
throw e; | ||
} | ||
|
||
assert(proof.identity, "Identity should be set when proof is obtained using OIDC token"); | ||
const iss = proof.identity!.iss; | ||
const sub = proof.identity!.sub; | ||
const email = proof.email; | ||
const name = proof.preferred_username; | ||
|
||
// If user does not exist, create it | ||
if (!proof.user_info?.user_id) { | ||
console.log(`Creating OIDC user ${email}`); | ||
const userId = await org.createOidcUser({ iss, sub }, email, { | ||
name, | ||
mfaPolicy: { | ||
num_auth_factors: 1, | ||
allowed_mfa_types: ["Fido"], | ||
}, | ||
}); | ||
console.log(`Creating key for user ${userId}...`); | ||
// Create a key for the OIDC user | ||
const key = await org.createKey(cs.Secp256k1.Evm, userId); | ||
console.log(`${await key.type()} key created ${key.materialId}`); | ||
} else { | ||
console.log(`User ${proof.user_info.user_id} already exists for ${email}`); | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<script> | ||
let params = new URLSearchParams(window.location.search); | ||
let state = params.get("state"); | ||
let code = params.get("code"); | ||
if (state && params) { | ||
new BroadcastChannel("oauth_code").postMessage({ | ||
code, state | ||
}) | ||
} | ||
window.close(); | ||
</script> |
Oops, something went wrong.