Feature(s) impacted
The Forest Admin agent authentication process and its integration with MongoDB using @forestadmin/datasource-mongoose
.
Observed behavior
The Forest Admin panel displays the message:
“Unlocking your data. We are validating your identity.”
The loading modal spins indefinitely, and the authentication process does not complete.
ps : nodejs receives the post request with renderingId
The Node.js application logs the following messages during startup:
Your application is listening on port 3310.
Connected to MongoDB successfully.
Registered models: [ ‘users’ ]
Applying users collection customizations
Customizing users collection
Adding Smart Action to users collection
Adding Smart Segment to users collection
info: Successfully mounted on Express.js
warning: Using unspecified flattenMode. Please refer to the documentation to update your code:
Forest Admin panel is ready.
info: Schema was not updated since last run (hash: 090377f3dcc077f5326d0c2256c73b223414fb64)
POST /forest/authentication - - - - ms
Context
- Project name:
dibsy-forest
- Team name:
dibsy
- Environment name: Development
- Agent technology: Node.js
- Agent (Forest package) name & version:
@forestadmin/agent
:^1.57.1
@forestadmin/datasource-mongoose
:^1.8.9
- Database type: MongoDB
- Recent changes made on your end:
- Migrated from
forest-express-mongoose
to the new@forestadmin/agent
architecture. - Updated the
forestadmin.js
andapp.js
:const chalk = require('chalk');
- Migrated from
const { createAgent } = require(‘@forestadmin/agent’);
const { createMongooseDataSource } = require(‘@forestadmin/datasource-mongoose’);
const mongoose = require(‘mongoose’);
const configureUsersCollection = require(‘…/forest/users’);
const usersModel = require(‘…/models/users’);
module.exports = async function forestadmin(app) {
try {
// Connect to MongoDB
const connection = await mongoose.connect(process.env.DATABASE_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log(chalk.green('Connected to MongoDB successfully.'));
usersModel(mongoose); // Register the users model
console.log('Registered models:', mongoose.modelNames());
// Initialize Forest Admin agent
const agent = createAgent({
authSecret: process.env.FOREST_AUTH_SECRET,
envSecret: process.env.FOREST_ENV_SECRET,
isProduction: process.env.NODE_ENV === 'production',
});
// Add Mongoose data source with flattenMode configuration
agent.addDataSource(
createMongooseDataSource(connection)
);
console.log('Applying users collection customizations'); // Debug log
configureUsersCollection(agent);
// Mount Forest Admin routes
await agent.mountOnExpress(app);
// Start the agent.
agent.start().catch(error => {
console.error('\x1b[31merror:\x1b[0m Forest Admin agent failed to start\n');
console.error('');
console.error(error.stack);
process.exit(1);
});
console.log(chalk.cyan('Forest Admin panel is ready.'));
} catch (error) {
console.error(chalk.red(‘Failed to initialize Forest Admin:’), error);
process.exit(1);
}
};
app.js :
require(‘dotenv’).config();
const express = require(‘express’);
const path = require(‘path’);
const cookieParser = require(‘cookie-parser’);
const bodyParser = require(‘body-parser’);
const cors = require(‘cors’);
const morgan = require(‘morgan’);
const forestadmin = require(‘./middlewares/forestadmin’);
const app = express();
let allowedOrigins = [/.forestadmin.com$/, /localhost:\d{4}$/];
if (process.env.CORS_ORIGINS) {
allowedOrigins = allowedOrigins.concat(process.env.CORS_ORIGINS.split(‘,’));
}
const corsConfig = {
origin: allowedOrigins,
maxAge: 86400,
credentials: true,
};
// Middleware setup
app.use(morgan(‘tiny’));
// Set CORS for authentication routes
app.use(
‘/forest/authentication’,
cors({
…corsConfig,
origin: corsConfig.origin.concat(‘null’),
})
);
app.use(cors(corsConfig));
// Body parsers and cookie parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// Initialize Forest Admin
(async () => {
try {
await forestadmin(app);
} catch (error) {
console.error(‘Failed to setup Forest Admin:’, error);
process.exit(1);
}
})();
// Protect /forest
routes
app.use(‘/forest’, (req, res, next) => {
const PUBLIC_ROUTES = [‘/authentication’];
if (PUBLIC_ROUTES.some((route) => req.url.startsWith(route))) {
return next();
}
if (!req.user) {
return res.status(401).send(‘Unauthorized’);
}
next();
});
// Static files
app.use(express.static(path.join(__dirname, ‘public’)));
module.exports = app;
```
- Customized the
users
collection with smart actions, smart fields, and smart segments.