Skip to content

Commit

Permalink
chore: implement auth flow
Browse files Browse the repository at this point in the history
  • Loading branch information
pyadav committed Jul 27, 2023
1 parent 3f6fb3a commit da0298a
Show file tree
Hide file tree
Showing 17 changed files with 662 additions and 216 deletions.
6 changes: 4 additions & 2 deletions sdks/packages/shield-js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,17 @@ export interface Role {
}

export interface ShieldClientOptions {
endpoint: string;
endpoint?: string;
redirectSignup?: string;
redirectLogin?: string;
}

export interface InitialState {
sessionId?: string | null;
}

export interface ShieldProviderProps {
endpoint: string;
config: ShieldClientOptions;
children: React.ReactNode;
initialState?: InitialState;
}
7 changes: 5 additions & 2 deletions sdks/packages/shield-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@raystack/shield-react",
"version": "0.0.1",
"version": "0.0.4",
"description": "A react library for shield",
"type": "module",
"main": "dist/index.cjs",
Expand Down Expand Up @@ -38,6 +38,7 @@
}
],
"devDependencies": {
"@hookform/resolvers": "^3.1.1",
"@raystack/shield": "workspace:^",
"@size-limit/preset-small-lib": "^8.2.6",
"@types/react": "^18.2.5",
Expand All @@ -49,13 +50,15 @@
"prettier": "^2.5.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.45.2",
"size-limit": "^8.2.6",
"tsup": "^6.7.0",
"typescript": "4.7",
"yup": "^1.2.0",
"zustand": "^4.3.9"
},
"dependencies": {
"@raystack/apsara": "^0.10.1",
"@raystack/apsara": "^0.10.3",
"axios": "^1.4.0"
},
"publishConfig": {
Expand Down
77 changes: 77 additions & 0 deletions sdks/packages/shield-react/src/components/Container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Flex } from "@raystack/apsara";
import React, { ComponentPropsWithRef } from "react";

const styles = {
container: {
fontSize: "12px",
width: "100%",
minWidth: "220px",
maxWidth: "480px",
color: "var(--foreground-base)",

display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "32px",
},
logoContainer: {},
titleContainer: {
fontWeight: "400",
},
fieldset: {
width: "100%",
border: "1px solid transparent",
borderTopColor: "rgb(205, 211, 223)",
gridArea: "1 / 1",
padding: 0,
margin: "2px",
},
legend: {
fontSize: "8px",
margin: "auto",
padding: "0 4px",
},
};

const shadowOptions = {
none: "none",
xs: "0px 1px 2px 0px rgba(16, 24, 40, 0.06)",
sm: "0px 1px 4px 0px rgba(0, 0, 0, 0.09)",
md: "0px 4px 6px -2px rgba(16, 24, 40, 0.03), 0px 12px 16px -4px rgba(16, 24, 40, 0.08)",
lg: "0px 8px 8px -4px rgba(16, 24, 40, 0.03), 0px 20px 24px -4px rgba(16, 24, 40, 0.08)",
};

const borderRadiusOptions = {
none: "0",
xs: "4px",
sm: "8px",
md: "16px",
lg: "24px",
};

type ContainerProps = ComponentPropsWithRef<"div"> & {
children?: React.ReactNode;
shadow?: "none" | "xs" | "sm" | "md" | "lg";
radius?: "none" | "xs" | "sm" | "md" | "lg";
};

export const Container = ({
children,
shadow = "none",
radius = "md",
style,
}: ContainerProps) => {
return (
<Flex
style={{
...styles.container,
...style,
flexDirection: "column",
boxShadow: shadowOptions[shadow],
borderRadius: borderRadiusOptions[radius],
}}
>
{children}
</Flex>
);
};
51 changes: 51 additions & 0 deletions sdks/packages/shield-react/src/components/Header.tsx

Large diffs are not rendered by default.

140 changes: 36 additions & 104 deletions sdks/packages/shield-react/src/components/login.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,27 @@
import { Text } from "@raystack/apsara";
import { Flex, Link, Text } from "@raystack/apsara";
import React, { ComponentPropsWithRef, useCallback } from "react";
import { useShield } from "../contexts/ShieldContext";
import { Container } from "./Container";
import { Header } from "./Header";
import { MagicLink } from "./magiclink";
import { OIDCButton } from "./oidc";

const styles = {
container: {
fontSize: "12px",

width: "28rem",
maxWidth: "100%",
padding: "1.5rem",

color: "rgb(60, 74, 90)",
backgroundColor: "#FFF",

display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "8px",
},
logoContainer: {
marginBottom: "1.5rem",
},
titleContainer: {
fontSize: "14px",
fontWeight: "bold",
marginBottom: "1rem",
},
fieldset: {
width: "100%",
border: "1px solid transparent",
borderTopColor: "rgb(205, 211, 223)",
gridArea: "1 / 1",
padding: 0,
margin: "2px",
fontWeight: "400",
},
legend: {
fontSize: "8px",
margin: "auto",
padding: "0 4px",
},
};

const shadowOptions = {
none: "none",
xs: "0px 1px 2px 0px rgba(16, 24, 40, 0.06)",
sm: "0px 1px 4px 0px rgba(0, 0, 0, 0.09)",
md: "0px 4px 6px -2px rgba(16, 24, 40, 0.03), 0px 12px 16px -4px rgba(16, 24, 40, 0.08)",
lg: "0px 8px 8px -4px rgba(16, 24, 40, 0.03), 0px 20px 24px -4px rgba(16, 24, 40, 0.08)",
};

const borderRadiusOptions = {
none: "0",
xs: "4px",
sm: "8px",
md: "16px",
lg: "24px",
type SignedInProps = ComponentPropsWithRef<typeof Container> & {
logo?: React.ReactNode;
title?: string;
};

const defaultLogo = (
<img
src="logo.svg"
style={{ borderRadius: "8px", width: "40px", height: "40px" }}
></img>
);

type SignedInProps = ComponentPropsWithRef<typeof Container>;
export const SignedIn = (props: SignedInProps) => {
export const SignedIn = ({
logo,
title = "Login to Raypoint",
...props
}: SignedInProps) => {
const { config } = useShield();
const { client, strategies = [] } = useShield();

const clickHandler = useCallback(
Expand All @@ -82,53 +36,31 @@ export const SignedIn = (props: SignedInProps) => {

const mailotp = strategies.find((s) => s.name === "mailotp");
const filteredOIDC = strategies.filter((s) => s.name !== "mailotp");

return (
<Container {...props}>
{mailotp && <MagicLink />}
{mailotp && (
<fieldset style={{ ...styles.fieldset, boxSizing: "border-box" }}>
<legend style={styles.legend}>or</legend>
</fieldset>
)}
{filteredOIDC.map((s, index) => {
return (
<OIDCButton key={index} onClick={() => clickHandler(s.name)}>
{s.name}
</OIDCButton>
);
})}
<Header logo={logo} title={title} />
<Flex direction="column" style={{ width: "100%", gap: "var(--pd-16)" }}>
{filteredOIDC.map((s, index) => {
return (
<OIDCButton key={index} onClick={() => clickHandler(s.name)}>
{s.name}
</OIDCButton>
);
})}

{mailotp && <MagicLink />}
</Flex>
<div style={styles.titleContainer}>
<Text size={2}>
Don’t have an account?{" "}
<Link
href={config.redirectSignup}
style={{ color: "var(--foreground-accent)" }}
>
Signup
</Link>
</Text>
</div>
</Container>
);
};

type ContainerProps = ComponentPropsWithRef<"div"> & {
children?: React.ReactNode;
shadow?: "none" | "xs" | "sm" | "md" | "lg";
radius?: "none" | "xs" | "sm" | "md" | "lg";
title?: string;
logo?: React.ReactNode;
};

export const Container = ({
children,
shadow = "sm",
radius = "md",
title = "Sign in",
logo,
}: ContainerProps) => (
<div
style={{
...styles.container,
flexDirection: "column",
boxShadow: shadowOptions[shadow],
borderRadius: borderRadiusOptions[radius],
}}
>
<div style={styles.logoContainer}>{logo ? logo : defaultLogo}</div>
<div style={styles.titleContainer}>
<Text size={6}>{title}</Text>
</div>
{children}
</div>
);
Loading

0 comments on commit da0298a

Please sign in to comment.