mirror of
https://github.com/lowdefy/lowdefy.git
synced 2025-03-25 15:10:33 +08:00
Merge branch 'develop' into react-18
This commit is contained in:
commit
c1c1adec3a
@ -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);
|
||||
@ -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 };
|
||||
|
@ -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,
|
||||
@ -40,5 +33,4 @@ export {
|
||||
getRootConfig,
|
||||
RequestError,
|
||||
ServerError,
|
||||
TokenExpiredError,
|
||||
};
|
||||
|
@ -23,9 +23,55 @@ function createJWTCallback({ authConfig, plugins }) {
|
||||
type: 'jwt',
|
||||
});
|
||||
|
||||
if (jwtCallbackPlugins.length === 0) return undefined;
|
||||
|
||||
async function jwtCallback({ token, user, account, profile, isNewUser }) {
|
||||
if (profile) {
|
||||
const {
|
||||
sub,
|
||||
name,
|
||||
given_name,
|
||||
family_name,
|
||||
middle_name,
|
||||
nickname,
|
||||
preferred_username,
|
||||
profile: profile_claim,
|
||||
picture,
|
||||
website,
|
||||
email,
|
||||
email_verified,
|
||||
gender,
|
||||
birthdate,
|
||||
zoneinfo,
|
||||
locale,
|
||||
phone_number,
|
||||
phone_number_verified,
|
||||
address,
|
||||
updated_at,
|
||||
} = profile;
|
||||
token = {
|
||||
sub,
|
||||
name,
|
||||
given_name,
|
||||
family_name,
|
||||
middle_name,
|
||||
nickname,
|
||||
preferred_username,
|
||||
profile: profile_claim,
|
||||
picture,
|
||||
website,
|
||||
email,
|
||||
email_verified,
|
||||
gender,
|
||||
birthdate,
|
||||
zoneinfo,
|
||||
locale,
|
||||
phone_number,
|
||||
phone_number_verified,
|
||||
address,
|
||||
updated_at,
|
||||
...token,
|
||||
};
|
||||
}
|
||||
|
||||
for (const plugin of jwtCallbackPlugins) {
|
||||
token = await plugin.fn({
|
||||
properties: plugin.properties ?? {},
|
@ -24,8 +24,53 @@ function createSessionCallback({ authConfig, plugins }) {
|
||||
});
|
||||
|
||||
async function sessionCallback({ session, token, user }) {
|
||||
// console.log({ session, token, user });
|
||||
if (token) {
|
||||
session.user.sub = token.sub;
|
||||
const {
|
||||
sub,
|
||||
name,
|
||||
given_name,
|
||||
family_name,
|
||||
middle_name,
|
||||
nickname,
|
||||
preferred_username,
|
||||
profile,
|
||||
picture,
|
||||
website,
|
||||
email,
|
||||
email_verified,
|
||||
gender,
|
||||
birthdate,
|
||||
zoneinfo,
|
||||
locale,
|
||||
phone_number,
|
||||
phone_number_verified,
|
||||
address,
|
||||
updated_at,
|
||||
} = token;
|
||||
session.user = {
|
||||
sub,
|
||||
name,
|
||||
given_name,
|
||||
family_name,
|
||||
middle_name,
|
||||
nickname,
|
||||
preferred_username,
|
||||
profile,
|
||||
picture,
|
||||
website,
|
||||
email,
|
||||
email_verified,
|
||||
gender,
|
||||
birthdate,
|
||||
zoneinfo,
|
||||
locale,
|
||||
phone_number,
|
||||
phone_number_verified,
|
||||
address,
|
||||
updated_at,
|
||||
...session.user,
|
||||
};
|
||||
}
|
||||
|
||||
for (const plugin of sessionCallbackPlugins) {
|
@ -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 });
|
||||
|
||||
|
@ -31,6 +31,7 @@ test('buildAuth default', async () => {
|
||||
expect(res).toEqual({
|
||||
auth: {
|
||||
callbacks: [],
|
||||
configured: false,
|
||||
events: [],
|
||||
pages: {
|
||||
roles: {},
|
||||
@ -53,6 +54,7 @@ test('buildAuth no pages', async () => {
|
||||
expect(res).toEqual({
|
||||
auth: {
|
||||
callbacks: [],
|
||||
configured: false,
|
||||
events: [],
|
||||
pages: {
|
||||
roles: {},
|
||||
@ -82,6 +84,7 @@ test('buildAuth all protected, some public', async () => {
|
||||
expect(res).toEqual({
|
||||
auth: {
|
||||
callbacks: [],
|
||||
configured: true,
|
||||
events: [],
|
||||
pages: {
|
||||
public: ['a', 'b'],
|
||||
@ -117,6 +120,7 @@ test('buildAuth all public, some protected', async () => {
|
||||
expect(res).toEqual({
|
||||
auth: {
|
||||
callbacks: [],
|
||||
configured: true,
|
||||
events: [],
|
||||
pages: {
|
||||
protected: ['a', 'b'],
|
||||
@ -152,6 +156,7 @@ test('buildAuth all public', async () => {
|
||||
expect(res).toEqual({
|
||||
auth: {
|
||||
callbacks: [],
|
||||
configured: true,
|
||||
events: [],
|
||||
pages: {
|
||||
public: true,
|
||||
@ -188,6 +193,7 @@ test('buildAuth all protected', async () => {
|
||||
auth: {
|
||||
callbacks: [],
|
||||
events: [],
|
||||
configured: true,
|
||||
pages: {
|
||||
protected: true,
|
||||
roles: {},
|
||||
@ -224,6 +230,7 @@ test('buildAuth roles', async () => {
|
||||
expect(res).toEqual({
|
||||
auth: {
|
||||
callbacks: [],
|
||||
configured: true,
|
||||
events: [],
|
||||
pages: {
|
||||
roles: {
|
||||
@ -276,6 +283,7 @@ test('buildAuth roles and protected pages array', async () => {
|
||||
expect(res).toEqual({
|
||||
auth: {
|
||||
callbacks: [],
|
||||
configured: true,
|
||||
events: [],
|
||||
pages: {
|
||||
roles: {
|
||||
@ -307,6 +315,7 @@ test('buildAuth roles and protected true', async () => {
|
||||
expect(res).toEqual({
|
||||
auth: {
|
||||
callbacks: [],
|
||||
configured: true,
|
||||
events: [],
|
||||
pages: {
|
||||
roles: {
|
||||
|
@ -30,7 +30,6 @@ const Client = ({
|
||||
config,
|
||||
resetContext = { reset: false, setReset: () => undefined },
|
||||
router,
|
||||
session,
|
||||
stage,
|
||||
types,
|
||||
window,
|
||||
@ -40,7 +39,6 @@ const Client = ({
|
||||
Components,
|
||||
config,
|
||||
router,
|
||||
session,
|
||||
stage,
|
||||
types,
|
||||
window,
|
||||
|
@ -34,12 +34,14 @@ function getCallbackUrl({ lowdefy, callbackUrl = {} }) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function createAuthMethods(lowdefy, auth) {
|
||||
function createAuthMethods({ lowdefy, auth }) {
|
||||
// login and logout are Lowdefy function that handle action params
|
||||
// signIn and signOut are the next-auth methods
|
||||
function login({ providerId, callbackUrl, authUrl = {} } = {}) {
|
||||
// TODO: if only one provider exists, pass provider here
|
||||
// to link directly to provider
|
||||
if (type.isNone(providerId) && auth.authConfig.providers.length === 1) {
|
||||
providerId = auth.authConfig.providers[0].id;
|
||||
}
|
||||
|
||||
auth.signIn(
|
||||
providerId,
|
||||
{ callbackUrl: getCallbackUrl({ lowdefy, callbackUrl }) },
|
||||
|
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
@ -69,7 +69,7 @@ function initLowdefyContext({ auth, Components, config, router, session, stage,
|
||||
lowdefy._internal.operators = types.operators;
|
||||
|
||||
// TODO: discuss not using object arguments
|
||||
lowdefy._internal.auth = createAuthMethods(lowdefy, auth);
|
||||
lowdefy._internal.auth = createAuthMethods({ lowdefy, auth });
|
||||
|
||||
return lowdefy;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
@ -44,6 +44,7 @@ const App = () => {
|
||||
<Reload basePath={router.basePath}>
|
||||
{(resetContext) => (
|
||||
<Page
|
||||
auth={auth}
|
||||
Components={{ Head, Link }}
|
||||
config={{
|
||||
rootConfig,
|
||||
|
@ -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 '';
|
||||
@ -38,7 +32,7 @@ const Page = ({ Components, config, pageId, resetContext, router, types }) => {
|
||||
}
|
||||
return (
|
||||
<Client
|
||||
auth={{ signIn, signOut }}
|
||||
auth={auth}
|
||||
Components={Components}
|
||||
config={{
|
||||
...config,
|
||||
@ -46,7 +40,6 @@ const Page = ({ Components, config, pageId, resetContext, router, types }) => {
|
||||
}}
|
||||
resetContext={resetContext}
|
||||
router={router}
|
||||
session={session}
|
||||
stage="dev"
|
||||
types={types}
|
||||
window={window}
|
||||
|
35
packages/server-dev/lib/auth/Auth.js
Normal file
35
packages/server-dev/lib/auth/Auth.js
Normal file
@ -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
packages/server-dev/lib/auth/AuthConfigured.js
Normal file
47
packages/server-dev/lib/auth/AuthConfigured.js
Normal file
@ -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
packages/server-dev/lib/auth/AuthNotConfigured.js
Normal file
32
packages/server-dev/lib/auth/AuthNotConfigured.js
Normal file
@ -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
packages/server-dev/lib/auth/getServerSession.js
Normal file
27
packages/server-dev/lib/auth/getServerSession.js
Normal file
@ -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;
|
@ -16,7 +16,8 @@
|
||||
|
||||
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';
|
||||
@ -24,9 +25,7 @@ import '../build/plugins/styles.less';
|
||||
function App({ Component }) {
|
||||
return (
|
||||
<Suspense fallback="">
|
||||
<SessionProvider>
|
||||
<Component />
|
||||
</SessionProvider>
|
||||
<Auth>{(auth) => <Component auth={auth} />}</Auth>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -16,8 +16,9 @@
|
||||
|
||||
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) {
|
||||
@ -25,7 +26,7 @@ export default async function handler(req, res) {
|
||||
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,
|
||||
|
@ -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,
|
||||
|
@ -20,34 +20,23 @@ import { useRouter } from 'next/router';
|
||||
import Client from '@lowdefy/client';
|
||||
import Head from 'next/head';
|
||||
import Link from 'next/link';
|
||||
import { signIn, signOut, useSession } from 'next-auth/react';
|
||||
|
||||
import actions from '../build/plugins/actions.js';
|
||||
import blocks from '../build/plugins/blocks.js';
|
||||
import icons from '../build/plugins/icons.js';
|
||||
import operators from '../build/plugins/operators/client.js';
|
||||
|
||||
const Page = ({ pageConfig, rootConfig }) => {
|
||||
const Page = ({ auth, pageConfig, rootConfig }) => {
|
||||
const router = useRouter();
|
||||
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 (
|
||||
<Client
|
||||
auth={{ signIn, signOut }}
|
||||
auth={auth}
|
||||
Components={{ Head, Link }}
|
||||
config={{
|
||||
pageConfig,
|
||||
rootConfig,
|
||||
}}
|
||||
router={router}
|
||||
session={session}
|
||||
types={{
|
||||
actions,
|
||||
blocks,
|
||||
|
35
packages/server/lib/auth/Auth.js
Normal file
35
packages/server/lib/auth/Auth.js
Normal file
@ -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
packages/server/lib/auth/AuthConfigured.js
Normal file
47
packages/server/lib/auth/AuthConfigured.js
Normal file
@ -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
packages/server/lib/auth/AuthNotConfigured.js
Normal file
32
packages/server/lib/auth/AuthNotConfigured.js
Normal file
@ -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
packages/server/lib/auth/getServerSession.js
Normal file
27
packages/server/lib/auth/getServerSession.js
Normal file
@ -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;
|
@ -15,13 +15,13 @@
|
||||
*/
|
||||
|
||||
import { createApiContext, getPageConfig, getRootConfig } from '@lowdefy/api';
|
||||
import { getSession } from 'next-auth/react';
|
||||
|
||||
import getServerSession from '../lib/auth/getServerSession.js';
|
||||
import Page from '../lib/Page.js';
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
const { pageId } = context.params;
|
||||
const session = await getSession(context);
|
||||
const session = await getServerSession(context);
|
||||
const apiContext = await createApiContext({
|
||||
buildDirectory: './build',
|
||||
logger: console,
|
||||
|
@ -13,20 +13,21 @@
|
||||
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 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';
|
||||
|
||||
// TODO: SessionProvider requires basebath
|
||||
function App({ Component, pageProps: { session, ...pageProps } }) {
|
||||
function App({ Component, pageProps: { session, rootConfig, pageConfig } }) {
|
||||
return (
|
||||
<SessionProvider session={session}>
|
||||
<Component {...pageProps} />
|
||||
</SessionProvider>
|
||||
<Auth session={session}>
|
||||
{(auth) => <Component auth={auth} rootConfig={rootConfig} pageConfig={pageConfig} />}
|
||||
</Auth>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -22,4 +22,16 @@ import callbacks from '../../../build/plugins/auth/callbacks.js';
|
||||
import events from '../../../build/plugins/auth/events.js';
|
||||
import providers from '../../../build/plugins/auth/providers.js';
|
||||
|
||||
export default NextAuth(getNextAuthConfig({ authJson, plugins: { callbacks, events, providers } }));
|
||||
export default async function auth(req, res) {
|
||||
if (authJson.configured === true) {
|
||||
return await NextAuth(
|
||||
req,
|
||||
res,
|
||||
getNextAuthConfig({ authJson, plugins: { callbacks, events, providers } })
|
||||
);
|
||||
}
|
||||
|
||||
return res.status(404).json({
|
||||
message: 'Auth not configured',
|
||||
});
|
||||
}
|
||||
|
@ -16,7 +16,9 @@
|
||||
|
||||
import { callRequest, createApiContext } from '@lowdefy/api';
|
||||
import { getSecretsFromEnv } from '@lowdefy/node-utils';
|
||||
import { getSession } from 'next-auth/react';
|
||||
|
||||
import getServerSession from '../../../../lib/auth/getServerSession.js';
|
||||
|
||||
import connections from '../../../../build/plugins/connections.js';
|
||||
import operators from '../../../../build/plugins/operators/server.js';
|
||||
|
||||
@ -25,7 +27,7 @@ export default async function handler(req, res) {
|
||||
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,
|
||||
|
@ -15,12 +15,13 @@
|
||||
*/
|
||||
|
||||
import { createApiContext, getPageConfig, getRootConfig } from '@lowdefy/api';
|
||||
import { getSession } from 'next-auth/react';
|
||||
|
||||
import getServerSession from '../lib/auth/getServerSession.js';
|
||||
import Page from '../lib/Page.js';
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
const session = await getSession(context);
|
||||
const session = await getServerSession(context);
|
||||
|
||||
const apiContext = await createApiContext({
|
||||
buildDirectory: './build',
|
||||
logger: console,
|
||||
|
Loading…
x
Reference in New Issue
Block a user