From 10a7ac539bbd32942ca696fc58894bc0301e9be6 Mon Sep 17 00:00:00 2001 From: Utkarsh Dixit Date: Wed, 24 Aug 2022 11:06:47 +0530 Subject: [PATCH 1/6] WIP --- packages/cli/src/bin/index.ts | 4 ++-- packages/cli/src/utils/hooks.ts | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/bin/index.ts b/packages/cli/src/bin/index.ts index c61d36ab6f..e5e6f44e88 100644 --- a/packages/cli/src/bin/index.ts +++ b/packages/cli/src/bin/index.ts @@ -17,9 +17,9 @@ if (parseFloat(nodeVersion) >= 10.0) { const hasDiscordInveite = args && args[0]?.includes("--") - const isDefaultCommand = (args.length === 0 || true) || ["open", "."].some((x) => args && args[0] === x); + const isDefaultCommand = (args.length === 0) || ["open", "."].some((x) => args && args[0] === x); - if(["version", "--version"].includes(args[0])) { + if(["version", "--version", "-v"].includes(args[0])) { // Do nothing since version gets printed for every command } else { if (isDefaultCommand) { diff --git a/packages/cli/src/utils/hooks.ts b/packages/cli/src/utils/hooks.ts index 9016beb26c..9d200d1397 100644 --- a/packages/cli/src/utils/hooks.ts +++ b/packages/cli/src/utils/hooks.ts @@ -20,16 +20,17 @@ const secretInviteCode = "crush" */ const checkForDiscord = async()=>{ const isCodeInCommandLine = process.argv.some((e)=>{ - return e.includes("--") || e === secretInviteCode + return e.includes("--invite-code=") && !["help", "--help", "-h"].includes(e) }) + const hasLoginFlag = process.argv.some((e) => e.includes("--login")); if(isUserLoggedIn() || isCodeInCommandLine) return; - if(!isCodeInCommandLine){ + if(!isCodeInCommandLine && !hasLoginFlag){ await cli.log(chalk.green(`New to crusher?`)) - await cli.log(`Get access code - ${chalk.green("https://discord.com/")}`) + await cli.log(`Get access code - ${chalk.green("https://discord.gg/sWbWNYWv")}`) await cli.log(`1.) Get access code on home screen`) await cli.log(`2.) Run command with access code`) @@ -45,7 +46,7 @@ const waitForUserLogin = async (): Promise => { // ask for discord code here? const discordCode = process.argv.find((i)=>{ - return i.includes("--") || i===secretInviteCode + return i.includes("--invite-code=") }); const loginKey = await axios From c7a0761f4b31dfb5959165884d1f5da93c86fd74 Mon Sep 17 00:00:00 2001 From: Utkarsh Dixit Date: Wed, 24 Aug 2022 13:06:39 +0530 Subject: [PATCH 2/6] WIP --- packages/cli/src/bin/index.ts | 1 + packages/cli/src/commands/index.ts | 2 +- .../src/utils/common/validationUtils.ts | 4 +++ .../containers/auth/components/FormInput.tsx | 4 +-- .../ui/containers/auth/signup_email.tsx | 30 +++++++++++++++++-- 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/bin/index.ts b/packages/cli/src/bin/index.ts index e5e6f44e88..9bd2151926 100644 --- a/packages/cli/src/bin/index.ts +++ b/packages/cli/src/bin/index.ts @@ -17,6 +17,7 @@ if (parseFloat(nodeVersion) >= 10.0) { const hasDiscordInveite = args && args[0]?.includes("--") + const commandArgs = args ? args.filter((a) => !a.startsWith("-")) : []; const isDefaultCommand = (args.length === 0) || ["open", "."].some((x) => args && args[0] === x); if(["version", "--version", "-v"].includes(args[0])) { diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 7873d88066..768560ad86 100755 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -1,4 +1,4 @@ -import { Command } from "commander"; +import { Command, program } from "commander"; import * as packgeJSON from "../../package.json"; import fs from "fs"; import path from "path"; diff --git a/packages/crusher-app/src/utils/common/validationUtils.ts b/packages/crusher-app/src/utils/common/validationUtils.ts index 8e9fddb2e0..c468782629 100644 --- a/packages/crusher-app/src/utils/common/validationUtils.ts +++ b/packages/crusher-app/src/utils/common/validationUtils.ts @@ -18,3 +18,7 @@ export const validateName = (name: string) => { } return true; }; + +export const validateInviteCode = (inviteCode: string) => { + return inviteCode && inviteCode.startsWith("CRU-"); +}; diff --git a/packages/crusher-app/src_ee/ui/containers/auth/components/FormInput.tsx b/packages/crusher-app/src_ee/ui/containers/auth/components/FormInput.tsx index 20f904b7c3..88e6490259 100644 --- a/packages/crusher-app/src_ee/ui/containers/auth/components/FormInput.tsx +++ b/packages/crusher-app/src_ee/ui/containers/auth/components/FormInput.tsx @@ -5,11 +5,11 @@ import { css } from "@emotion/react"; @Note - Wrong implementation of the loading state. It should be implemented in the parent component. */ -export function FormInput({ type, data, onChange, placeholder, autoComplete, onBlur, onKeyDown, onReturn }: any) { +export function FormInput({ type, data, onChange, placeholder, autoComplete, onBlur, onKeyDown, onReturn, className }: any) { return (
{ + setInviteCode({...inviteCode, value: e.target.value}); + }, [inviteCode]); const verifyInfo = (completeVerify = false) => { const shouldValidateEmail = completeVerify || email.value; const shouldValidatePassword = completeVerify || password.value; const shouldValidateName = completeVerify || name.value; + const shouldValidateInvitecode = completeVerify || inviteCode.value; + if (!validateEmail(email.value) && shouldValidateEmail) { setEmail({ ...email, error: "Please enter valid email" }); } else setEmail({ ...email, error: "" }); @@ -64,12 +71,18 @@ export default function Signup_email({ loginWithEmailHandler }) { if (!validateName(name.value) && shouldValidateName) { setName({ ...name, error: "Please enter a valid name" }); } else setName({ ...name, error: "" }); + + if(!validateInviteCode(inviteCode.value) && shouldValidateInvitecode) { + setInviteCode({...inviteCode, error: "Please enter correct invite code."}) + } else { + setName({ ...name, error: ""}); + } }; const signupUser = async () => { verifyInfo(true); - if (!validateEmail(email.value) || !validatePassword(password.value) || !validateName(email.value)) return; + if (!validateEmail(email.value) || !validatePassword(password.value) || !validateName(email.value) || !validateInviteCode(inviteCode.value)) return; setLoading(true); try { const data = await registerUser(name.value, email.value, password.value, query?.inviteType?.toString(), query?.inviteCode?.toString()); @@ -155,13 +168,24 @@ export default function Signup_email({ loginWithEmailHandler }) { + +
+ Don't have any? Get one +
From fa411dde428e1cd49c1dce08c2e040224cdffa88 Mon Sep 17 00:00:00 2001 From: Utkarsh Dixit Date: Wed, 24 Aug 2022 18:49:44 +0530 Subject: [PATCH 3/6] WIP --- packages/cli/src/bin/index.ts | 8 ++++---- packages/cli/src/constants.ts | 4 ++-- packages/cli/src/utils/hooks.ts | 20 +++++++++++++------ packages/crusher-app/src/hooks/tempTest.tsx | 6 ++++++ .../src/store/atoms/global/inviteCode.ts | 15 ++++++++++++++ .../ui/containers/auth/signup_email.tsx | 12 ++++++++++- .../src/modules/resources/cli/controller.ts | 2 +- 7 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 packages/crusher-app/src/store/atoms/global/inviteCode.ts diff --git a/packages/cli/src/bin/index.ts b/packages/cli/src/bin/index.ts index 9bd2151926..aac6379907 100644 --- a/packages/cli/src/bin/index.ts +++ b/packages/cli/src/bin/index.ts @@ -18,12 +18,12 @@ if (parseFloat(nodeVersion) >= 10.0) { const hasDiscordInveite = args && args[0]?.includes("--") const commandArgs = args ? args.filter((a) => !a.startsWith("-")) : []; - const isDefaultCommand = (args.length === 0) || ["open", "."].some((x) => args && args[0] === x); - + const isDefaultCommand = (commandArgs.length === 0) || ["open", "."].some((x) => args && args[0] === x); + const isHelpArg = helpArgs.includes(args[0]); if(["version", "--version", "-v"].includes(args[0])) { // Do nothing since version gets printed for every command } else { - if (isDefaultCommand) { + if (isDefaultCommand && !isHelpArg) { // console.log("Choose a command to run"); // new EntryCommand().help(); @@ -46,7 +46,7 @@ if (parseFloat(nodeVersion) >= 10.0) { execSync(`${getRecorderDistCommand()} --crusher-cli-path=${eval("__dirname") + "/index.js"} ${customFlags} --no-sandbox`, {stdio: "inherit"}); }); - } else if(helpArgs.includes(args[0])) { + } else if(isHelpArg) { new EntryCommand().help(); } else { new EntryCommand().run(); diff --git a/packages/cli/src/constants.ts b/packages/cli/src/constants.ts index 9fcf4e5f40..47726b4be1 100644 --- a/packages/cli/src/constants.ts +++ b/packages/cli/src/constants.ts @@ -1,8 +1,8 @@ import * as path from "path"; import { getIsArm, getRuntimeEnv } from "./utils/utils"; -export const BACKEND_SERVER_URL = "https://backend.crusher.dev"; -export const FRONTEND_SERVER_URL = "https://app.crusher.dev"; +export const BACKEND_SERVER_URL = "http://localhost:8000"; +export const FRONTEND_SERVER_URL = "http://localhost:3000"; export const APP_DIRECTORY = getRuntimeEnv().CRUSHER_GLOBAL_DIR || diff --git a/packages/cli/src/utils/hooks.ts b/packages/cli/src/utils/hooks.ts index 9d200d1397..3c5f9aba8f 100644 --- a/packages/cli/src/utils/hooks.ts +++ b/packages/cli/src/utils/hooks.ts @@ -20,7 +20,7 @@ const secretInviteCode = "crush" */ const checkForDiscord = async()=>{ const isCodeInCommandLine = process.argv.some((e)=>{ - return e.includes("--invite-code=") && !["help", "--help", "-h"].includes(e) + return e.includes("--code=") && !["help", "--help", "-h"].includes(e) }) const hasLoginFlag = process.argv.some((e) => e.includes("--login")); @@ -41,28 +41,36 @@ const checkForDiscord = async()=>{ } } +const parseDiscordFlag = (flag: string) => { + if(!flag) return null; + return flag.split("--code=")[1]; +}; + const waitForUserLogin = async (): Promise => { await checkForDiscord(); // ask for discord code here? - const discordCode = process.argv.find((i)=>{ - return i.includes("--invite-code=") - }); + + const discordCode = parseDiscordFlag(process.argv.find((i)=>{ + return i.includes("--code="); + })); + const loginKey = await axios .get(resolveBackendServerUrl("/cli/get.key")) .then((res) => { return res.data.loginKey; }); + const loginUrl = resolveFrontendServerUrl(`/login_sucessful?lK=${loginKey}&inviteCode=${discordCode}`); await cli.log( "Login or create an account to create/sync tests⚡⚡. Opening a browser to sync test.\nOr open this link:" ); - await cli.log(`${resolveFrontendServerUrl(`/login_sucessful?lK=${loginKey}&code=${discordCode}`)} \n`); + await cli.log(`${loginUrl} \n`); await cli.action.start("Waiting for login"); await cli - .open(`${resolveFrontendServerUrl(`/login_sucessful?lK=${loginKey}&code=${discordCode}`)}`) + .open(loginUrl) .catch((err) => { console.error(err); }); diff --git a/packages/crusher-app/src/hooks/tempTest.tsx b/packages/crusher-app/src/hooks/tempTest.tsx index 7cda8d0c15..ac15f0d925 100644 --- a/packages/crusher-app/src/hooks/tempTest.tsx +++ b/packages/crusher-app/src/hooks/tempTest.tsx @@ -12,6 +12,7 @@ import { cliLoginUserKeyAtom } from "@store/atoms/global/cliToken"; import { backendRequest } from "@utils/common/backendRequest"; import { resolvePathToBackendURI } from "@utils/common/url"; import { RequestMethod } from "@types/RequestOptions"; +import { inviteCodeUserKeyAtom } from "@store/atoms/global/inviteCode"; export const useLoadTempData = () => { const [, setTempTest] = useAtom(tempTestAtom); @@ -21,6 +22,7 @@ export const useLoadTempData = () => { const [, setGithubToken] = useAtom(githubTokenAtom); const [, setLoginKey] = useAtom(cliLoginUserKeyAtom); const [, setProjectToRedirect] = useAtom(tempProjectAtom); + const [, setInviteCode] = useAtom(inviteCodeUserKeyAtom); const { asPath } = useRouter(); @@ -35,6 +37,7 @@ export const useLoadTempData = () => { const githubToken = urlQuery.get("github_token"); const loginKey = urlQuery.get("lK"); + const inviteCode = urlQuery.get("inviteCode"); setTempTestName(tempTestName); setTempTest(tempTestId); @@ -50,6 +53,9 @@ export const useLoadTempData = () => { console.error("Request failed"); }); } + if(!!inviteCode) { + setInviteCode(inviteCode); + } if (githubToken) { setGithubToken(githubToken); } diff --git a/packages/crusher-app/src/store/atoms/global/inviteCode.ts b/packages/crusher-app/src/store/atoms/global/inviteCode.ts new file mode 100644 index 0000000000..276f52fef3 --- /dev/null +++ b/packages/crusher-app/src/store/atoms/global/inviteCode.ts @@ -0,0 +1,15 @@ +import { atom } from "jotai"; + +const LOCAL_STORAGE_KEY = "inviteCodeUserKeyAtom"; +const primitiveInviteCodeUserKeyAtom = atom(typeof window !== "undefined" ? localStorage.getItem(LOCAL_STORAGE_KEY) ?? null : null); + +export const inviteCodeUserKeyAtom = atom( + (get) => get(primitiveInviteCodeUserKeyAtom), + (_get, set, newValue: any) => { + set(primitiveInviteCodeUserKeyAtom, newValue); + if(newValue == null) { + window.localStorage.removeItem(LOCAL_STORAGE_KEY); + } + window.localStorage.setItem(LOCAL_STORAGE_KEY, newValue); + }, +); diff --git a/packages/crusher-app/src_ee/ui/containers/auth/signup_email.tsx b/packages/crusher-app/src_ee/ui/containers/auth/signup_email.tsx index cc39178cbc..817b04b286 100644 --- a/packages/crusher-app/src_ee/ui/containers/auth/signup_email.tsx +++ b/packages/crusher-app/src_ee/ui/containers/auth/signup_email.tsx @@ -12,6 +12,8 @@ import { FormInput } from "./components/FormInput"; import { LoginNavBar } from "@ui/containers/common/login/navbar"; import { backendRequest } from "@utils/common/backendRequest"; import { RequestMethod } from "@types/RequestOptions"; +import { inviteCodeUserKeyAtom } from "@store/atoms/global/inviteCode"; +import { useAtom } from "jotai"; const registerUser = (name: string, email: string, password: string, inviteType: string | null = null, inviteCode: string | null = null) => { return backendRequest("/users/actions/signup", { @@ -28,8 +30,15 @@ export default function Signup_email({ loginWithEmailHandler }) { const [email, setEmail] = useState({ value: "", error: "" }); const [password, setPassword] = useState({ value: "", error: "" }); const [name, setName] = useState({ value: "", error: "" }); + const [sessionInviteCode, setSessionInviteCode] = useAtom(inviteCodeUserKeyAtom); + const [inviteCode, setInviteCode] = React.useState({value: "", error: ""}); + React.useEffect(() => { + if(sessionInviteCode) { + setInviteCode({value: sessionInviteCode, error: ""}); + } + }, [sessionInviteCode]); const [loading, setLoading] = useState(false); const emailChange = useCallback( @@ -87,6 +96,7 @@ export default function Signup_email({ loginWithEmailHandler }) { try { const data = await registerUser(name.value, email.value, password.value, query?.inviteType?.toString(), query?.inviteCode?.toString()); setData(data.systemInfo); + setSessionInviteCode(null); } catch (e: any) { console.error(e); alert(e.message === "USER_EMAIL_NOT_AVAILABLE" ? "User already registered" : "Some error occurred while registering"); @@ -184,7 +194,7 @@ export default function Signup_email({ loginWithEmailHandler }) { onBlur={verifyInfo.bind(this, false)} />
- Don't have any? Get one + Don't have any? Get one
diff --git a/packages/crusher-server/src/modules/resources/cli/controller.ts b/packages/crusher-server/src/modules/resources/cli/controller.ts index 2d8e082a29..8d6ebcf21c 100644 --- a/packages/crusher-server/src/modules/resources/cli/controller.ts +++ b/packages/crusher-server/src/modules/resources/cli/controller.ts @@ -13,7 +13,7 @@ class CLIController { @Get("/cli/get.key") async getUniqueLoginKey() { const key = uuidv4() + Date.now(); - await this.redisManager.set(key, JSON.stringify({ userId: null, teamId: null }), { expiry: { type: "s", value: 5 * 60 } }); + await this.redisManager.set(key, JSON.stringify({ userId: null, teamId: null }), { expiry: { type: "s", value: 60 * 60 } }); return { loginKey: key }; } From 1ac46528f5d4ac7339b68a03df8cd2b6696d0a8c Mon Sep 17 00:00:00 2001 From: Utkarsh Dixit Date: Thu, 25 Aug 2022 12:21:30 +0530 Subject: [PATCH 4/6] WIP --- packages/cli/src/constants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/constants.ts b/packages/cli/src/constants.ts index 47726b4be1..9fcf4e5f40 100644 --- a/packages/cli/src/constants.ts +++ b/packages/cli/src/constants.ts @@ -1,8 +1,8 @@ import * as path from "path"; import { getIsArm, getRuntimeEnv } from "./utils/utils"; -export const BACKEND_SERVER_URL = "http://localhost:8000"; -export const FRONTEND_SERVER_URL = "http://localhost:3000"; +export const BACKEND_SERVER_URL = "https://backend.crusher.dev"; +export const FRONTEND_SERVER_URL = "https://app.crusher.dev"; export const APP_DIRECTORY = getRuntimeEnv().CRUSHER_GLOBAL_DIR || From 4461d81042f613af482d963aac113bf38f46ef1d Mon Sep 17 00:00:00 2001 From: Utkarsh Dixit Date: Thu, 25 Aug 2022 15:41:57 +0530 Subject: [PATCH 5/6] WIP --- .../src/utils/common/validationUtils.ts | 2 +- .../crusher-app/src/utils/core/external.ts | 14 ++++++---- .../src_ee/ui/containers/auth/login.tsx | 2 +- .../src_ee/ui/containers/auth/signup.tsx | 6 ++++- .../ui/containers/auth/signup_email.tsx | 26 +++++++++---------- .../resources/integrations/controller.ts | 4 ++- .../modules/resources/users/auth.service.ts | 7 +++-- .../src/modules/resources/users/controller.ts | 22 ++++++++++++++-- .../src/modules/resources/users/service.ts | 3 ++- 9 files changed, 59 insertions(+), 27 deletions(-) diff --git a/packages/crusher-app/src/utils/common/validationUtils.ts b/packages/crusher-app/src/utils/common/validationUtils.ts index c468782629..43f1966c4c 100644 --- a/packages/crusher-app/src/utils/common/validationUtils.ts +++ b/packages/crusher-app/src/utils/common/validationUtils.ts @@ -19,6 +19,6 @@ export const validateName = (name: string) => { return true; }; -export const validateInviteCode = (inviteCode: string) => { +export const validateSessionInviteCode = (inviteCode: string) => { return inviteCode && inviteCode.startsWith("CRU-"); }; diff --git a/packages/crusher-app/src/utils/core/external.ts b/packages/crusher-app/src/utils/core/external.ts index 00d8877ff9..9efd5d8db2 100644 --- a/packages/crusher-app/src/utils/core/external.ts +++ b/packages/crusher-app/src/utils/core/external.ts @@ -24,11 +24,15 @@ const getGithubOAuthURLLegacy = (alreadyAuthorized = false) => { return githubUrl.toString(); }; -export const getGithubLoginURL = () => { - const url = new URL("https://github.com/login/oauth/authorize"); - url.searchParams.append("client_id", CLIENT_ID); - url.searchParams.append("state", `${btoa(JSON.stringify({ type: "auth" }))}`); - +export const getGithubLoginURL = (inviteType, inviteCode, sessionInviteCode) => { + const url = new URL(resolvePathToBackendURI("/users/actions/auth.github")); + if(inviteCode && inviteType) { + url.searchParams.append("inviteCode", inviteCode); + url.searchParams.append("inviteType", inviteType); + } + if(sessionInviteCode) { + url.searchParams.append("sessionInviteCode", sessionInviteCode); + } return url.toString(); }; diff --git a/packages/crusher-app/src_ee/ui/containers/auth/login.tsx b/packages/crusher-app/src_ee/ui/containers/auth/login.tsx index f02c7abf54..282b936532 100644 --- a/packages/crusher-app/src_ee/ui/containers/auth/login.tsx +++ b/packages/crusher-app/src_ee/ui/containers/auth/login.tsx @@ -88,7 +88,7 @@ export default function Login({ loginWithEmailHandler }) {
- + - {/*