forestadmin / forest-express Goto Github PK
View Code? Open in Web Editor NEW𧱠Dependency of Express Lianas for Forest Admin
License: GNU General Public License v3.0
𧱠Dependency of Express Lianas for Forest Admin
License: GNU General Public License v3.0
In forest-express v2.0.2, the dependency [email protected]
contains a low-severity vulnerability according to NSP: https://nodesecurity.io/advisories/532
With a field like this in my model
status: {
name: {
type: String,
enum: ['EVENT.ONE', 'EVENT.TWO', 'EVENT.THREE'],
},
event_id: String,
description: String,
updated_at: Date,
},
i expect to be able to filter by status.name
Only event_id
, description
and updated_at
subfields are available in the Forest UI. status
is not.
No logs
TODO: Please provide any relevant information about your setup.
Liana doesn't override the cors preferences set by previous middlewares.
It could just append hosts to the existing origins.
It could also respect the predefined maxAge value.
It overrides origin and maxAge, making it very difficult to handle custom cors
configurations.
It's also very hard to track who modifies those headers.
TODO: Please include any relevant log snippets, if necessary.
TODO: Please provide any relevant information about your setup.
βββ¬ [email protected]
β βββ¬ [email protected]
When specifying the name of a field on the "collection" configurator (usually used for Smart Fields) with the "isSortable" property - it would use that value and not the default "false".
The field is duplicated in the schema.json file and as a result in the UI as well (well, it basically generates a smart field with the same name as the native field)
We are using mongoose - but this seems to be relevant to any Liana implementations.
At the core of the issue, the need to set field properties for fields which are derived from the ORM schema. Some properties like "isRrequired" can be inferred from the DB schema definition, others like "isSortable" are not.
Still, for performance reasons we would like to limit which fields are available for sorting by.
Ideally, if we use the forest-express
modules collection
export - the one that is used for smart fields and smart collections etc., we could just specify the name of a db derived field with the isSortable
value set to false
which would override the default true
.
This is not working since:
here the collection configurator concats field defs instead of possibly merging them.
The formatter for the field options here does his job by parsing the value correctly.
Of course, conflicts nay arise, so I would gate those "extensions" to native fields with only valid settable attributes and a clear override priority.
The existing field duplication behaviour to me seems like a bug - either throw on such cases blocking this option or properly implement a merge.
Hope this helps!
When editing the content of a record in a "related data" set that triggers a custom action, I would expect the custom response from that action to be rendered as a message in the same manner as is specified at https://doc.forestadmin.com/developer-guide/express-mongoose.html#customizing-response.
The custom message works for POST
requests with the same set of related data, but not for PUT
requests. When sending a PUT
request from a related data edit form, it has the following behavior:
400
response, the UI "blinks" and shows no message.200
response, the UI displays a brief generic "success" message, and then returns to the related data list page.Here's an example valid update PUT
request and the custom response
Request URL: http://localhost:5000/forest/Survey/5ada0e46c38fd399899c9dfa/relationships/questionList/18
Request Method: PUT
Status Code: 200 OK
Remote Address: [::1]:5000
Referrer Policy: no-referrer-when-downgrade
RESPONSE HEADERS
Access-Control-Allow-Origin: http://app.forestadmin.com
Connection: keep-alive
Content-Length: 42
Content-Type: application/vnd.api+json; charset=utf-8
Date: Fri, 27 Apr 2018 15:18:09 GMT
ETag: W/"2a-Aqil8IhIAZRpmsttb3yXbM5+PxI"
Vary: Origin
X-Powered-By: Express
REQUEST HEADERS
Accept: application/json, text/javascript, */*; q=0.01
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Authorization: Bearer [hidden]
Connection: keep-alive
Content-Length: 114
Content-Type: application/json; charset=UTF-8
Host: localhost:5000
Origin: http://app.forestadmin.com
Referer: http://app.forestadmin.com/23689/data/857897/index/record/857897/5ada0e46c38fd399899c9dfa/has-many-embedded/13974064/edit/18
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
REQUEST PAYLOAD
{"data":{"attributes":{"question_id":"5ad7d3c623a9b5d7aec16c30","questionName":"VideoFeedback","sortOrder":"22"}}}
RESPONSE
{"success":"Survey question list updated"}
Instead of displaying the message "Survey question list updated", the message displayed is:
Which is just the default message for this related data type.
When sending a failed request such as the following...
Request URL: http://localhost:5000/forest/Survey/5ada0e46c38fd399899c9dfa/relationships/questionList/18
Request Method: PUT
Status Code: 400 Bad Request
Remote Address: [::1]:5000
Referrer Policy: no-referrer-when-downgrade
RESPONSE
{"error":"Survey validation failed: questions.18.sortOrder: Path `sortOrder` (-22) is less than minimum allowed value (0)."}
...no message at all is shown. The UI flickers and stays on the same view.
Using Mongo 3.6 with forest-express-mongoose
package.
I've defined a get route for a smart collection as mentioned in the documentation but I keep getting a 404 error. Any suggestions?
Thanks.
I would like to build my forest admin project with esbuild into a single js file. That's almost working perfectly.
However, I have defined actions in some collections. I would like to import statically these collections otherwise esbuild won't bundle them.
Currently, the only way to import collections is by providing a configDir
in LianaOptions
. This will load dynamically (through a call to requireAll()
) all the files in the provided directory.
N/A
I'm using [email protected]
which requires [email protected]
.
Here is my attempt:
const lianaOptions: LianaOptions = {
authSecret: readFromEnv('FOREST_AUTH_SECRET'),
// configDir will load dynamically js files. It is replaced by the explicit import of ../forest
configDir: `pathWhichMustNotExist${Math.random()}`,
connections,
envSecret: readFromEnv('FOREST_ENV_SECRET'),
objectMapping,
schemaDir: join(__dirname, '../..'),
};
require('../forest');
app.use(await init(lianaOptions));
require('../forest')
imports a call to the function collection()
like this:
collection('contracts', {
actions: [
// ...
],
It does not work because Schemas.schemas
was not yet initialized and the collection is not loaded (see https://github.com/ForestAdmin/forest-express/blob/main/src/index.js#L402).
If I require the collection after the initialization, the schema .forestadmin-schema.json
has been written and does not include the actions.
If we could have a (asynchronous) function to load the collections in addition to the configDir
that would solve my problem.
Maybe something like:
if (configStore.doesConfigDirExist()) {
loadCollections(configStore.configDir);
}
if (typeof configStore.loadCollections === 'function') {
await configStore.loadCollections();
}
I would appreciate your help or feedbacks. If you like the idea, I can create a PR.
So far I had been using a maximum of 1 async setter per collection in my code. Last week I created many smart fields with async setters to implement a gallery admin. And things went awry!
The best way to illustrate all the bugs I encountered is to comment the snippet implementing setters in collections (///
comments are mine):
return P
/// Looping on `smartFields` which is an array of all virtual fields with setters.
/// Let's keep that in mindβ¦
.each(smartFields, function (field) {
// WARNING: The Smart Fields setters may override other changes.
/// The `attributes` object is passed by reference, so it's already possible to modify it.
/// Why is it mandatory to return it from every setter then?
/// Is the following condition supposed to test if the setter is async?
/// This actually tests if the setter is itself a promise, which is probably never true.
/// I believe this whole block is useless, async results are already dealt with by `P.each(β¦`
if (_.isFunction(field.set.then)) {
return field.set(attributes, attributes[field.field])
.then(function (newAttributes) {
attributes = newAttributes;
return attributes;
});
} else {
/// So each setter is called with `attributes`, no matter if the value of that field has
/// actually been updated or notβ¦
/// Bug 1: most of the time my fields ended up having their value reset to `undefined`
/// because of the way this code is written.
attributes = field.set(attributes, attributes[field.field]);
/// Bug 2: since the above `if` doesn't actually deal with promise results,
/// having 1 async setter breaks all other setters, which are called with that promise :-(
return attributes;
}
})
I have fixed all my problems at once by replacing the above snippet with the following one:
return P
.each(smartFields, function (field) {
if ( field.field in attributes ) {
return field.set(attributes, attributes[field.field]);
}
})
I would really like to get this code change merged into the official forest-express, but first I wanted to make sure I understood why the current code was written that way.
It looks like this line is writing over what I might had described earlier when I used Liana.collection():
https://github.com/ForestAdmin/forest-express/blob/devel/generators/schemas.js#L18
I remember that Liana.collection used to work, but now it doesn't. I'm not sure if reconciliation was happening somewhere else, because this file has not been changed in some time.
Any help is appreciated!
Hi,
We are currently unable to use async/await notation with sequelize/express. It is misleading and time consuming to investigate on such issues. We would like to be able to write models not syntactically analyzed by sequelize/express on pure node javascript.
> node -v; node ./bin/www
v8.4.0
Listening on port 3000
Open your admin UI: http://app.forestadmin.com
[forest] π³π³π³ Forest customization failed due to a syntax error: Unexpected token function in /home/lpayet/WebstormProjects/admin/forest/premium_subscription.js:16
[forest] π³π³π³ An error occured while computing the Forest apimap. Your application apimap cannot be sent to Forest. Your Admin UI might not reflect your application models.
Error
at /home/lpayet/WebstormProjects/admin/node_modules/forest-express/index.js:156:23
at tryCatcher (/home/lpayet/WebstormProjects/admin/node_modules/forest-express/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/lpayet/WebstormProjects/admin/node_modules/forest-express/node_modules/bluebird/js/release/promise.js:503:31)
at Promise._settlePromise (/home/lpayet/WebstormProjects/admin/node_modules/forest-express/node_modules/bluebird/js/release/promise.js:560:18)
at Promise._settlePromiseCtx (/home/lpayet/WebstormProjects/admin/node_modules/forest-express/node_modules/bluebird/js/release/promise.js:597:10)
at Async._drainQueue (/home/lpayet/WebstormProjects/admin/node_modules/forest-express/node_modules/bluebird/js/release/async.js:131:12)
at Async._drainQueues (/home/lpayet/WebstormProjects/admin/node_modules/forest-express/node_modules/bluebird/js/release/async.js:136:10)
at Immediate.Async.drainQueues (/home/lpayet/WebstormProjects/admin/node_modules/forest-express/node_modules/bluebird/js/release/async.js:16:14)
at runCallback (timers.js:781:20)
at tryOnImmediate (timers.js:743:5)
at processImmediate [as _immediateCallback] (timers.js:714:5)
Sorry for the quality of the issue.
My .forestadmin-schema.json was in my server directory.
When i run my code in dev, I sometime,
cd server; node index.js
But in production I run
node server/index.js
I think, it's an issue. You should create the file, relatively from the index.js and not from where you run the command line. Imagine I run the server with a super long absolute path.
arnaud:f-forest: il y a 5 minutes
The file is created in the project repository (nowhere else). But, indeed the code does not work properly if you run your server without being in the server repository.
Could create an issue in the forest-express repository (https://github.com/ForestAdmin/forest-express/issues)?
The issue looks to be here:
https://github.com/ForestAdmin/forest-express/blob/devel/src/index.js#L31
As of January 2017 intercom requires that access tokens be used rather than apiKeys (https://developers.intercom.com/reference).
As a new user of intercom (post January) I do not have the ability to generate an apiKey and therefore cannot use this integration.
forest-express/src/services/path.js
Line 12 in feb5ecc
It would be great if we can use an external endpoint for smart actions. It is especially useful in a serverless architecture. Currently we need to write an indirection in the routes folder to forward the request.
could you upgrade express-cors to the newest version?
because I obtain
express deprecated res.send(status): Use res.sendStatus(status) instead node_modules/express-cors/index.js:95:45
Init should return a promise or accept a callback, so we know when the returned app is ready to service requests.
Init returns an app, which is not ready to service requests. Init has a fairly complex promise chain, which is not resolved until after the app is returned.
Serverless: ANY /forest/User (Ξ»: forest)
Serverless: The first request might take a few extra seconds
Serverless: [404] {"statusCode":404,"body":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot GET /forest/User</pre>\n</body>\n</html>\n","headers":{"x-powered-by":"Express","vary":"Origin","content-security-policy":"default-src 'self'","x-content-type-options":"nosniff","content-type":"text/html; charset=utf-8","content-length":"150","date":"Tue, 05 Jun 2018 20:57:14 GMT","connection":"close"},"isBase64Encoded":false}
Our app is built on AWS Lambda. To support Forest, we created a Lambda that wraps the forest-express-sequelize example.
Unlike a traditional Express app, the Express app in the Lambda is created and immediately receives a requests, before the promise chain in init
is resolved. This results in a 404 from Express.
import awsServerlessExpress from "aws-serverless-express";
import Server from "./server";
async function handler(event, context) {
const server = await Server();
return new Promise(resolve => {
awsServerlessExpress.proxy(server, event, {
...context,
succeed: process.env.IS_OFFLINE ? context.succeed : resolve
});
});
}
export { handler };
import awsServerlessExpress from "aws-serverless-express";
import express from "express";
import forestExpressSequelize from "forest-express-sequelize";
import environment from "./environment";
import Db from "../models";
let _server;
export default async function() {
if (_server) return _server;
const db = await Db();
const config = forestExpressSequelize.init({
authSecret: environment.forestAuthSecret,
envSecret: await environment.forestEnvSecret(),
sequelize: db.sequelize
});
const app = express();
app.use(config);
_server = awsServerlessExpress.createServer(app);
return _server;
}
In a smart action with a form that has a enum , the user selects an option and execute the action, after data is fetched I want to download a file from a remote url (a cloudinary hosted file) and return the downloaded file as a response
Not returning the file
I could not find any documentation about how to do this
//rest of the code in users collection
{
name: "Download User Documents",
type: "single",
fields: [
{
field: 'Download User Documents',
description: 'Select Document Type',
type: 'Enum',
isRequired: true,
enums: [
"Carta del Banco",
"Certificado de Proyecto de Trabajo",
"Certifico de No Adeudo Fiscal",
],
}
]
},
...//rest of the code
```
The action code
```
router.post('/actions/download-user-documents', permissionMiddlewareCreator.smartAction(),
(req, res) => {
// Get the values of the input fields entered by the admin user.
const attrs = req.body.data.attributes.values;
let selected_document = attrs['Download User Documents'];
console.log("selected document ", selected_document);
//Logic where I calculate the right file and get the url
res.sendFile(fileName, options, (error) => {
if (error) { next(error); }
//HOW TO SEND THE FILE BACK IF I ONLY HAVE AN EXTERNAL URL??
});
// res.send({ success: "Accion exitosa selected_document " + selected_document })
});
```
In Actions, I'm trying to prefill a form with dynamic default values. So I used the example here and it's like value
function has no effect on fields. No field is prefilled.
Liana.collection('customers', {
actions: [{
name: 'Send money',
fields: [{
field: 'amount',
isRequired: true,
description: 'Amount',
type: 'Number'
}]
}],
values: (context) => {
return {
amount: 123
};
}
});
I'm running on Express server.
When setting APPLICATION_URL need to replace http://localhost:3310 with the URL mentioned as APPLICATION_URL on .env file.
redirect_uri should use this APPLICATION_URL
APPLICATION_URL always return http://localhost:3310
https://api.forestadmin.com/oidc/auth?client_id=eyJraWQiOiJFN3E2Q0FWNGxuWUtwNmdPTlFiaWlZOFhVUDVWSHhmS21VUHZRSnV0Q1Q4IiwiYWxnIjoiUlMyNTYifQ.eyJyZWRpcmVjdF91cmlzIjpbImh0dHA6Ly9sb2NhbGhvc3Q6MzMxMC9mb3Jlc3QvYXV0aGVudGljYXRpb24vY2FsbGJhY2siXSwidG9rZW5fZW5kcG9pbnRfYXV0aF9tZXRob2QiOiJub25lIiwiYXBwbGljYXRpb25fdHlwZSI6IndlYiIsImdyYW50X3R5cGVzIjpbImF1dGhvcml6YXRpb25fY29kZSJdLCJyZXNwb25zZV90eXBlcyI6WyJjb2RlIl0sImVudmlyb25tZW50X2lkIjoxMzA5MTEsImlzcyI6IkZPUkVTVF9BVVRIRU5USUNBVElPTl9TWVNURU0ifQ.l_PY4b6LQ5oQTrt_fqNs3FaQnHFmx6FTJVP8QFZKmZChBWcqKM6zBnh8cheewvxH_2p10qtqjjOhvQILPgnbm49p2dK-uKeLJQmfKXmIa55isgF3BiI3r06hPsnCtB6sLHvgqaO3dPvOCh7ggAv_SdcCa8K2CfiKssPT3PnZEwOvajBgKkuP4hEij2vUKYnmsA-YvSje3048KHZxypVYgFtpb962Lv5X4-r444y4j5TCHDAZsIcL6e45oUfhY1zTZWYyCjzgFEqAo64HF_TOv_WA0NPbtXYhgza58dWfJmawtNiO2dC9MI1uYdGh_eFSxpHV69c5rtJNybYpRWfdbQ&scope=openid email profile&response_type=code&redirect_uri=http://localhost:3310/forest/authentication/callback&state={"renderingId":194334}
When reading core files finds that "require('dotenv'):config();" was missing inside /node_modules/forest-express/dist/context/init.js. So the env file was not loded.
init.js is seen after "npm run build" on server. On repository and in file in my local machine, seen this code in/node_modules/forest-express/dist/context/build-values.js
insde build-values.js the portion
module.exports = function (context) {
return context.addInstance('env', function () {
return _objectSpread(_objectSpread({}, process.env), {}, {
FOREST_URL: process.env.FOREST_URL || 'https://api.forestadmin.com',
JWT_ALGORITHM: process.env.JWT_ALGORITHM || 'HS256',
NODE_ENV: ['dev', 'development'].includes(process.env.NODE_ENV) ? 'development
' : 'production',
APPLICATION_URL: process.env.APPLICATION_URL || "http://localhost:".concat(process.env.APPLICATION_PORT || 3310)
});
}).addValue('forestUrl', process.env.FOREST_URL || 'https://api.forestadmin.com');
};
here didn't get proccess.env.APPLICATION_URL and other variable values
Non-files in the modules (directories esp.) cause the system to crash with the following error message:
[forest] π³π³π³ Cannot read your model in the file DIRNAME for the following reason:
Error: Cannot find module '/PATH/TO/MODELS/DIRNAME'
at Function.Module._resolveFilename (module.js:489:15)
at Function.Module._load (module.js:439:25)
at Module.require (module.js:517:17)
at require (internal/module.js:11:18)
at /PATH/TO/node_modules/forest-express/index.js:28:11
Steps to reproduce:
create a sub-directory in your modules directory and try to re-load
Smart actions maps automatically the action name to the action route converting to lowercase and replacing spaces with -
Cancel Order => cancel-order
There is no way to allow an smart action to be displayed like "Cancel" but the route be "cancel-order" or "cancel-payment" in the same app.
Another use case is to display an action in some Language different to english but keep code in english.
Currently, the integration uses a field called "email" on the model provided by the mapping
parameter to retrieve the associated user in Intercom :
./attributes-getter.js: return intercom.users.find({ email: customer.email });
./conversations-getter.js: email: customer.email,
This needs to be a parameter for when the email field has another name (like us), or we could just rely on the ID which is also stored on intercom.
It looks like forest-express
started using babel back in release 2.9.0 according to the changelog but only as a dev dependency. However, it appears that release 2.14 introduced a dependency on babel in the distributed code. You can see this in routes/sessions.js
and services/login-handler.js
on lines 3-9. I believe this is a result of commit b4dec67 which introduced the ability to use async/await.
I would prefer not to create a dependency to babel in my app.
Today went to work on an app that uses the forest-express-mongoose
implementation of this. I had my version pinned to ^2.5.0
and the app was working in production. Upon starting some new work after a break, I was unable to get my forest express app working with the latest release. It was complaining of being unable to find the babel-runtime/regenerator
module.
module.js:478
throw err;
^
Error: Cannot find module 'babel-runtime/regenerator'
at Function.Module._resolveFilename (module.js:476:15)
at Function.Module._load (module.js:424:25)
at Module.require (module.js:504:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/app/admin/node_modules/forest-express/dist/routes/sessions.js:3:20)
at Module._compile (module.js:577:32)
at Object.Module._extensions..js (module.js:586:10)
at Module.load (module.js:494:32)
at tryModuleLoad (module.js:453:12)
at Function.Module._load (module.js:445:3)
at Module.require (module.js:504:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/app/admin/node_modules/forest-express/dist/index.js:17:20)
at Module._compile (module.js:577:32)
at Object.Module._extensions..js (module.js:586:10)
at Module.load (module.js:494:32)
at tryModuleLoad (module.js:453:12)
at Function.Module._load (module.js:445:3)
at Module.require (module.js:504:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/app/admin/node_modules/forest-express-mongoose/index.js:3:17)
at Module._compile (module.js:577:32)
at Object.Module._extensions..js (module.js:586:10)
at Module.load (module.js:494:32)
at tryModuleLoad (module.js:453:12)
at Function.Module._load (module.js:445:3)
at Module.require (module.js:504:17)
at require (internal/module.js:20:19)
Hi and thanks for your work !
Why is the require call for the models wrapped in an "ignore errors" try/catch ?
Lines 27 to 29 in ed4e501
Am I missing something ?
Cheers
At the moment when I want to add a smart field, I have to add a file to a directory called 'forest' at the route of my project, which is included when the server initializes.
This causes problems for my current set-up, where I'm using babel to transpile ES6 code, as my uncompiled code exists in a 'src' directory and therefore the directory is at 'src/forest'.
The line that enforces this is 215 in index.js:
return requireAllModels(Implementation, path.resolve('.') + '/forest')
It would be good to be able to define this in the same way as 'modelsDir' during initialization.
An even nicer API would be if I could call liana.collection() separately in my apps existing initialization sequence. It seems to me this would open up more options for custom setups like mine not to have to rely on putting all Forest specific code in one predetermined directory
Schema is expected to be created successfully.
Errors out with EROFS: read-only filesystem, open '/.forestadmin-schema.json'
Yarn v2 has introduced a new way of storing dependencies, i.e. not in node_modules, but rather in a cache with dependencies zipped up. This breaks forest-express's getAbsolutePath utility.:
Since the dir no longer has 'node_modules', it is taking the fork return process.cwd()
, which is returning ''
(not sure why, possibly because it's running from a zipped file?), which causes this:
Line 35 in f632e03
The temporary solution is to yarn unplug forest-express
, but if Yarn v2 is going to become more widely used, this should probably be fixed.
I need to update 2 collections at same time.
Right know, here is the simplified structure of my collections:
./models/Batch
const batchSchema = new mongoose.Schema({
name: String,
users: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
});
const Batch = mongoose.model("Batch", batchSchema);
module.exports = Batch;
./models/User
const userSchema = new mongoose.Schema({
firstname: String,
lastname: String,
batch: {
type: mongoose.Schema.Types.ObjectId,
ref: "Batch"
}
});
const User = mongoose.model("User", userSchema);
module.exports = User;
Once I assign a batch
value to an item in the User
collection, I need to update the Batch
collection to add the user._id
in the array. Any way to do that?
I'm currently trying to override a create
route for one of my resources, but I want to deserialize the data coming in the same way forest is deserializing for the create
method. The Serializer is exposed to the API, but the Deserializer is not. I suppose this would also mean it would need to also be exposed in forest-express-sequelize
as well, since it is a wrapper around this.
I know I can copy the deserializer resource and apply it directly since the only dependencies it has are Schema
which IS exposed to the API, but it would be a lot less hacky if it could be exposed directly.
I would like to user https://my-domain.com/path as my Forest Admin server URL. It should work fine.
This setup partially works since I can finish the deployment, but then I can't access my data.
The problem comes from an "OPTIONS" request that is sent to my domain.com/forest/authentication/callback
instead of my-domain.com/path/forest/authentication/callback
.
Hence the request is not recognized by my reverse proxy and fails.
=> This bug comes from routes/authentication.js, in function getCallbackUrl, because of
var url = new URL("/forest/".concat(CALLBACK_AUTHENTICATION_ROUTE), applicationUrl);
(new URL
removes all paths in applicationUrl)
To fix it, new URL should be given the absolute URL already concatenated.
var url = new URL(applicationUrl+"/forest/".concat(CALLBACK_AUTHENTICATION_ROUTE));
Hi guys, could you create a generic Node.js / Mongoose config for forest ?
We use KOA, so your installation sets are not compatible.
Thanks !
Clement from Paris
Form field has the default value as defined in .forestadmin-schema.json
Field has no default value
After migrating from 7.5.1 to 7.9.6 version (I use forest-express-sequelize, migrated from 6.3.15 to 6.7.6) defaultValue in .forestadmin-schema.json has no impact on the UI. If switch forest-express-sequelize back to 6.3.15 (and forest-express to 7.5.1) - defaultValue works
The request is not tampered with if it is for a non forest admin route.
Body parsing middleware runs before matching a forest admin route.
I have an app that exposes both a proxy endpoint to proxy to other services in our system, and a few standard API endpoints. I'm using forest to expose the data in the db owned by the API. I'm using https://github.com/nodejitsu/node-http-proxy as the proxy library, which expects the incoming request to be unparsed.
If using forest, unless I register it as the very last piece of middleware, it breaks the proxying mechanism. Registering forest last does fix the problem, but seems undesirable and not obvious (our production systems went down for 20m when we first deployed w/ forest because we did not know of or expect this quirk).
I first tried to use the collection method to create a new action on the admin panel. I followed the steps in the developper guide but everytime I started my server I got this error :
[forest] π³π³π³ Cannot customize your collection named "contents" properly. Did you call the "collection" method in the /forest directory?
I tried a lot of solutions but none had worked. After inspecting the code, I've seen that this part of the code was blocking the execution.
if (_.isEmpty(Schemas.schemas)) {
logger.error('Cannot customize your collection named "' + name +
'" properly. Did you call the "collection" method in the /forest ' +
'directory?');
return;
}
The Schemas.schemas object was not empty but the code systematically entered in the if statement. After commenting this part of the code, everything worked, the server launched and the actions were available and working on the Admin panel.
npm install forest-express
should work on machines where git is not installed.
Example: a Dockerfile based on Alpine Linux.
Error message: error Couldn't find the binary git
Here is the dependency that is locked on a git version:
Line 34 in bc2bfa1
Allow importing of ESM modules within the require-all
module import happens.
When importing an ESM module using babel, if that module has another ESM module inside it, we get this error (which ultimately comes from require-all
):
import { arrayToObject } from '../utils/arrayUtils';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1055:16)
at Module._compile (internal/modules/cjs/loader.js:1103:27)
at Module._compile (/Users/austin/Dev/RupieNetwork/node_modules/pirates/lib/index.js:99:24)
at Module._extensions..js (internal/modules/cjs/loader.js:1159:10)
at Object.newLoader [as .js] (/Users/austin/Dev/RupieNetwork/node_modules/pirates/lib/index.js:104:7)
at Module.load (internal/modules/cjs/loader.js:988:32)
at Function.Module._load (internal/modules/cjs/loader.js:896:14)
at Module.require (internal/modules/cjs/loader.js:1028:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object.<anonymous> (/Users/austin/Dev/RupieNetwork/src/admin/models/gig.js:1:1)
at Module._compile (internal/modules/cjs/loader.js:1139:30)
at Module._compile (/Users/austin/Dev/RupieNetwork/node_modules/pirates/lib/index.js:99:24)
at Module._extensions..js (internal/modules/cjs/loader.js:1159:10)
at Object.newLoader [as .js] (/Users/austin/Dev/RupieNetwork/node_modules/pirates/lib/index.js:104:7)
at Module.load (internal/modules/cjs/loader.js:988:32)
at Function.Module._load (internal/modules/cjs/loader.js:896:14)
at Module.require (internal/modules/cjs/loader.js:1028:19)
at require (internal/modules/cjs/helpers.js:72:18)
at /Users/austin/Dev/RupieNetwork/node_modules/require-all/index.js:56:46
at Array.forEach (<anonymous>)
at requireAll (/Users/austin/Dev/RupieNetwork/node_modules/require-all/index.js:34:9)
at requireAllModels (/Users/austin/Dev/RupieNetwork/node_modules/forest-express/dist/index.js:95:7)
at buildSchema (/Users/austin/Dev/RupieNetwork/node_modules/forest-express/dist/index.js:130:10)
at Object.exports.init (/Users/austin/Dev/RupieNetwork/node_modules/forest-express/dist/index.js:232:3)
at Object.init (/Users/austin/Dev/RupieNetwork/node_modules/forest-express-sequelize/dist/index.js:219:20)
at new module.exports (/Users/austin/Dev/RupieNetwork/src/admin/middlewares/forestadmin.js:11:17)
at resolve (/Users/austin/Dev/RupieNetwork/src/admin/app.js:62:24)
at /Users/austin/Dev/RupieNetwork/node_modules/require-all/index.js:56:38
at Array.forEach (<anonymous>)
at requireAll (/Users/austin/Dev/RupieNetwork/node_modules/require-all/index.js:34:9)
at /Users/austin/Dev/RupieNetwork/src/admin/app.js:59:3
at Generator.next (<anonymous>)
at asyncGeneratorStep (/Users/austin/Dev/RupieNetwork/src/admin/app.js:14:103)
at _next (/Users/austin/Dev/RupieNetwork/src/admin/app.js:16:194)
See above
Importing ESM modules that contain nested ESM modules from within sequelize-express
.
Hi,
I'd like to integrate InvoiceNinja into Forest, by taking inspiration on the Stripe integration. After digging around the integration code, I realize it will be difficult for me to do that without forking forest-express.
It seems it could be easy to change https://github.com/ForestAdmin/forest-express/blob/devel/integrations/index.js#L5 to initialize modules
with values passed through the liana options.
Before I open a pull request, I'd like to know if you would be willing to make the integration system pluggable.
Thanks :-)
According to the documentation for a hasMany smart field I can define my own route in the form:
router.get('/forest/actor/:actorId/relationships/movies', topMovies);
When I do this my route never gets hit and I see an error being thrown from within forest-express. Looking through the code I see this:
https://github.com/ForestAdmin/forest-express/blob/devel/routes/associations.js#L89
Maybe I'm missing something but isn't that route on the same path as the example one in the docs? If so that would explain why my route never gets hit since the request matches the once noted above.
I feel like I'm probably missing something but I can't for the life of me get a smart field with hasMany to work as is in the documentation. Is there a forest-express example somewhere that I could take a look at?
Thanks!
Since this commit : 20f1ad5 the require('forest-express').ResourceSerializer is not working correctly.
On a relationship route i fetch some data then i pass it to Serializer like that :
const serialized = await new Serializer(Liana, Letters, results.docs, null, {}, {
count: results.total
}).perform()
But i now have an error related to aws-sdk (probably when trying to get signed url from aws to display it on forest)
MissingRequiredParameter: Missing required key 'Key' in params
"Fixed" with npm i [email protected]
Our forest api usually works great.
One time, there was a request that caused a crash in forest-express.
I don't know why this request was special, all I have is the following stack trace.
/tmp/node_modules/forest-express/dist/services/forest-server-requester.js:25
if (result.status === 200 && result.body) {
^
TypeError: Cannot read property 'status' of undefined
at /tmp/node_modules/forest-express/dist/services/forest-server-requester.js:25:18
at Request.callback (/tmp/node_modules/superagent/lib/node/index.js:704:3)
at ClientRequest.<anonymous> (/tmp/node_modules/superagent/lib/node/index.js:637:10)
at Object.onceWrapper (events.js:286:20)
at ClientRequest.emit (events.js:198:13)
at ClientRequest.EventEmitter.emit (domain.js:448:20)
at TLSSocket.socketOnEnd (_http_client.js:426:9)
at TLSSocket.emit (events.js:203:15)
at TLSSocket.EventEmitter.emit (domain.js:448:20)
at endReadableNT (_stream_readable.js:1129:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `lumber update && node ./bin/www.js`
npm ERR! Exit status 1
I'm looking forward to giving this a shot, but didn't see any documentation (or links to it). Can this be added to the README? Otherwise, I'm happy to contribute a PR for it; a link to documentation guidelines would help. Thanks!
I am having a problem using Liana.ensureAuthenticated
for a custom route. I followed the directions of putting the route prior to using Liana.init
, which makes sense so we can use next
to allow liana to handle the request, but then it fails since req.user
is not defined yet. My code looks like this:
app.put('/forest/opportunities/:opportunityId', Liana.ensureAuthenticated, saveImageToS3);
app.use(Liana.init({
modelsDir: require('path').join(__dirname, '/models'), // Your models directory.
envSecret: process.env.FOREST_ENV_SECRET,
authSecret: process.env.FOREST_AUTH_SECRET,
mongoose: require('mongoose')
}));
It never gets to saveImageToS3 since it fails at auth.js
Please support also Fastify framework with another dedicated repo or with some adaptation of the express implementation.
I tried to manually convert every single route and dependencies, but it's an huge job and involves the 2 dependencies forest-express and forest-express-mongoose plus your custom project files.
I need help! Thanks
TODO: What is the current behavior?
TODO: Please include any relevant log snippets, if necessary.
TODO: Please provide any relevant information about your setup.
I should be able to deploy forest-express to Firebase Functions (or another Cloud Functions environment)
All requests fail
All my requests fail with this error:
{
"error": {
"code": 500,
"status": "INTERNAL",
"message": "function crashed",
"errors": [
"socket hang up"
]
}
}
Inside the library forest-express on the function init, there's an async function call to buildSchema, but you guys don't wait for this execution to end before returning the express app. So, the app is being returned too early and the cloud function is being triggered and executed prior to buildSchema finishes and properly set everything up.
This is not going to cause problems on a normal server (unless you made a really fast request before buildSchema finishes), but on cloud functions, this is really problematic.
Here's my log showing the order that things happened:
info: app is being returned
info: User function triggered, starting execution
info: finished defining routes
info: Execution took 4467 ms, finished with status: 'crash'
And this is the proper order that things should have happened:
info: app is being returned
info: finished defining routes
info: User function triggered, starting execution
Notes:
All the logs you saw before I've inserted on this file
added on line 297
- info: app is being returned
added on line 206
- info: finished defining routes
Forest-express has a few outdated deps which have some known vulnerabilities (mostly through the express version).
I think that the easiest way to see what should be updated is using nsp https://github.com/nodesecurity/nsp . You can just run this on the command line and it let's you know what issues exist.
$ nsp check --output summary
(+) 7 vulnerabilities found
Name Installed Patched Path More Info
debug 2.2.0 >= 2.6.9 < 3.0.0 || >= 3.1.0 [email protected] > [email protected] > [email protected] https://nodesecurity.io/advisories/534
debug 2.2.0 >= 2.6.9 < 3.0.0 || >= 3.1.0 [email protected] > [email protected] > [email protected] https://nodesecurity.io/advisories/534
mime 1.3.4 >= 1.4.1 < 2.0.0 || >= 2.0.3 [email protected] > [email protected] > [email protected] > [email protected] https://nodesecurity.io/advisories/535
mime 1.3.4 >= 1.4.1 < 2.0.0 || >= 2.0.3 [email protected] > [email protected] > [email protected] https://nodesecurity.io/advisories/535
fresh 0.3.0 >= 0.5.2 [email protected] > [email protected] > [email protected] https://nodesecurity.io/advisories/526
superagent 1.8.3 None [email protected] > [email protected] https://nodesecurity.io/advisories/479
useragent 2.1.9 >=2.1.13 [email protected] > [email protected] https://nodesecurity.io/advisories/312
Anyway it would be awesome to clean this up. We use nsp to check our dependencies on all our builds and we want to get to green :)
Hello,
Applications with recent versions of forest-express, those that include the server events subscription, do not gracefully shut down.
This is caused by the commit b5db483#diff-bfe9874d239014961b1ae4e89875a6155667db834a410aaaa2ebe3cf89820556R379.
This commit introduces an EventSource subscription which is never properly closed. Since this subscription opens resources that cannot accessed or closed upon shutdown, the process cannot gracefully exit.
How can we close this subscription?
For example let's say I have an entity "Contact" with a couple of smart fields. I also have a "User" entity with a foreign key pointing at a Contact. If I load the forest UI on the User list and click through to an assoicated Contact, the Contact details will not have the smart fields populated, there will be a blank space.
However if I navigate to the Contact list and load a contact it will load the smart field correctly.
I was able to fix this locally with this change: gcoombe@c9b3afa but haven't created a Pull request yet as I feel like I might be missing how this is supposed to work.
I'm trying to upload files to server. I've updated the Maximum Files Size parameter in my Fields configuration. Is there a way to upload a larger file than 100kb, get it through the API, send it to AWS, then get the infos about upload and update collection? I didn't find any documentation about that.
It seems the size limit is set to less than 100kb and every file is sent as a Base64.
PUT /forest/leads/5e8b0e24cdd94010c9c66f12 413 4076 - 3.442 ms
PayloadTooLargeError: request entity too large
at readStream (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/raw-body/index.js:155:17)
at getRawBody (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/raw-body/index.js:108:12)
at read (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/body-parser/lib/read.js:77:3)
at jsonParser (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/body-parser/lib/types/json.js:135:5)
at Layer.handle [as handle_request] (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:317:13)
at /Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:335:12)
at next (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:275:10)
at logger (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/morgan/index.js:144:5)
at Layer.handle [as handle_request] (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:317:13)
at /Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:335:12)
at next (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:275:10)
at expressInit (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/middleware/init.js:40:5)
at Layer.handle [as handle_request] (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:317:13)
at /Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:335:12)
at next (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:275:10)
at query (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/middleware/query.js:45:5)
at Layer.handle [as handle_request] (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:317:13)
at /Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:335:12)
at next (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:275:10)
at Function.handle (/Users/sylvainartuys/Github/LessIsMore/my-admin/node_modules/express/lib/router/index.js:174:3)
I run API with Mongoose.
I've also set the file size limit to 10Mb
app.use(bodyParser.urlencoded({ limit: "10mb", extended: false }));
Authentication to work across clustered apps
The /authentication/callback endpoint fails with a 403
NodeJS runs only on a single core, and it is possible for performance reasons to use nodejs clusters to fork your web server to use all cores. These cores do not share memory, which is not usually a problem so long as express endpoints do not rely on local shared memory, typically these things are pushed into a REDIS or other mem store.
However, in forest-express there is the use of a local cache in forest-express/src/services/oidc-client-manager.js. As far as I can tell, this is causing my clustered forest install to fail on authentication, since there is no guarantee the callback request goes to the same worker process.
No idea how to fix this without explicitly running on a single core.
master
branch failed. π¨I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.
You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. Iβm sure you can resolve this πͺ.
Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.
Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master
branch. You can also manually restart the failed CI job that runs semantic-release.
If you are not sure how to resolve this, here is some links that can help you:
If those donβt help, or if this issue is reporting something you think isnβt right, you can always ask the humans behind semantic-release.
A name for the package must be created. Run through npm (npm run to use npm package name or define packageName in the plugin config or SEMANTIC_RELEASE_PACKAGE
in the environment
Good luck with your project β¨
Your semantic-release bot π¦π
ForestAdmin.com should be able to login to my local instance.
It crashes and does not connect.
TypeError: Cannot read property 'renderingId' of undefined
at getRenderingIdFromUser (/usr/src/app/node_modules/forest-express/dist/middlewares/permissions.js:18:15)
at /usr/src/app/node_modules/forest-express/dist/middlewares/permissions.js:37:27
at Layer.handle [as handle_request] (/usr/src/app/node_modules/express/lib/router/layer.js:95:5)
at next (/usr/src/app/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/usr/src/app/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/usr/src/app/node_modules/express/lib/router/layer.js:95:5)
at /usr/src/app/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/usr/src/app/node_modules/express/lib/router/index.js:335:12)
at next (/usr/src/app/node_modules/express/lib/router/index.js:275:10)
at Function.handle (/usr/src/app/node_modules/express/lib/router/index.js:174:3)
at router (/usr/src/app/node_modules/express/lib/router/index.js:47:12)
at Layer.handle [as handle_request] (/usr/src/app/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/usr/src/app/node_modules/express/lib/router/index.js:317:13)
at /usr/src/app/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/usr/src/app/node_modules/express/lib/router/index.js:335:12)
at next (/usr/src/app/node_modules/express/lib/router/index.js:275:10)
at /usr/src/app/node_modules/express/lib/router/index.js:635:15
at next (/usr/src/app/node_modules/express/lib/router/index.js:260:14)
at Function.handle (/usr/src/app/node_modules/express/lib/router/index.js:174:3)
at router (/usr/src/app/node_modules/express/lib/router/index.js:47:12)
at Layer.handle [as handle_request] (/usr/src/app/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/usr/src/app/node_modules/express/lib/router/index.js:317:13)
at /usr/src/app/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/usr/src/app/node_modules/express/lib/router/index.js:335:12)
at next (/usr/src/app/node_modules/express/lib/router/index.js:275:10)
at /usr/src/app/node_modules/express/lib/router/index.js:635:15
at next (/usr/src/app/node_modules/express/lib/router/index.js:260:14)
at Function.handle (/usr/src/app/node_modules/express/lib/router/index.js:174:3)
at router (/usr/src/app/node_modules/express/lib/router/index.js:47:12)
at Layer.handle [as handle_request] (/usr/src/app/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/usr/src/app/node_modules/express/lib/router/index.js:317:13)
at /usr/src/app/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/usr/src/app/node_modules/express/lib/router/index.js:335:12)
at next (/usr/src/app/node_modules/express/lib/router/index.js:275:10)
Moreover, we have attempted hacking into the code. Switching request.user
to request.body
made it able to connect but made subsequent requests crash.
Setting it back to request.user
made all other requests work and allowed me to view my data.
This may not be a bug within forest-express
itself but possibly within the FA app (did you forget to wrap the body's data into a user
object maybe?). I am submitting this bug here because this is the package in which the code crashes and I am unfamiliar with your package environment.
Dates shown in "Intercom attributes" are expected to be correct.
Dates look exactly like in your screenshot at https://docs.forestadmin.com/documentation/reference-guide/integrations#intercom - they're all in 1970.
Dates returned by the Intercom integration are returned as a Unix time, e.g.1613415151
.
The Date constructor in JS is expecting a number of milliseconds since Unix epoch, e.g. 1613415151000
> new Date(1613415151)
1970-01-19T16:10:15.151Z
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.