Skip to content

Commit

Permalink
fix: Fix auth errors if auth is not configured.
Browse files Browse the repository at this point in the history
  • Loading branch information
SamTolmay committed May 25, 2022
1 parent 2ef19d9 commit 8a386a8
Show file tree
Hide file tree
Showing 41 changed files with 337 additions and 75 deletions.
16 changes: 1 addition & 15 deletions packages/api/src/context/errors.js
Expand Up @@ -16,13 +16,6 @@

/* eslint-disable max-classes-per-file */

class AuthenticationError extends Error {
constructor(message) {
super(message);
this.name = 'AuthenticationError';
}
}

class ConfigurationError extends Error {
constructor(message) {
super(message);
Expand All @@ -44,11 +37,4 @@ class ServerError extends Error {
}
}

class TokenExpiredError extends Error {
constructor(message) {
super(message);
this.name = 'TokenExpiredError';
}
}

export { AuthenticationError, ConfigurationError, RequestError, ServerError, TokenExpiredError };
export { ConfigurationError, RequestError, ServerError };
12 changes: 2 additions & 10 deletions packages/api/src/index.js
Expand Up @@ -17,20 +17,13 @@
import callRequest from './routes/request/callRequest.js';
import createApiContext from './context/createApiContext.js';
import getHomeAndMenus from './routes/rootConfig/getHomeAndMenus.js';
import getNextAuthConfig from './auth/getNextAuthConfig.js';
import getNextAuthConfig from './routes/auth/getNextAuthConfig.js';
import getPageConfig from './routes/page/getPageConfig.js';
import getRootConfig from './routes/rootConfig/getRootConfig.js';

import {
AuthenticationError,
ConfigurationError,
RequestError,
ServerError,
TokenExpiredError,
} from './context/errors.js';
import { ConfigurationError, RequestError, ServerError } from './context/errors.js';

export {
AuthenticationError,
callRequest,
ConfigurationError,
createApiContext,
Expand All @@ -40,5 +33,4 @@ export {
getRootConfig,
RequestError,
ServerError,
TokenExpiredError,
};
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions packages/build/src/build/buildAuth/buildAuth.js
Expand Up @@ -16,12 +16,16 @@
limitations under the License.
*/

import { type } from '@lowdefy/helpers';
import buildAuthPlugins from './buildAuthPlugins.js';
import buildPageAuth from './buildPageAuth.js';
import validateAuthConfig from './validateAuthConfig.js';

function buildAuth({ components, context }) {
const configured = !type.isNone(components.auth);

validateAuthConfig({ components });
components.auth.configured = configured;
buildPageAuth({ components });
buildAuthPlugins({ components, context });

Expand Down
2 changes: 0 additions & 2 deletions packages/client/src/Client.js
Expand Up @@ -30,7 +30,6 @@ const Client = ({
config,
resetContext = { reset: false, setReset: () => undefined },
router,
session,
stage,
types,
window,
Expand All @@ -40,7 +39,6 @@ const Client = ({
Components,
config,
router,
session,
stage,
types,
window,
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/initLowdefyContext.js
Expand Up @@ -44,7 +44,7 @@ const lowdefy = {
lowdefyGlobal: {},
};

function initLowdefyContext({ auth, Components, config, router, session, stage, types, window }) {
function initLowdefyContext({ auth, Components, config, router, stage, types, window }) {
if (stage === 'dev') {
window.lowdefy = lowdefy;
}
Expand All @@ -54,7 +54,7 @@ function initLowdefyContext({ auth, Components, config, router, session, stage,
lowdefy.menus = config.rootConfig.menus;
lowdefy.pageId = config.pageConfig.pageId;
lowdefy.urlQuery = urlQuery.parse(window.location.search.slice(1));
lowdefy.user = session?.user ?? null;
lowdefy.user = auth?.session?.user ?? null;

lowdefy._internal.window = window;
lowdefy._internal.document = window.document;
Expand Down
3 changes: 2 additions & 1 deletion packages/server-dev/lib/App.js
Expand Up @@ -31,7 +31,7 @@ import blocks from '../build/plugins/blocks.js';
import icons from '../build/plugins/icons.js';
import operators from '../build/plugins/operators/client.js';

const App = () => {
const App = ({ auth }) => {
const router = useRouter();
const { data: rootConfig } = useRootConfig(router.basePath);

Expand All @@ -44,6 +44,7 @@ const App = () => {
<Reload basePath={router.basePath}>
{(resetContext) => (
<Page
auth={auth}
Components={{ Head, Link }}
config={{
rootConfig,
Expand Down
11 changes: 2 additions & 9 deletions packages/server-dev/lib/Page.js
Expand Up @@ -15,20 +15,14 @@
*/

import React from 'react';
import { signIn, signOut, useSession } from 'next-auth/react';

import Client from '@lowdefy/client';

import RestartingPage from './RestartingPage.js';
import usePageConfig from './utils/usePageConfig.js';

const Page = ({ Components, config, pageId, resetContext, router, types }) => {
const { data: session, status } = useSession();
const Page = ({ auth, Components, config, pageId, resetContext, router, types }) => {
const { data: pageConfig } = usePageConfig(pageId, router.basePath);

if (status === 'loading') {
return '';
}
if (!pageConfig) {
router.replace(`/404`);
return '';
Expand All @@ -38,15 +32,14 @@ const Page = ({ Components, config, pageId, resetContext, router, types }) => {
}
return (
<Client
auth={{ signIn, signOut }}
auth={auth}
Components={Components}
config={{
...config,
pageConfig,
}}
resetContext={resetContext}
router={router}
session={session}
stage="dev"
types={types}
window={window}
Expand Down
35 changes: 35 additions & 0 deletions packages/server-dev/lib/auth/Auth.js
@@ -0,0 +1,35 @@
/*
Copyright 2020-2022 Lowdefy, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* eslint-disable react/jsx-props-no-spreading */

import React from 'react';
import AuthConfigured from './AuthConfigured.js';
import AuthNotConfigured from './AuthNotConfigured.js';

import authConfig from '../../build/auth.json';

function Auth({ children, session }) {
if (authConfig.configured === true) {
return (
<AuthConfigured session={session} authConfig={authConfig}>
{(auth) => children(auth)}
</AuthConfigured>
);
}
return <AuthNotConfigured authConfig={authConfig}>{(auth) => children(auth)}</AuthNotConfigured>;
}

export default Auth;
47 changes: 47 additions & 0 deletions packages/server-dev/lib/auth/AuthConfigured.js
@@ -0,0 +1,47 @@
/*
Copyright 2020-2022 Lowdefy, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* eslint-disable react/jsx-props-no-spreading */

import React from 'react';
import { SessionProvider, signIn, signOut, useSession } from 'next-auth/react';

function Session({ children }) {
const { data: session, status } = useSession();
// If session is passed to SessionProvider from getServerSideProps
// we won't have a loading state here.
// But 404 uses getStaticProps so we have this for 404.
if (status === 'loading') {
return '';
}
return children(session);
}

function AuthConfigured({ authConfig, children, serverSession }) {
const auth = { signIn, signOut, authConfig };

return (
<SessionProvider session={serverSession}>
<Session>
{(session) => {
auth.session = session;
return children(auth);
}}
</Session>
</SessionProvider>
);
}

export default AuthConfigured;
32 changes: 32 additions & 0 deletions packages/server-dev/lib/auth/AuthNotConfigured.js
@@ -0,0 +1,32 @@
/*
Copyright 2020-2022 Lowdefy, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* eslint-disable react/jsx-props-no-spreading */

function authNotConfigured() {
throw new Error('Auth not configured.');
}

function AuthNotConfigured({ authConfig, children }) {
const auth = {
authConfig,
signIn: authNotConfigured,
signOut: authNotConfigured,
};

return children(auth);
}

export default AuthNotConfigured;
27 changes: 27 additions & 0 deletions packages/server-dev/lib/auth/getServerSession.js
@@ -0,0 +1,27 @@
/*
Copyright 2020-2022 Lowdefy, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import { getSession } from 'next-auth/react';
import authJson from '../../build/auth.json';

async function getServerSession(context) {
if (authJson.configured === true) {
return await getSession(context);
}
return undefined;
}

export default getServerSession;
7 changes: 3 additions & 4 deletions packages/server-dev/pages/_app.js
Expand Up @@ -16,17 +16,16 @@

import React, { Suspense } from 'react';
import dynamic from 'next/dynamic';
import { SessionProvider } from 'next-auth/react';

import Auth from '../lib/auth/Auth.js';

// Must be in _app due to next specifications.
import '../build/plugins/styles.less';

function App({ Component }) {
return (
<Suspense fallback="">
<SessionProvider>
<Component />
</SessionProvider>
<Auth>{(auth) => <Component auth={auth} />}</Auth>
</Suspense>
);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/server-dev/pages/api/page/[pageId].js
Expand Up @@ -15,10 +15,10 @@
*/

import { createApiContext, getPageConfig } from '@lowdefy/api';
import { getSession } from 'next-auth/react';
import getServerSession from '../../../lib/auth/getServerSession.js';

export default async function handler(req, res) {
const session = await getSession({ req });
const session = await getServerSession({ req });
const apiContext = await createApiContext({
buildDirectory: './build',
logger: console,
Expand Down
5 changes: 3 additions & 2 deletions packages/server-dev/pages/api/request/[pageId]/[requestId].js
Expand Up @@ -16,16 +16,17 @@

import { callRequest, createApiContext } from '@lowdefy/api';
import { getSecretsFromEnv } from '@lowdefy/node-utils';
import { getSession } from 'next-auth/react';

import connections from '../../../../build/plugins/connections.js';
import getServerSession from '../../../../lib/auth/getServerSession.js';
import operators from '../../../../build/plugins/operators/server.js';

export default async function handler(req, res) {
try {
if (req.method !== 'POST') {
throw new Error('Only POST requests are supported.');
}
const session = await getSession({ req });
const session = await getServerSession({ req });
const apiContext = await createApiContext({
buildDirectory: './build',
connections,
Expand Down
5 changes: 3 additions & 2 deletions packages/server-dev/pages/api/root.js
Expand Up @@ -15,10 +15,11 @@
*/

import { createApiContext, getRootConfig } from '@lowdefy/api';
import { getSession } from 'next-auth/react';

import getServerSession from '../../lib/auth/getServerSession.js';

export default async function handler(req, res) {
const session = await getSession({ req });
const session = await getServerSession({ req });
const apiContext = await createApiContext({
buildDirectory: './build',
logger: console,
Expand Down

0 comments on commit 8a386a8

Please sign in to comment.