Skip to content

Commit

Permalink
Merge pull request #15 from barbalex/auth
Browse files Browse the repository at this point in the history
Auth
  • Loading branch information
barbalex authored Apr 4, 2024
2 parents 20e9f50 + e087b90 commit 9ff7b8e
Show file tree
Hide file tree
Showing 15 changed files with 186 additions and 182 deletions.
2 changes: 1 addition & 1 deletion db/migrations/01-tables.sql
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
CREATE TABLE users(
user_id uuid PRIMARY KEY DEFAULT NULL,
email text DEFAULT NULL, -- TODO: email needs to be unique per account. But: not possible in electric-sql
auth_id uuid DEFAULT NULL,
label_replace_by_generated_column text DEFAULT NULL,
deleted boolean DEFAULT NULL
);
Expand Down Expand Up @@ -1364,6 +1363,7 @@ COMMENT ON COLUMN fields.level IS 'level of field if places or below: 1, 2';
CREATE TABLE ui_options(
user_id uuid PRIMARY KEY DEFAULT NULL REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
account_id uuid DEFAULT NULL REFERENCES accounts(account_id) ON DELETE CASCADE ON UPDATE CASCADE,
authenticated_email text DEFAULT NULL,
designing boolean DEFAULT NULL, -- FALSE,
breadcrumbs_overflowing boolean DEFAULT NULL, -- FALSE,
navs_overflowing boolean DEFAULT NULL, -- FALSE,
Expand Down
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ export default function App() {
ctx-name="uploadcare-uploader"
></lr-upload-ctx-provider>
<style dangerouslySetInnerHTML={{ __html: styleSheet() }} />
<SqlInitializer />
<Syncer />
<FluentProvider theme={lightTheme}>
<div style={routerContainerStyle}>
<SqlInitializer />
<Syncer />
<UploaderContext.Provider value={uploaderRef}>
<RouterProviderWithDb />
</UploaderContext.Provider>
Expand Down
8 changes: 8 additions & 0 deletions src/components/Auth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { CorbadoAuth } from '@corbado/react'

export const Auth = () => (
<CorbadoAuth
onLoggedIn={() => console.log('hi')}
customerSupportEmail="[email protected]"
/>
)
3 changes: 2 additions & 1 deletion src/components/Layout/Breadcrumbs/BreadcrumbForData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const isOdd = (num) => num % 2
const siblingStyle = {
marginLeft: 7,
}
const labelStyle = { userSelect: 'none' }

// forwarding refs is crucial for the overflow menu to work
// https://github.com/microsoft/fluentui/issues/27652#issuecomment-1520447241
Expand Down Expand Up @@ -162,7 +163,7 @@ export const BreadcrumbForData = forwardRef(
}
ref={ref}
>
<div className="text">{label}</div>
<div style={labelStyle}>{label}</div>
{!!sibling && <div style={siblingStyle}>{sibling}</div>}
<Menu navs={navs} />
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/components/Layout/Breadcrumbs/BreadcrumbForFolder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { user_id } from '../../SqlInitializer'
const siblingStyle = {
marginLeft: 7,
}
const labelStyle = { userSelect: 'none' }

// forwarding refs is crucial for the overflow menu to work
// https://github.com/microsoft/fluentui/issues/27652#issuecomment-1520447241
Expand Down Expand Up @@ -138,7 +139,7 @@ export const BreadcrumbForFolder = forwardRef(
}
ref={ref}
>
<div className="text">{label}</div>
<div style={labelStyle}>{label}</div>
{!!sibling && <div style={siblingStyle}>{sibling}</div>}
<Menu navs={navs} />
</div>
Expand Down
182 changes: 89 additions & 93 deletions src/components/Layout/Header/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import {
} from '@fluentui/react-components'
import { FaCog } from 'react-icons/fa'
import { MdLogout, MdLogin } from 'react-icons/md'
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
import {
useNavigate,
useParams,
useSearchParams,
useLocation,
} from 'react-router-dom'
import { useLiveQuery } from 'electric-sql/react'
import { useCorbado } from '@corbado/react'

Expand Down Expand Up @@ -50,9 +55,10 @@ export const Menu = memo(() => {
const params = useParams()
const [searchParams] = useSearchParams()

const { isAuthenticated, logout } = useCorbado()
const { pathname } = useLocation()
const isHome = pathname === '/'

console.log('hello Menu, isAuthenticated:', isAuthenticated)
const { isAuthenticated, logout } = useCorbado()

const { db } = useElectric()!
// get ui_options.tabs
Expand All @@ -78,112 +84,90 @@ export const Menu = memo(() => {
})
}, [navigate, params.user_id, searchParams])

const onClickLogin = useCallback(() => navigate('/auth'), [navigate])
const onClickLogout = useCallback(() => {
logout()
navigate('/auth')
}, [logout, navigate])
const onClickLogout = useCallback(() => logout(), [logout])
const onClickEnter = useCallback(() => navigate('/projects'), [navigate])

const treeIsActive = tabs.includes('tree')
const dataIsActive = tabs.includes('data')
const filterIsActive = tabs.includes('filter')
const mapIsActive = tabs.includes('map')

console.log('hello Menu rendering', { isAuthenticated, isHome })

return (
<div style={controls}>
<Toolbar
aria-label="active tabs"
checkedValues={{ tabs }}
onCheckedValueChange={onChangeTabs}
>
<ToolbarToggleButton
aria-label="Tree"
name="tabs"
value="tree"
style={css(
buildButtonStyle({
prevIsActive: false,
nextIsActive: dataIsActive,
selfIsActive: treeIsActive,
}),
)}
>
Tree
</ToolbarToggleButton>
<ToolbarToggleButton
aria-label="Data"
name="tabs"
value="data"
style={css(
buildButtonStyle({
prevIsActive: treeIsActive,
nextIsActive: filterIsActive,
selfIsActive: dataIsActive,
}),
)}
>
Data
</ToolbarToggleButton>
<ToolbarToggleButton
aria-label="Filter"
name="tabs"
value="filter"
style={css(
buildButtonStyle({
prevIsActive: dataIsActive,
nextIsActive: mapIsActive,
selfIsActive: filterIsActive,
}),
)}
>
Filter
</ToolbarToggleButton>
<ToolbarToggleButton
aria-label="Map"
name="tabs"
value="map"
style={css(
buildButtonStyle({
prevIsActive: filterIsActive,
nextIsActive: false,
selfIsActive: mapIsActive,
}),
)}
>
Map
</ToolbarToggleButton>
{!isHome && (
<>
<ToolbarToggleButton
aria-label="Tree"
name="tabs"
value="tree"
style={css(
buildButtonStyle({
prevIsActive: false,
nextIsActive: dataIsActive,
selfIsActive: treeIsActive,
}),
)}
>
Tree
</ToolbarToggleButton>
<ToolbarToggleButton
aria-label="Data"
name="tabs"
value="data"
style={css(
buildButtonStyle({
prevIsActive: treeIsActive,
nextIsActive: filterIsActive,
selfIsActive: dataIsActive,
}),
)}
>
Data
</ToolbarToggleButton>
<ToolbarToggleButton
aria-label="Filter"
name="tabs"
value="filter"
style={css(
buildButtonStyle({
prevIsActive: dataIsActive,
nextIsActive: mapIsActive,
selfIsActive: filterIsActive,
}),
)}
>
Filter
</ToolbarToggleButton>
<ToolbarToggleButton
aria-label="Map"
name="tabs"
value="map"
style={css(
buildButtonStyle({
prevIsActive: filterIsActive,
nextIsActive: false,
selfIsActive: mapIsActive,
}),
)}
>
Map
</ToolbarToggleButton>
</>
)}
</Toolbar>
<Button
size="medium"
icon={<FaCog />}
onClick={onClickOptions}
title="Options"
style={css({
backgroundColor: 'rgba(38, 82, 37, 0)',
border: 'none',
color: 'white',
on: ($) => [$('&:hover', { filter: 'brightness(85%)' })],
})}
/>
{isAuthenticated ? (
{!isHome && (
<Button
size="medium"
icon={<MdLogout />}
onClick={onClickLogout}
title="Log out"
style={css({
backgroundColor: 'rgba(38, 82, 37, 0)',
border: 'none',
color: 'white',
on: ($) => [$('&:hover', { filter: 'brightness(85%)' })],
})}
/>
) : (
<Button
size="medium"
icon={<MdLogin />}
onClick={onClickLogin}
title="Log in"
icon={<FaCog />}
onClick={onClickOptions}
title="Options"
style={css({
backgroundColor: 'rgba(38, 82, 37, 0)',
border: 'none',
Expand All @@ -192,6 +176,18 @@ export const Menu = memo(() => {
})}
/>
)}
<Button
size="medium"
icon={isAuthenticated && !isHome ? <MdLogout /> : <MdLogin />}
onClick={isAuthenticated && !isHome ? onClickLogout : onClickEnter}
title={!isAuthenticated ? 'Login' : isHome ? 'Enter' : 'Logout'}
style={css({
backgroundColor: 'rgba(38, 82, 37, 0)',
border: 'none',
color: 'white',
on: ($) => [$('&:hover', { filter: 'brightness(85%)' })],
})}
/>
</div>
)
})
2 changes: 1 addition & 1 deletion src/components/Layout/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const containerStyle = {
padding: '0 10px',
color: 'white',
}
const titleStyle = { fontSize: 'large' }
const titleStyle = { fontSize: 'large', userSelect: 'none' }

export const Header = () => {
return (
Expand Down
36 changes: 30 additions & 6 deletions src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,52 @@
import { useSearchParams } from 'react-router-dom'
import { useSearchParams, useLocation, Outlet } from 'react-router-dom'

import { Breadcrumbs } from './Breadcrumbs'
import { Navs } from './Navs'
import { Header } from './Header'
import { Main } from './Main'
import { Notifications } from '../Notifications'
import { ProtectedRoute } from '../ProtectedRoute'

const homeOutletStyle = {
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
overflow: 'hidden',
position: 'relative',
}

export const Layout = () => {
const [searchParams] = useSearchParams()
const onlyForm = searchParams.get('onlyForm')

// console.log('Layout rendering')
const { pathname } = useLocation()
const isHome = pathname === '/'

console.log('hello Layout rendering, location:', pathname)

// this is used to show forms inside popups in the map
if (onlyForm) {
return <Main />
}
if (onlyForm) return <Main />

// TODO: not logged in visitors
// should see only simplified header and home page
if (isHome) {
return (
<>
<Header />
<div style={homeOutletStyle}>
<Outlet />
</div>
</>
)
}
return (
<>
<Header />
<Breadcrumbs />
<Navs />
<Main />
<ProtectedRoute>
<Main />
</ProtectedRoute>
<Notifications />
</>
)
Expand Down
24 changes: 10 additions & 14 deletions src/components/ProtectedRoute.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { useCorbadoSession } from '@corbado/react'
import { useLocation, Navigate } from 'react-router-dom'
import { memo } from 'react'
import { useCorbado } from '@corbado/react'
import { Loading } from './shared/Loading'

// https://www.robinwieruch.de/react-router-authentication/
export const ProtectedRoute = ({ children }) => {
const { loading, isAuthenticated, user } = useCorbadoSession()
const location = useLocation()
import { Auth } from './Auth'

// console.warn('ProtectedRoute', { loading, isAuthenticated, user })
// https://www.robinwieruch.de/react-router-authentication/
export const ProtectedRoute = memo(({ children }) => {
const { loading, isAuthenticated } = useCorbado()
// console.log('hello ProtectedRoute', { loading, isAuthenticated })

if (loading) {
return <Loading label="Authenticating" />
}
if (loading) return <Loading label="Authenticating" />

if (!isAuthenticated || !user) {
return <Navigate to="/auth" replace state={{ from: location }} />
}
if (!isAuthenticated) return <Auth />

return children
}
})
Loading

0 comments on commit 9ff7b8e

Please sign in to comment.