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

Feat(tenant): Add unique admin route for each instances #1709

Merged
merged 5 commits into from
Sep 25, 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
13 changes: 13 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
"username": "user",
"password": "secret"
},
"rootAuth": {
"username": "root",
"password": "secret"
},
"enrichmentBatchSize": 10,
"routinesCache": false,
"routines": [
Expand Down Expand Up @@ -145,6 +149,15 @@
"position": "advanced",
"role": "admin"
},
{
"label": {
"en": "Instances settings",
"fr": "Gestion instances"
},
"icon": "faCogs",
"position": "advanced",
"role": "root"
},
{
"label": {
"en": "Sign in",
Expand Down
2 changes: 1 addition & 1 deletion cypress/support/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const goToAdminDashboard = () => {
cy.get('.advanced-page a')
.contains('Admin')
.click();
cy.location('pathname').should('equal', '/admin');
cy.location('pathname').should('equal', '/instance/default/admin');
};

export const goToHomePage = () => {
Expand Down
2 changes: 1 addition & 1 deletion globalConfig.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"mongoUri":"mongodb://127.0.0.1:43907/jest?","mongoDBName":"jest"}
{"mongoUri":"mongodb://127.0.0.1:36595/jest?","mongoDBName":"jest"}
1,108 changes: 554 additions & 554 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/api/controller/api/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const postLogin = date => ctx => {

const { username, password } = ctx.request.body;
const userAuth = get(ctx, 'ezMasterConfig.userAuth', {});
const rootAuth = get(ctx, 'ezMasterConfig.rootAuth', {});

let role;
if (
Expand All @@ -38,6 +39,14 @@ export const postLogin = date => ctx => {
role = 'user';
}

if (
rootAuth &&
username === rootAuth.username &&
password === rootAuth.password
) {
role = 'root';
}

if (!role) {
ctx.status = 401;
return;
Expand Down
8 changes: 7 additions & 1 deletion src/api/controller/api/publish.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { doPublish } from './publish';
import { PUBLISHER } from '../../workers/publisher';
import { workerQueues } from '../../workers';
jest.mock('../../workers');
jest.mock('../../workers', () => ({
workerQueues: {
lodex_test: {
add: jest.fn(),
},
},
}));

describe.skip('publish', () => {
describe('doPublish', () => {
Expand Down
6 changes: 6 additions & 0 deletions src/api/controller/api/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ app.use(
maxAge: config.cache.maxAge,
}),
);

app.use(async (ctx, next) => {
await next();
ctx.response.set('Vary', 'X-Lodex-Tenant');
});

app.use(route.get('/', getScripts));
app.use(route.get('/:scriptNameCalled', middlewareScript));
app.use(route.get('/:scriptNameCalled/*', middlewareScript));
Expand Down
36 changes: 23 additions & 13 deletions src/api/controller/front.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,6 @@ const indexHtml = fs
.toString()
.replace(REGEX_JS_HOST, jsHost);

const adminIndexHtml = fs
.readFileSync(path.resolve(__dirname, '../../app/admin.html'))
.toString()
.replace(
'</body>',
` <script>window.__DBNAME__ = ${JSON.stringify(
mongo.dbName,
)}</script><script src="{|__JS_HOST__|}/admin/index.js"></script>
</body>`,
)
.replace(REGEX_JS_HOST, jsHost);

const getDefaultInitialState = (token, cookie, locale) => ({
fields: {
loading: false,
Expand Down Expand Up @@ -265,6 +253,22 @@ const handleRender = async (ctx, next) => {
ctx.body = renderFullPage(html, css, preloadedState, helmet, ctx.tenant);
};

const renderAdminIndexHtml = ctx => {
ctx.body = fs
.readFileSync(path.resolve(__dirname, '../../app/admin.html'))
.toString()
.replace(
'</body>',
` <script>window.__DBNAME__ = ${JSON.stringify(
mongo.dbName,
)}</script><script>window.__TENANT__ = ${JSON.stringify(
ctx.tenant,
)}</script><script src="{|__JS_HOST__|}/admin/index.js"></script>
</body>`,
)
.replace(REGEX_JS_HOST, jsHost);
};

const app = new Koa();

if (config.userAuth) {
Expand Down Expand Up @@ -298,9 +302,15 @@ if (config.userAuth) {

app.use(handleRender);

app.use(
route.get('/instance/:slug/admin', async ctx => {
renderAdminIndexHtml(ctx);
}),
);

app.use(
route.get('/admin', async ctx => {
ctx.body = adminIndexHtml;
ctx.body = `<div>Super Root Admin</div>`;
}),
);

Expand Down
2 changes: 2 additions & 0 deletions src/api/e2e/publishedDataset.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
loadFixtures,
close,
} from '../../common/tests/fixtures';
import { closeAllWorkerQueues } from '../workers';

const adminHeader = {
cookie: `lodex_token=${jwt.sign(
Expand Down Expand Up @@ -390,6 +391,7 @@ describe('e2e publishedDataset Authentication', () => {
});

afterAll(async () => {
await closeAllWorkerQueues();
server.close();
await clear();
await close();
Expand Down
2 changes: 2 additions & 0 deletions src/api/e2e/ssr.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
loadFixtures,
close,
} from '../../common/tests/fixtures';
import { closeAllWorkerQueues } from '../workers';

const authentifiedHeader = {
cookie: `lodex_token=${jwt.sign(
Expand Down Expand Up @@ -253,6 +254,7 @@ describe('ssr', () => {
});

afterAll(async () => {
await closeAllWorkerQueues();
server.close();
await clear();
await close();
Expand Down
4 changes: 2 additions & 2 deletions src/api/workers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ export const cleanWaitingJobsOfType = (queueName, jobType) => {

export const closeAllWorkerQueues = async () => {
await Promise.all(
workerQueues.map(async workerQueue => {
await workerQueue.close();
Object.keys(workerQueues).map(queueName => {
workerQueues[queueName].close();
}),
);
};
1 change: 1 addition & 0 deletions src/app/custom/robots.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
User-agent: *
Disallow: /admin
Disallow: /instance/*/admin
Disallow: /login
Sitemap: /api/export/sitemap

7 changes: 1 addition & 6 deletions src/app/js/admin/Appbar/Menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,7 @@ const MenuComponent = ({
};

function setTenant(tenant) {
if (tenant === 'default') {
sessionStorage.removeItem('lodex-tenant');
} else {
sessionStorage.setItem('lodex-tenant', tenant);
}
window.location.reload();
window.location.href = `/instance/${tenant}/admin`;
}

const modelMenuItems = [
Expand Down
2 changes: 2 additions & 0 deletions src/app/js/admin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ if (process.env.NODE_ENV === 'e2e') {
sessionStorage.setItem('lodex-dbName', 'lodex_test');
} else {
const dbName = window.__DBNAME__;
const tenant = window.__TENANT__;
sessionStorage.setItem('lodex-dbName', dbName);
sessionStorage.setItem('lodex-tenant', tenant);
}

render(
Expand Down
9 changes: 6 additions & 3 deletions src/app/js/public/Property/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import memoize from 'lodash.memoize';
import get from 'lodash.get';
import translate from 'redux-polyglot/translate';

import { extractTenantFromUrl } from '../tenantTools';
import { fromDisplayConfig, fromResource } from '../selectors';
import ModerateButton from './ModerateButton';
import { changeFieldStatus } from '../resource';
Expand Down Expand Up @@ -98,14 +99,16 @@ const styles = {
};

export const getEditFieldRedirectUrl = (fieldName, scope, subresourceId) => {
const tenant = extractTenantFromUrl(window.location.href);

if (scope === SCOPE_DOCUMENT) {
if (subresourceId) {
return `/admin#/display/${SCOPE_DOCUMENT}/subresource/${subresourceId}/edit/${fieldName}`;
return `/instance/${tenant}/admin#/display/${SCOPE_DOCUMENT}/subresource/${subresourceId}/edit/${fieldName}`;
} else {
return `/admin#/display/${SCOPE_DOCUMENT}/main/edit/${fieldName}`;
return `/instance/${tenant}/admin#/display/${SCOPE_DOCUMENT}/main/edit/${fieldName}`;
}
} else {
return `/admin#/display/${scope}/edit/${fieldName}`;
return `/instance/${tenant}/admin#/display/${scope}/edit/${fieldName}`;
}
};

Expand Down
22 changes: 21 additions & 1 deletion src/app/js/public/menu/MenuItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import get from 'lodash.get';
import classnames from 'classnames';
import { Link, NavLink } from 'react-router-dom';

import { extractTenantFromUrl } from '../tenantTools';
import { polyglot as polyglotPropTypes } from '../../propTypes';
import stylesToClassname from '../../lib/stylesToClassName';
import customTheme from '../../../custom/customTheme';
Expand Down Expand Up @@ -193,7 +194,9 @@ const MenuItem = ({
return (
role === 'admin' && (
<a
href="/admin"
href={`/instance/${extractTenantFromUrl(
window.location.href,
)}/admin`}
className={classnames(
'nav-item',
styles.menuItem,
Expand All @@ -205,6 +208,23 @@ const MenuItem = ({
</a>
)
);
case 'root':
return (
role === 'root' && (
<a
href={`/admin`}
className={classnames(
'nav-item',
styles.menuItem,
styles.link,
)}
style={{ maxWidth: 'none' }} // TODO: Quick Fix, check why maxWidth is set to 90px
>
{icon}
{label}
</a>
)
);
case 'sign-in':
return (
role === 'not logged' && (
Expand Down
2 changes: 1 addition & 1 deletion src/app/js/public/menu/MenuItem.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ describe('MenuItem', () => {

const link = wrapper.find('a');

expect(link.prop('href')).toBe('/admin');
expect(link.prop('href')).toBe('/instance/default/admin');
});

it('should not render MenuItem when role is not admin', () => {
Expand Down
4 changes: 4 additions & 0 deletions src/app/js/public/tenantTools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function extractTenantFromUrl(url) {
const match = url.match(/\/instance\/([^/]+)/);
return match ? match[1] : 'default';
}
2 changes: 1 addition & 1 deletion src/app/js/user/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const loginSuccess = createAction(LOGIN_SUCCESS);
export const logout = createAction(LOGOUT);
export const signOut = createAction(SIGNOUT);

export const isAdmin = state => state.role === 'admin';
export const isAdmin = state => state.role === 'admin' || state.role === 'root';
export const getRole = state => state.role || 'not logged';
export const getToken = state => state.token;
export const getCookie = state => state.cookie;
Expand Down