Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable cloud backend for unverified users; use local backend as default backend; minor bugfixes #6779

Merged
merged 17 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion app/ide-desktop/lib/content/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ const FETCH_TIMEOUT = 300

if (IS_DEV_MODE) {
new EventSource(ESBUILD_PATH).addEventListener(ESBUILD_EVENT_NAME, () => {
location.reload()
// This acts like `location.reload`, but it preserves the query-string.
// The `toString()` is to bypass a lint without using a comment.
location.href = location.href.toString()
})
void navigator.serviceWorker.register(SERVICE_WORKER_PATH)
}
Expand Down
2 changes: 1 addition & 1 deletion app/ide-desktop/lib/content/src/serviceWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ declare const self: ServiceWorkerGlobalScope
self.addEventListener('fetch', event => {
const url = new URL(event.request.url)
if (url.hostname === 'localhost' && url.pathname !== '/esbuild') {
const responsePromise = /\/[^.]+$/.test(event.request.url)
const responsePromise = /\/[^.]+$/.test(new URL(event.request.url).pathname)
? fetch('/index.html')
: fetch(event.request.url)
event.respondWith(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import * as errorModule from '../../error'
import * as http from '../../http'
import * as loggerProvider from '../../providers/logger'
import * as newtype from '../../newtype'
import * as platform from '../../platform'
import * as platformModule from '../../platform'
import * as remoteBackend from '../../dashboard/remoteBackend'
import * as sessionProvider from './session'

Expand All @@ -35,25 +35,29 @@ const MESSAGES = {
pleaseWait: 'Please wait...',
} as const

// =============
// === Types ===
// =============

// ===================
// === UserSession ===
// ===================

/** A user session for a user that may be either fully registered,
* or in the process of registering. */
export type UserSession = FullUserSession | PartialUserSession
/** Possible types of {@link BaseUserSession}. */
export enum UserSessionType {
partial = 'partial',
awaitingAcceptance = 'awaitingAcceptance',
full = 'full',
}

/** Object containing the currently signed-in user's session data. */
export interface FullUserSession {
/** A discriminator for TypeScript to be able to disambiguate between this interface and other
* `UserSession` variants. */
variant: 'full'
/** Properties common to all {@link UserSession}s. */
interface BaseUserSession<Type extends UserSessionType> {
/** A discriminator for TypeScript to be able to disambiguate between `UserSession` variants. */
type: Type
/** User's JSON Web Token (JWT), used for authenticating and authorizing requests to the API. */
accessToken: string
/** User's email address. */
email: string
}

/** Object containing the currently signed-in user's session data. */
export interface FullUserSession extends BaseUserSession<UserSessionType.full> {
/** User's organization information. */
organization: backendModule.UserOrOrganization
}
Expand All @@ -64,15 +68,11 @@ export interface FullUserSession {
* If a user has not yet set their username, they do not yet have an organization associated with
* their account. Otherwise, this type is identical to the `Session` type. This type should ONLY be
* used by the `SetUsername` component. */
export interface PartialUserSession {
/** A discriminator for TypeScript to be able to disambiguate between this interface and other
* `UserSession` variants. */
variant: 'partial'
/** User's JSON Web Token (JWT), used for authenticating and authorizing requests to the API. */
accessToken: string
/** User's email address. */
email: string
}
export interface PartialUserSession extends BaseUserSession<UserSessionType.partial> {}

/** A user session for a user that may be either fully registered,
* or in the process of registering. */
export type UserSession = FullUserSession | PartialUserSession

// ===================
// === AuthContext ===
Expand Down Expand Up @@ -140,14 +140,15 @@ const AuthContext = react.createContext<AuthContextType>({} as AuthContextType)
/** Props for an {@link AuthProvider}. */
export interface AuthProviderProps {
authService: authServiceModule.AuthService
platform: platformModule.Platform
/** Callback to execute once the user has authenticated successfully. */
onAuthenticated: () => void
children: react.ReactNode
}

/** A React provider for the Cognito API. */
export function AuthProvider(props: AuthProviderProps) {
const { authService, children } = props
const { authService, platform, children } = props
const { cognito } = authService
const { session } = sessionProvider.useSession()
const { setBackend } = backendProvider.useSetBackend()
Expand All @@ -173,20 +174,21 @@ export function AuthProvider(props: AuthProviderProps) {
headers.append('Authorization', `Bearer ${accessToken}`)
const client = new http.Client(headers)
const backend = new remoteBackend.RemoteBackend(client, logger)
setBackend(backend)
if (platform === platformModule.Platform.cloud) {
setBackend(backend)
}
const organization = await backend.usersMe().catch(() => null)
let newUserSession: UserSession
const sharedSessionData = { email, accessToken }
if (!organization) {
newUserSession = {
variant: 'partial',
email,
accessToken,
type: UserSessionType.partial,
...sharedSessionData,
}
} else {
newUserSession = {
variant: 'full',
email,
accessToken,
type: UserSessionType.full,
...sharedSessionData,
organization,
}

Expand Down Expand Up @@ -272,7 +274,7 @@ export function AuthProvider(props: AuthProviderProps) {
username: string,
email: string
) => {
if (backend.platform === platform.Platform.desktop) {
if (backend.platform === platformModule.Platform.desktop) {
toast.error('You cannot set your username on the local backend.')
return false
} else {
Expand Down Expand Up @@ -395,7 +397,7 @@ export function ProtectedLayout() {

if (!session) {
return <router.Navigate to={app.LOGIN_PATH} />
} else if (session.variant === 'partial') {
} else if (session.type === UserSessionType.partial) {
return <router.Navigate to={app.SET_USERNAME_PATH} />
} else {
return <router.Outlet context={session} />
Expand All @@ -411,7 +413,7 @@ export function ProtectedLayout() {
export function SemiProtectedLayout() {
const { session } = useAuth()

if (session?.variant === 'full') {
if (session?.type === UserSessionType.full) {
return <router.Navigate to={app.DASHBOARD_PATH} />
} else {
return <router.Outlet context={session} />
Expand All @@ -427,9 +429,9 @@ export function SemiProtectedLayout() {
export function GuestLayout() {
const { session } = useAuth()

if (session?.variant === 'partial') {
if (session?.type === UserSessionType.partial) {
return <router.Navigate to={app.SET_USERNAME_PATH} />
} else if (session?.variant === 'full') {
} else if (session?.type === UserSessionType.full) {
return <router.Navigate to={app.DASHBOARD_PATH} />
} else {
return <router.Outlet />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import * as router from 'react-router-dom'
import * as toast from 'react-hot-toast'

import * as authService from '../authentication/service'
import * as localBackend from '../dashboard/localBackend'
import * as platformModule from '../platform'

import * as authProvider from '../authentication/providers/auth'
Expand Down Expand Up @@ -121,7 +122,7 @@ function App(props: AppProps) {
* because the {@link AppRouter} relies on React hooks, which can't be used in the same React
* component as the component that defines the provider. */
function AppRouter(props: AppProps) {
const { logger, showDashboard, onAuthenticated } = props
const { logger, platform, showDashboard, onAuthenticated } = props
const navigate = router.useNavigate()
const mainPageUrl = new URL(window.location.href)
const memoizedAuthService = react.useMemo(() => {
Expand Down Expand Up @@ -163,11 +164,20 @@ function AppRouter(props: AppProps) {
userSession={userSession}
registerAuthEventListener={registerAuthEventListener}
>
{/* @ts-expect-error Auth will always set this before dashboard is rendered. */}
<backendProvider.BackendProvider initialBackend={null}>
<backendProvider.BackendProvider
initialBackend={
platform === platformModule.Platform.desktop
? new localBackend.LocalBackend()
: // This is UNSAFE. However, the backend will be set by the
// authentication flow.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
null!
}
>
<authProvider.AuthProvider
authService={memoizedAuthService}
onAuthenticated={onAuthenticated}
platform={platform}
>
<modalProvider.ModalProvider>{routes}</modalProvider.ModalProvider>
</authProvider.AuthProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export interface UserOrOrganization {
id: UserOrOrganizationId
name: string
email: EmailAddress
/** If `false`, this account is awaiting acceptance from an admin, and endpoints other than
* `usersMe` will not work. */
isEnabled: boolean
}

/** Possible states that a project can be in. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ function ChangePasswordModal() {
onClick={event => {
event.stopPropagation()
}}
onSubmit={async event => {
event.preventDefault()
await onSubmit()
}}
className="flex flex-col bg-white shadow-md px-4 sm:px-6 md:px-8 lg:px-10 py-8 rounded-md w-full max-w-md"
>
<div className="font-medium self-center text-xl sm:text-2xl uppercase text-gray-800">
Expand Down
Loading