-
+
+
+
diff --git a/nesis/frontend/client/src/pages/DocumentGPT/ChatPage.js b/nesis/frontend/client/src/pages/DocumentGPT/ChatPage.js
index ff4ce69..92b46c5 100644
--- a/nesis/frontend/client/src/pages/DocumentGPT/ChatPage.js
+++ b/nesis/frontend/client/src/pages/DocumentGPT/ChatPage.js
@@ -1,7 +1,6 @@
import React, { useState } from 'react';
import { useHistory, Route, Switch, useRouteMatch } from 'react-router-dom';
-import { GearFill } from 'react-bootstrap-icons';
-import Optim from '../../components/Menu';
+import Nesis from '../../components/Menu';
import styled from 'styled-components/macro';
import { FileEarmarkPost } from 'react-bootstrap-icons';
import {
@@ -140,7 +139,7 @@ const ChatPage = () => {
};
return (
-
+
Chat with
your Documents
@@ -220,7 +219,7 @@ const ChatPage = () => {
-
+
);
};
diff --git a/nesis/frontend/client/src/pages/Settings/SettingPage.js b/nesis/frontend/client/src/pages/Settings/SettingPage.js
index 176969f..bc81148 100644
--- a/nesis/frontend/client/src/pages/Settings/SettingPage.js
+++ b/nesis/frontend/client/src/pages/Settings/SettingPage.js
@@ -5,7 +5,7 @@ import { GearFill } from 'react-bootstrap-icons';
import DatasourcesPage from './Datasources/DatasourcesPage';
import UsersPage from './Users/UsersPage';
import RolesPage from './Roles/RolesPage';
-import Optim from '../../components/Menu';
+import Nesis from '../../components/Menu';
import styled from 'styled-components/macro';
const Heading = styled.h1`
@@ -23,7 +23,7 @@ const SettingsPage = () => {
const history = useHistory();
const match = useRouteMatch();
return (
-
+
Settings
@@ -68,7 +68,7 @@ const SettingsPage = () => {
-
+
);
};
diff --git a/nesis/frontend/client/src/pages/SignInPage.js b/nesis/frontend/client/src/pages/SignInPage.js
index c5ed91d..8643ba8 100644
--- a/nesis/frontend/client/src/pages/SignInPage.js
+++ b/nesis/frontend/client/src/pages/SignInPage.js
@@ -9,9 +9,14 @@ import FullPageFormContainer from '../components/layout/FullPageFormContainer';
import client from '../utils/httpClient';
import parseApiErrorMessage from '../utils/parseApiErrorMessage';
import SessionContext from '../SessionContext';
+import { useConfig } from '../ConfigContext';
import { useHistory } from 'react-router-dom';
import { setToken } from '../utils/tokenStorage';
import MessageRow from '../components/MessageRow';
+import { Col, Container, Row, Form } from 'react-bootstrap';
+import classes from '../styles/SignInPage.module.css';
+import AzureButton from '../components/AzureButton';
+import { Toggles } from 'react-bootstrap-icons';
const LogoContainer = styled.div`
margin-top: 32px;
@@ -84,8 +89,12 @@ const HTTP_STATUS_UNAUTHORIZED = 401;
const SignInPage = () => {
const [error, setError] = useState();
+ const [toggleCreds, setToggleCreds] = useState(false);
const { setSession } = useContext(SessionContext);
const history = useHistory();
+ const config = useConfig();
+ const azureAuthEnabled = config?.auth?.OAUTH_AZURE_ENABLED;
+ const oauthEnabled = azureAuthEnabled;
function submit(session, actions) {
client
@@ -124,42 +133,70 @@ const SignInPage = () => {
Nesis
Your Enterprise Knowledge Partner
{error}
-
- {({ isSubmitting, resetForm }) => (
-
-
-
-
-
-
-
-
-
- Log In
-
-
-
-
- )}
-
+
+
+
+
+ {azureAuthEnabled && !toggleCreds && (
+
+ )}
+
+
+
+ {(!oauthEnabled || toggleCreds) && (
+
+
+ {({ isSubmitting, resetForm }) => (
+
+
+
+
+
+
+
+
+
+ Log In
+
+
+
+
+ )}
+
+
+ )}
+ {oauthEnabled && (
+
+ setToggleCreds(!toggleCreds)}
+ >
+ Use {!toggleCreds ? 'password' : 'Azure'}
+
+
+ )}
diff --git a/nesis/frontend/client/src/styles/SignInPage.module.css b/nesis/frontend/client/src/styles/SignInPage.module.css
new file mode 100644
index 0000000..5827a8b
--- /dev/null
+++ b/nesis/frontend/client/src/styles/SignInPage.module.css
@@ -0,0 +1,32 @@
+.colsign {
+ margin: 0 auto;
+}
+
+@media only screen and (max-width: 450px) {
+ .w25 {
+ width: 160px !important;
+ }
+}
+
+@media only screen and (max-width: 992px) {
+ .formsize {
+ width: 100%;
+ padding: 30px !important;
+ }
+ .signinheading {
+ text-align: center;
+ }
+ .orloginbutton {
+ margin: 0 !important;
+ }
+}
+
+.orloginbutton {
+ border: 1px solid rgb(0, 18, 30);
+ padding: 15px 3px;
+ border-radius: 1px;
+ background-color: white;
+ color: black;
+ width: 100%;
+ font-size: 12px;
+}
diff --git a/nesis/frontend/package-lock.json b/nesis/frontend/package-lock.json
index ef89a69..876be85 100644
--- a/nesis/frontend/package-lock.json
+++ b/nesis/frontend/package-lock.json
@@ -9,6 +9,8 @@
"version": "0.0.1",
"license": "ISC",
"dependencies": {
+ "@azure/msal-browser": "^3.14.0",
+ "@azure/msal-react": "^2.0.16",
"app-root-path": "^3.1.0",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
@@ -39,6 +41,37 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@azure/msal-browser": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.14.0.tgz",
+ "integrity": "sha512-Un85LhOoecJ3HDTS3Uv3UWnXC9/43ZSO+Kc+anSqpZvcEt58SiO/3DuVCAe1A3I5UIBYJNMgTmZPGXQ0MVYrwA==",
+ "dependencies": {
+ "@azure/msal-common": "14.10.0"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@azure/msal-common": {
+ "version": "14.10.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.10.0.tgz",
+ "integrity": "sha512-Zk6DPDz7e1wPgLoLgAp0349Yay9RvcjPM5We/ehuenDNsz/t9QEFI7tRoHpp/e47I4p20XE3FiDlhKwAo3utDA==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@azure/msal-react": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/@azure/msal-react/-/msal-react-2.0.16.tgz",
+ "integrity": "sha512-fToFi/wG5e81Dir7Lw3/a2rZRRxvyD89ufI/GeVxcK3rblzJ6BT7fUoYnQsYTB6VR+z3MzRHpbJ3XgfESRk5ng==",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@azure/msal-browser": "^3.14.0",
+ "react": "^16.8.0 || ^17 || ^18"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
@@ -2098,8 +2131,7 @@
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"node_modules/js-yaml": {
"version": "3.14.1",
@@ -2336,6 +2368,18 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "peer": true,
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
"node_modules/loupe": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
@@ -3255,6 +3299,18 @@
"node": ">= 0.8"
}
},
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@@ -4077,6 +4133,25 @@
"@jridgewell/trace-mapping": "^0.3.9"
}
},
+ "@azure/msal-browser": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.14.0.tgz",
+ "integrity": "sha512-Un85LhOoecJ3HDTS3Uv3UWnXC9/43ZSO+Kc+anSqpZvcEt58SiO/3DuVCAe1A3I5UIBYJNMgTmZPGXQ0MVYrwA==",
+ "requires": {
+ "@azure/msal-common": "14.10.0"
+ }
+ },
+ "@azure/msal-common": {
+ "version": "14.10.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.10.0.tgz",
+ "integrity": "sha512-Zk6DPDz7e1wPgLoLgAp0349Yay9RvcjPM5We/ehuenDNsz/t9QEFI7tRoHpp/e47I4p20XE3FiDlhKwAo3utDA=="
+ },
+ "@azure/msal-react": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/@azure/msal-react/-/msal-react-2.0.16.tgz",
+ "integrity": "sha512-fToFi/wG5e81Dir7Lw3/a2rZRRxvyD89ufI/GeVxcK3rblzJ6BT7fUoYnQsYTB6VR+z3MzRHpbJ3XgfESRk5ng==",
+ "requires": {}
+ },
"@babel/code-frame": {
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
@@ -5640,8 +5715,7 @@
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"js-yaml": {
"version": "3.14.1",
@@ -5841,6 +5915,15 @@
}
}
},
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "peer": true,
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
"loupe": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
@@ -6544,6 +6627,15 @@
"unpipe": "1.0.0"
}
},
+ "react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "peer": true,
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
"readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
diff --git a/nesis/frontend/package.json b/nesis/frontend/package.json
index fb2b4d3..708c544 100644
--- a/nesis/frontend/package.json
+++ b/nesis/frontend/package.json
@@ -25,6 +25,8 @@
"url": "https://github.com/ametnes/nesis/issues"
},
"dependencies": {
+ "@azure/msal-browser": "^3.14.0",
+ "@azure/msal-react": "^2.0.16",
"app-root-path": "^3.1.0",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
diff --git a/nesis/frontend/server/api/config.js b/nesis/frontend/server/api/config.js
new file mode 100644
index 0000000..2a2e3e9
--- /dev/null
+++ b/nesis/frontend/server/api/config.js
@@ -0,0 +1,20 @@
+const getConfig = (requests, profile) => (request, response) => {
+ const config = {
+ version: 'v1',
+ auth: {
+ OAUTH_AZURE_ENABLED: profile.NESIS_OAUTH_AZURE_ENABLED,
+ OAUTH_AZURE_CLIENT_ID: profile.NESIS_OAUTH_AZURE_CLIENT_ID,
+ OAUTH_AZURE_AUTHORITY: profile.NESIS_OAUTH_AZURE_AUTHORITY,
+ OAUTH_AZURE_REDIRECTURI: profile.NESIS_OAUTH_AZURE_REDIRECTURI,
+ OAUTH_AZURE_CACHELOCATION: profile.NESIS_OAUTH_AZURE_CACHELOCATION,
+ OAUTH_AZURE_STOREAUTHSTATEINCOOKIE:
+ profile.NESIS_OAUTH_AZURE_STOREAUTHSTATEINCOOKIE,
+ OAUTH_AZURE_SCOPES: profile.NESIS_OAUTH_AZURE_SCOPES || ['User.Read'],
+ },
+ };
+ response.status(200).send(JSON.stringify(config));
+};
+
+module.exports = {
+ get: getConfig,
+};
diff --git a/nesis/frontend/server/api/datasources.spec.js b/nesis/frontend/server/api/datasources.spec.js
index 9ef5a49..baef92b 100644
--- a/nesis/frontend/server/api/datasources.spec.js
+++ b/nesis/frontend/server/api/datasources.spec.js
@@ -1,5 +1,5 @@
const api = require('./datasources');
-const config = require('../config');
+const config = require('../profile');
const sinon = require('sinon');
const { Request } = require('../util/test-util');
diff --git a/nesis/frontend/server/api/index.js b/nesis/frontend/server/api/index.js
index e69eb63..de48da4 100644
--- a/nesis/frontend/server/api/index.js
+++ b/nesis/frontend/server/api/index.js
@@ -5,3 +5,4 @@ module.exports.settings = require('./settings');
module.exports.roles = require('./roles');
module.exports.users = require('./users');
module.exports.tasks = require('./tasks');
+module.exports.config = require('./config');
diff --git a/nesis/frontend/server/api/sessions.js b/nesis/frontend/server/api/sessions.js
index 9667c49..b437b01 100644
--- a/nesis/frontend/server/api/sessions.js
+++ b/nesis/frontend/server/api/sessions.js
@@ -3,25 +3,39 @@ const logger = require('../util/logger');
const post = (requests, profile) => async (request, response) => {
const url = profile.SERVICE_ENDPOINT;
const session = request.body;
+ const oauth_token_key = profile.NESIS_OAUTH_TOKEN_KEY;
- if (!session) {
+ // session cannot contain the oauth token key
+ if (!session || oauth_token_key in session) {
return response.status(400).send({
message: 'Invalid request. session not supplied',
});
}
- logger.info(`Posting to ${url}/sessions`);
- requests
- .post(`${url}/sessions`)
- .set('Accept', 'application/json')
- .set('Content-Type', 'application/json')
- .send(session)
+ let oauthProvider = null;
+
+ if (session.azure) {
+ oauthProvider = authenticateWithAzure(requests, profile, session.azure);
+ } else {
+ oauthProvider = requests
+ .post(`${url}/sessions`)
+ .set('Accept', 'application/json')
+ .set('Content-Type', 'application/json')
+ .send({ ...session });
+ }
+
+ oauthProvider
.then((res) => {
response.status(res.status).send(res.body);
})
.catch((err) => {
- logger.error(`Fail posting to ${url}: ${err}, status: ${err.status}`);
- response.status(err.status).send(err.response.body);
+ if (err && err.response && err.response.body) {
+ response.status(err.status).send(err.response.body);
+ } else if (err) {
+ response.status(err.status || 400).send('Error processing request');
+ } else {
+ response.status(500).send('Error processing request');
+ }
});
};
@@ -39,13 +53,65 @@ const _delete = (requests, url) => (request, response) => {
})
.catch((err) => {
logger.error(
- `Fail posting to ${url}: ${JSON.stringify(
- err.response.body,
- )} with status ${err.status}`,
+ `Fail posting to ${url}: ${JSON.stringify(err)} with status ${
+ err.status
+ }`,
);
response.status(err.status).send(err.response.body);
});
};
+function authenticateWithAzure(requests, profile, azure) {
+ const email = azure.account.username;
+ const name = azure.account.name;
+
+ const graphUrl = 'https://graph.microsoft.com/v1.0/me';
+
+ return requests
+ .get(graphUrl)
+ .set('Authorization', `Bearer ${azure.accessToken}`)
+ .set('Content-Type', 'application/json')
+ .send()
+ .then((res) => {
+ if (res.body.mail !== email) {
+ const messsage = 'Invalid azure access token';
+ const error = new Error(messsage);
+ Object.assign(error, {
+ status: 401,
+ response: {
+ body: 'Invalid azure access token',
+ },
+ });
+ throw error;
+ }
+ })
+ .then(() => sendOauthSession(requests, name, email, profile));
+}
+
+function sendOauthSession(requests, name, email, profile) {
+ const url = profile.SERVICE_ENDPOINT;
+ const oauth_token_key = profile.NESIS_OAUTH_TOKEN_KEY;
+ const oauth_token_value = profile.NESIS_OAUTH_TOKEN_VALUE;
+ const payload = {
+ email: email,
+ name: name,
+ [oauth_token_key]: oauth_token_value,
+ };
+
+ return requests
+ .post(`${url}/sessions`)
+ .set('Accept', 'application/json')
+ .set('Content-Type', 'application/json')
+ .send(payload)
+ .then((res) => ({
+ status: res.status,
+ body: {
+ ...res.body,
+ email,
+ name,
+ },
+ }));
+}
+
module.exports.post = post;
module.exports.delete = _delete;
diff --git a/nesis/frontend/server/api/sessions.spec.js b/nesis/frontend/server/api/sessions.spec.js
index f2109f6..80df11d 100644
--- a/nesis/frontend/server/api/sessions.spec.js
+++ b/nesis/frontend/server/api/sessions.spec.js
@@ -1,6 +1,7 @@
const api = require('./sessions');
-const config = require('../config');
+const config = require('../profile');
const sinon = require('sinon');
+const assert = require('chai').assert;
const { Request } = require('../util/test-util');
describe('Sessions', () => {
@@ -32,4 +33,88 @@ describe('Sessions', () => {
);
sinon.assert.match('POST', requests.method);
});
+
+ it('can not be created with token key in payload', () => {
+ const requests = new Request();
+ const request = {
+ headers: {},
+ body: {
+ email: 'email@domain.com',
+ [config.profile.DEV.NESIS_OAUTH_TOKEN_KEY]:
+ 'some.one.knows.something.about.our.internals',
+ },
+ };
+
+ const responseStab = sinon.stub();
+ const statusStab = sinon.stub().returns({ send: responseStab });
+ const response = {
+ status: statusStab,
+ };
+
+ const post = api.post(requests, config.profile.DEV);
+ post(request, response);
+ sinon.assert.calledWith(statusStab, 400);
+ sinon.assert.called(responseStab);
+ });
+
+ it('can not be created with no payload', () => {
+ const requests = new Request();
+ const request = {
+ headers: {},
+ body: null,
+ };
+
+ const responseStab = sinon.stub();
+ const statusStab = sinon.stub().returns({ send: responseStab });
+ const response = {
+ status: statusStab,
+ };
+
+ const post = api.post(requests, config.profile.DEV);
+ post(request, response);
+ sinon.assert.calledWith(statusStab, 400);
+ sinon.assert.called(responseStab);
+ });
+
+ it('can be created with Azure', () => {
+ const requests = new Request();
+ requests.azureUserData = {
+ displayName: 'Michy Tan',
+ mail: 'michy.tan@acme.onmicrosoft.com',
+ userPrincipalName: 'michy.tan@acme.onmicrosoft.com',
+ };
+ const request = {
+ headers: {},
+ body: {
+ email: 'michy.tan@acme.onmicrosoft.com',
+ azure: {
+ authority: 'https://login.microsoftonline.com/common/',
+ uniqueId: '9cdd0b94-0000-48db-8bc8-00000000',
+ tenantId: '041e34c2-0000-44b0-8aa4-00000000',
+ accessToken: 'some.key',
+ account: {
+ username: 'michy.tan@acme.onmicrosoft.com',
+ name: 'First Last',
+ },
+ },
+ },
+ };
+
+ const responseStab = sinon.stub();
+ const statusStab = sinon.stub().returns({ send: responseStab });
+ const response = {
+ status: statusStab,
+ };
+
+ const post = api.post(requests, config.profile.DEV);
+ post(request, response);
+ sinon.assert.calledWith(statusStab, 200);
+ sinon.assert.called(responseStab);
+
+ assert.deepEqual(requests.data, {
+ email: 'michy.tan@acme.onmicrosoft.com',
+ name: 'First Last',
+ ___nesis_oauth_token_key___: '___nesis_oauth_token_value___',
+ });
+ });
});
diff --git a/nesis/frontend/server/api/tasks.spec.js b/nesis/frontend/server/api/tasks.spec.js
index 6771aae..d846e7f 100644
--- a/nesis/frontend/server/api/tasks.spec.js
+++ b/nesis/frontend/server/api/tasks.spec.js
@@ -1,5 +1,5 @@
const api = require('./tasks');
-const config = require('../config');
+const config = require('../profile');
const sinon = require('sinon');
const { Request } = require('../util/test-util');
diff --git a/nesis/frontend/server/config.js b/nesis/frontend/server/config.js
deleted file mode 100644
index 77520ee..0000000
--- a/nesis/frontend/server/config.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const profile = {
- PROD: {
- SERVICE_ENDPOINT: `${process.env.API_URL}/v1`,
- },
- TEST: {
- SERVICE_ENDPOINT: `${process.env.API_URL}/v1`,
- },
- DEV: {
- SERVICE_ENDPOINT: `http://localhost:6000/v1`,
- },
-};
-
-module.exports.profile = profile;
diff --git a/nesis/frontend/server/main.js b/nesis/frontend/server/main.js
index 6cd172c..ccbfb43 100644
--- a/nesis/frontend/server/main.js
+++ b/nesis/frontend/server/main.js
@@ -7,7 +7,7 @@ const logger = require('./util/logger');
const api = require('./api/index');
const app = express();
-const config = require('./config');
+const config = require('./profile');
const profile = config.profile[process.env.PROFILE] || config.profile.DEV;
//Handles post requests
const bodyParser = require('body-parser');
@@ -29,7 +29,7 @@ async function init() {
USERS: '/api/users',
TASKS: '/api/tasks',
DATA_SOURCES: '/api/datasources',
- DATA_SOURCES_MODELS: '/api/models',
+ CONFIG: '/api/config',
QANDA_PREDICTIONS: '/api/qanda/predictions',
};
@@ -90,6 +90,7 @@ async function init() {
`${API.QANDA_PREDICTIONS}/:id`,
api.qanda_predictions.getById(requests, profile),
);
+ app.get(`${API.CONFIG}`, api.config.get(requests, profile));
app.get('/*', (req, res) => {
res.sendFile(path.join(home, 'index.html'));
diff --git a/nesis/frontend/server/profile.js b/nesis/frontend/server/profile.js
new file mode 100644
index 0000000..7d267be
--- /dev/null
+++ b/nesis/frontend/server/profile.js
@@ -0,0 +1,38 @@
+const profile = {
+ PROD: {
+ SERVICE_ENDPOINT: `${process.env.API_URL}/v1`,
+ NESIS_OAUTH_TOKEN_KEY: process.env.NESIS_OAUTH_TOKEN_KEY,
+ NESIS_OAUTH_TOKEN_VALUE: process.env.NESIS_OAUTH_TOKEN_VALUE,
+ NESIS_OAUTH_AZURE_ENABLED: process.env.NESIS_OAUTH_AZURE_ENABLED,
+ NESIS_OAUTH_AZURE_CLIENT_ID: process.env.NESIS_OAUTH_AZURE_CLIENT_ID,
+ NESIS_OAUTH_AZURE_TENANT_ID: process.env.NESIS_OAUTH_AZURE_TENANT_ID,
+ NESIS_OAUTH_AZURE_AUTHORITY: 'https://login.microsoftonline.com/common/',
+ NESIS_OAUTH_AZURE_REDIRECTURI: process.env.NESIS_OAUTH_AZURE_REDIRECTURI,
+ NESIS_OAUTH_AZURE_CACHELOCATION:
+ process.env.NESIS_OAUTH_AZURE_CACHELOCATION || 'sessionStorage',
+ NESIS_OAUTH_AZURE_STOREAUTHSTATEINCOOKIE:
+ process.env.NESIS_OAUTH_AZURE_STOREAUTHSTATEINCOOKIE || false,
+ NESIS_OAUTH_AZURE_SCOPES: process.env.NESIS_OAUTH_AZURE_SCOPES || [
+ 'User.Read',
+ ],
+ },
+ DEV: {
+ SERVICE_ENDPOINT: `http://localhost:6000/v1`,
+ NESIS_OAUTH_TOKEN_KEY: '___nesis_oauth_token_key___',
+ NESIS_OAUTH_TOKEN_VALUE: '___nesis_oauth_token_value___',
+ NESIS_OAUTH_AZURE_ENABLED: true,
+ NESIS_OAUTH_AZURE_CLIENT_ID: process.env.NESIS_OAUTH_AZURE_CLIENT_ID,
+ NESIS_OAUTH_AZURE_TENANT_ID: process.env.NESIS_OAUTH_AZURE_TENANT_ID,
+ NESIS_OAUTH_AZURE_AUTHORITY: 'https://login.microsoftonline.com/common/',
+ NESIS_OAUTH_AZURE_REDIRECTURI: 'http://localhost:3000/',
+ NESIS_OAUTH_AZURE_CACHELOCATION:
+ process.env.NESIS_OAUTH_AZURE_CACHELOCATION || 'localStorage',
+ NESIS_OAUTH_AZURE_STOREAUTHSTATEINCOOKIE:
+ process.env.NESIS_OAUTH_AZURE_STOREAUTHSTATEINCOOKIE || false,
+ NESIS_OAUTH_AZURE_SCOPES: process.env.NESIS_OAUTH_AZURE_SCOPES || [
+ 'User.Read',
+ ],
+ },
+};
+
+module.exports.profile = profile;
diff --git a/nesis/frontend/server/util/test-util.js b/nesis/frontend/server/util/test-util.js
index 571f934..8c45eeb 100644
--- a/nesis/frontend/server/util/test-util.js
+++ b/nesis/frontend/server/util/test-util.js
@@ -20,6 +20,7 @@ class Request {
this.tasks = [];
this.taskById = {};
this.targets = {};
+ this.azureUserData = {};
}
set(header, value) {
this.headers[header] = value;
@@ -114,6 +115,8 @@ class Request {
res = { body: this.tasks, status: 200 };
} else if (this.url.includes('/tasks/')) {
res = { body: this.taskById, status: 200 };
+ } else if (this.url.endsWith('/v1.0/me')) {
+ res = { body: this.azureUserData, status: 200 };
}
} else if (this.method === 'DELETE') {
res = { body: 'Deleted', status: 200 };