Coder Social home page Coder Social logo

adminjs-expressjs's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

adminjs-expressjs's Issues

There is no documentation or way how to redirect to custom Login page

Using this function to check the authenticated access to the admin panel:

const router = AdminBroExpress.buildAuthenticatedRouter(adminBro, {
        authenticate: async (email, password) => {
            if (ADMIN.password === password && ADMIN.email === email) {
                return ADMIN
            }
            return null
        },
        cookieName: 'somename',
        cookiePassword: 'somepassword',
    })

How can I use custom login page?

buildAuthenticatedRouter not working correctly in 4.0.2

Hello there,

I am using this package in one of my project and I noticed that after updating to 4.0.2 the authentication is not working as intended.
When i visit the url http://localhost:8080/admin everything works fine, it redirects me to the login route. When i visit http://localhost:8080/admin/(with the / in the end) it just lets me in and i can see the dashboard.
I can also see the the resource urls for example http://localhost:8080/admin/resources/User

I made a small test project so you can test it out.

package.json

{
  "dependencies": {
    "@adminjs/express": "^4.0.2",
    "@adminjs/mongoose": "^2.0.0",
    "adminjs": "^5.6.1",
    "express": "^4.17.2",
    "express-formidable": "^1.2.0",
    "mongoose": "^6.2.1"
  }
}

app.js

const AdminJS = require('adminjs');
const AdminJSExpress = require('@adminjs/express');
const AdminJSMongoose = require('@adminjs/mongoose');
const mongoose = require('mongoose');
const express = require('express');
const app = express();

AdminJS.registerAdapter(AdminJSMongoose);

const run = async () => {
    const User = mongoose.model('User', { name: String, email: String, surname: String });
    const mongooseDb = await mongoose.connect('mongodb://localhost:27017/adminjsissue', { useNewUrlParser: true })

    const adminJs = new AdminJS({
        resources: [User],
        rootPath: '/admin',
    });

    const Admin = {
        email: "[email protected]",
        password: "password"
    }

    const router = AdminJSExpress.buildAuthenticatedRouter(adminJs, {
        authenticate: async (email, password) => {
            if (Admin.email === email && Admin.password === password) {
                return Admin;
            }
            return false;
        },
        cookiePassword: 'some-secret-password-used-to-secure-cookie',
    }, null, {
        resave: false,
        saveUninitialized: true
    });

    const port = 8080;
    const adminPath = adminJs.options.rootPath;

    app.use(adminPath, router);
    app.listen(port, () => console.log(`AdminJS is under localhost:${port}${adminPath}`));
}

run();

If you try it with "@adminjs/express": "4.0.1" it will work just fine.

Library not working with @4.1.0 for some reason

When visiting http://localhost:8000/admin it shows following error:

TypeError: path_to_regexp_1.pathToRegexp is not a function at /Users/yenliksharipkhanova/Documents/projects/yenbek/rest/node_modules/@adminjs/express/src/authentication/protected-routes.handler.ts:59:7 at Array.find (<anonymous>) at Object.isAdminRoute (/Users/yenliksharipkhanova/Documents/projects/yenbek/rest/node_modules/@adminjs/express/src/authentication/protected-routes.handler.ts:58:19) at /Users/yenliksharipkhanova/Documents/projects/yenbek/rest/node_modules/@adminjs/express/src/authentication/protected-routes.handler.ts:22:16 at Layer.handle [as handle_request] (/Users/yenliksharipkhanova/Documents/projects/yenbek/rest/node_modules/express/lib/router/layer.js:95:5) at trim_prefix (/Users/yenliksharipkhanova/Documents/projects/yenbek/rest/node_modules/express/lib/router/index.js:323:13) at /Users/yenliksharipkhanova/Documents/projects/yenbek/rest/node_modules/express/lib/router/index.js:284:7 at Function.process_params (/Users/yenliksharipkhanova/Documents/projects/yenbek/rest/node_modules/express/lib/router/index.js:341:12) at next (/Users/yenliksharipkhanova/Documents/projects/yenbek/rest/node_modules/express/lib/router/index.js:275:10) at /Users/yenliksharipkhanova/Documents/projects/yenbek/rest/node_modules/express-formidable/lib/middleware.js:36:7

The package.json:

{
  "dependencies": {
    "@adminjs/express": "^4.1.0",
    "@adminjs/sequelize": "^2.1.5",
    "@sentry/node": "^6.19.2",
    "@sentry/tracing": "^6.19.2",
    "@types/express-session": "^1.17.4",
    "adminjs": "^5.9.9",
    "aws-sdk": "^2.1111.0",
    "bcrypt": "^5.0.1",
    "body-parser": "^1.20.0",
    "compression": "^1.7.4",
    "cookie-parser": "^1.4.6",
    "cors": "^2.8.5",
    "detect-libc": "^2.0.1",
    "express": "^4.17.2",
    "express-formidable": "^1.2.0",
    "express-session": "^1.17.2",
    "express-validator": "^6.14.0",
    "file-type": "^17.1.1",
    "firebase": "^9.6.5",
    "firebase-admin": "^10.0.2",
    "formidable": "^2.0.1",
    "multiparty": "^4.2.3",
    "node-gyp": "^9.0.0",
    "pg": "^8.7.1",
    "pg-hstore": "^2.3.4",
    "reflect-metadata": "^0.1.13",
    "sequelize": "^6.17.0",
    "sequelize-typescript": "^2.1.3",
    "sqlite3": "^5.0.2",
    "uuid": "^8.3.2"
  },
  "devDependencies": {
    "@types/bcrypt": "^5.0.0",
    "@types/compression": "^1.7.2",
    "@types/cors": "^2.8.12",
    "@types/express": "^4.17.13",
    "@types/multiparty": "^0.0.33",
    "@types/node": "^14.18.12",
    "@types/uuid": "^8.3.4",
    "@types/validator": "^13.7.1",
    "@typescript-eslint/eslint-plugin": "^5.10.1",
    "@typescript-eslint/parser": "^5.10.1",
    "eslint": "^8.7.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-prettier": "^4.0.0",
    "nodemon": "^2.0.15",
    "prettier": "2.5.1",
    "ts-node": "^10.4.0",
    "tsconfig-paths": "^3.12.0",
    "tslint": "^6.1.3",
    "typescript": "^4.5.5"
  }
}

After downgrading @adminjs/express to 4.0.1 it starts to work fine. Both 4.0.2, 4.0.3 not working.

Can you please help with this issue?

rootPath as slash causes endless redirect loop

Lukáš Novotný wrote on slack:

Adminbro end in endless redirect loop when I set rootPath: "/"? It does a redirect to /login but it end in redirect loop.

Code to reproduce

const server = express()
const adminBro = new AdminBro({
    rootPath: "/",
    loginPath: "/login",
    logoutPath: "/logout",
    ...
})
const adminRouter = buildAdminRouter(adminBro)
server.use("/", adminRouter)
server.listen(3000, () => {
    console.log(`Server running at 3000`)
})

Boot timeout - Deploy to Heroku

I'm trying to deploy the admin app to Heroku, I keep getting this error. I managed to increase this boot time as far as 180 seconds and the outcome was the same.

Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch

Screenshot from 2020-11-05 21-21-51
Screenshot from 2020-11-05 21-22-28
Screenshot from 2020-11-05 21-22-59

Not able to login when NODE_ENV=production

Authentication works fine on the development environment. But if I set the NODE_ENV to production, it won't.

I see the server is still responding with 200 OK, but it's getting redirected to the login page.

Also, I noticed a warning,

express-session deprecated undefined resave option;
express-session deprecated undefined saveUninitialized option
Warning: connect.session() MemoryStore is not
designed for a production environment, as it will leak
memory, and will not scale past a single process.

It would be nice if the default cookie parser and session is configured only no predefined router is passed. Or at least an option to skip that, so that I can pass a predefined router with session configuration. I'm not using the buildRouter since I want the authentication methods.

Passing query params makes requests bypass the auth check

Describe the bug
Providing any valid query param combination, allows users to bypass the cookie check

Installed libraries and their versions

To Reproduce
Steps to reproduce the behavior:

  1. Have an admin with required authentication
  2. Log in
  3. Navigate to any resource
  4. Apply any filter
  5. Bookmark the page or copy the URL with query params
  6. Either log out or open a new tab in incognito mode
  7. Go to saved URL with query params
  8. You will see the entities

Expected behavior
You should be redirected to the login page

Trailing slash on rootPath not taken into account by authentication

Hi 👋

First of all thanks for AdminJS, I am very happy to use it and it saves us a lot of time in our Company.

We did some tests recently about authentication, and it seems that there is a hole in the admin route management.

Here is what we observed:

  • AdminJS is configured with a /admin rootPath
  • We are using the default authentication system, with a custom authenticate handler
  • Being logged out:
    • Accessing /admin prompt the expected login screen
    • Accessing /admin/ shows to the dashboard and bypass the login screen 🚨

We are using AdminJS in a NestJS 8.4.2 context, with AdminJS 5.7.4 and authentication enabled:

auth: {
  authenticate: authenticateAdmin,
  cookieName: adminCookieInfo.name,
  cookiePassword: adminCookieInfo.password,
},
sessionOptions: {
  secret: adminCookieInfo.password,
  store: new PGStore({
    pool: pgSessionPool,
    tableName: 'user_session',
  }),
},
adminJsOptions: {
  rootPath: '/admin',
}

After some investigations, it seems that the problem is located in the isAdminRoute function from the src/authentication/protected-routes.handler.ts file when the isAdminRootUrl is set.
At this point, url and adminRootPath are different: url is /admin/ (the URL from my test), and adminRootPath is /admin.
As I do not fully understand the consequences of changing the code in this file, I prefer not to suggest a PR and only report an issue.

Edit: updating to the latest AdminJS / @adminjs/express (6.2.3 / 5.0.0) does not fix the issue unfortunately.

Don't redirect using POST on login

PR: #35

Problem

Currently after POST on loginPath you're being redirected to either rootPath or redirectTo from session. The problem is, it uses 307 redirect which keeps the request method and form data.

In some circumstances (eg. using with nestjs) you might end up with redirecting to the rootPath AS a POST request, so you'll see the message that route POST ${rootPath} does not exist.

Solution

Redirect from POST loginPath using 302 status

express-session deprecated pass resave option

express-session deprecated undefined resave option; provide resave option at node_modules/@adminjs/express/lib/buildAuthenticatedRouter
express-session deprecated undefined saveUninitialized option; provide saveUninitialized option at node_modules/@adminjs/express/lib/buildAuthenticatedRouter.js

I get that deprecation warning above, which needs to specify the resave and the saveUninitialized options to the value you want to use. See https://github.com/expressjs/session#options for their values and meanings.

express-session deprecated undefined resave option & undefined saveUninitialized option.

When I set up Role-Based Access Control in my Express API got the next warnings:

Warnings

express-session deprecated undefined resave option; provide resave option node_modules/admin-bro-expressjs/plugin.js:131:14
express-session deprecated undefined saveUninitialized option; provide saveUninitialized option node_modules/admin-bro-expressjs/plugin.js:131:14

Versions

"admin-bro": "^1.3.5",
"admin-bro-expressjs": "^0.2.0",
"admin-bro-sequelizejs": "^0.2.6",
"admin-bro-theme-dark": "^1.0.0",
"cookie-parser": "~1.4.4",
"express": "~4.16.1",
"express-session": "^1.17.0",

Option to use cookie-session.

We are looking into using Admin Bro and would like the option to be able to use cookie-session over express-session, as client side cookies would be more convenient in our use case.

We are currently implementing our own buildAuthenticatedRouter style function to hook into our auth system.

TypeError: AdminJSExpress.buildAuthenticatedRouter is not a function

I've tried implementing the example of an authenticated router provided here but I am running into an error message.

I have changed to use my DB_URI and I am able to access DB_URI both locally and remotely on my fly.io app, but in both cases I run into this error:


  const adminRouter = AdminJSExpress.buildAuthenticatedRouter(
                                     ^

TypeError: AdminJSExpress.buildAuthenticatedRouter is not a function
    at start (etc)

Here is the code I am running, based off that adminjsexpress example:


import AdminJS from 'adminjs'
import * as AdminJSExpress from '@adminjs/express'
import express from 'express'
import Connect from 'connect-pg-simple'
import session from 'express-session'
// import  from 'express-session'
import * as dotenv from 'dotenv' // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
dotenv.config()

const PORT = 3000

const DEFAULT_ADMIN = {
  email: '[email protected]',
  password: 'password',
}

const authenticate = async (email, password) => {
  if (email === DEFAULT_ADMIN.email && password === DEFAULT_ADMIN.password) {
    return Promise.resolve(DEFAULT_ADMIN)
  }
  return null
}
console.log("hi");
console.log(process.env.DB_URI);
const start = async () => {
  const app = express()

  const admin = new AdminJS({})

  const ConnectSession = Connect(session)
  const sessionStore = new ConnectSession({
    conObject: {
      connectionString: process.env.DB_URI,
      ssl: process.env.NODE_ENV === 'production',
    },
    tableName: 'session',
    createTableIfMissing: true,
  })

  const adminRouter = AdminJSExpress.buildAuthenticatedRouter(
    admin,
    {
      authenticate,
      cookieName: 'adminjs',
      cookiePassword: 'sessionsecret',
    },
    null,
    {
      store: sessionStore,
      resave: true,
      saveUninitialized: true,
      secret: 'sessionsecret',
      cookie: {
        httpOnly: process.env.NODE_ENV === 'production',
        secure: process.env.NODE_ENV === 'production',
      },
      name: 'adminjs',
    }
  )
  app.use(admin.options.rootPath, adminRouter)

  app.listen(PORT, () => {
    console.log(`AdminJS started on http://localhost:${PORT}${admin.options.rootPath}`)
  })
}

start()

Express issue + improvement

I noticed some errors when I run that inside a NODE_ENV=production env.

express-session deprecated undefined resave option; provide resave option at node_modules/admin-bro-expressjs/plugin.js:131:14
express-session deprecated undefined saveUninitialized option; provide saveUninitialized option at node_modules/admin-bro-expressjs/plugin.js:131:14
Warning: connect.session() MemoryStore is not
designed for a production environment, as it will leak
memory, and will not scale past a single process.

We should have a options to set express.js values directly.
Something like that in plugin.js :

const buildAuthenticatedRouter = (admin, auth, predefinedRouter, expressOptions = {}) => {
  if (!cookieParser || !session) {
    throw new Error(['In order to use authentication, you have to install',
      'cookie-parser and express-session packages'].join(' '))
  }
  const router = predefinedRouter || express.Router()
  router.use(cookieParser())
  router.use(session({
    secret: auth.cookiePassword,
    name: auth.cookieName || 'adminbro',
    ...expressOptions
  }))

AdminJS Mongoose is not working with Typescript

Cannot find module '@adminjs/mongoose' or its corresponding type declarations.
There are types at 'c:/Users/Aman/Desktop/Project/mlcoe/quiz_backend/node_modules/@adminjs/mongoose/lib/index.d.ts', but this result could not be resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'.ts(2307)

Here my ts config file
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"strict": true,
"noImplicitAny": true,
"moduleResolution": "node",
"sourceMap": true,
"baseUrl": ".",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strictPropertyInitialization": false,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"paths": {
"": [
"node_modules/
"
]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}

Unable to use nestjs and admin-bro in the same app due to body-parser and formidable.

Backend api built with nestjs serves call at /, endpoints looks like /users/me or /auth/login etc.
Before adding AdminBro, call to /auth/login with post body of {"email": "<some-email>", "password": "<some-password>" } works fine.
But when adding a module named Backoffice to my app.module.ts post body is not found when calling /auth/login and throws an exception in the controller.
All calls to AdminBro works fine under /admin

@Module({
    imports: [
      AdminModule.createAdminAsync({
        imports: [
          TypeOrmModule.forRootAsync({
            imports: [SharedModule],
            inject: [ConfigService],
            useFactory: (configService: ConfigService) => configService.typeOrmConfig,
          }),
          UsersModule,
        ],
        inject: [UsersService, ConfigService],
        useFactory: (usersService: UsersService, configService: ConfigService) => {
          return {
            adminBroOptions: {
              rootPath: '/admin',
              resources: AdminBroResources,
            },
            auth: {
              authenticate: async (email, password) => {
                const user = await usersService.findOne({
                  email: email,
                  password: ConfigService.getPasswordsHash(password),
                });
                if (user) {
                  return { email: `${user.firstName}`, title: user.email.split('@')[0] };
                }
                return false;
              },
              cookiePassword: configService.get('COOKIE_SECRET'),
              cookieName: 'backoffice',
            },
          } as AdminModuleOptions;
        },
      }),
    ],
    // providers: [UsersService],
  })
  export class BackofficeModule {}

package.json dependencies used:
"@admin-bro/express": "^3.0.1", "@admin-bro/nestjs": "^1.0.0", "@admin-bro/typeorm": "^1.3.0", "express-formidable": "^1.2.0",

I've narrowed it down to ExpressLoader in this repo which moves jsonParser and urlencodeparser in layer stack below AdminBro router. Commenting this out breaks AdminBro but nestjs api works again.

Redirect to previously visited page after login

Actual behaviour:

  • Visit <admin_url>/resources/MyResource/records/SomeId
  • If you didn't log in earlier you are redirected to log in page.
  • After logging in with valid credentials you are redirected to main page of admin panel instead of the desired: <admin_url>/resources/MyResource/records/SomeId

Expected:

  • Visit <admin_url>/resources/MyResource/records/SomeId
  • Log in
  • After successful login be redirected to <admin_url>/resources/MyResource/records/SomeId

It would be nice to have feature, good to be picked up as first issue I think

Typescript import does not work as intended

Typescript failing to execute due to error TS2339
AdminJSExpress is failing to be identified proper in typing.

My versions:

  • "typescript": "^4.6.3"
  • "adminjs": "^5.9.10",
  • "@adminjs/express": "^4.1.0"

Code example:

import * as express from 'express'
import AdminJS from 'adminjs'
import * as AdminJSExpress from '@adminjs/express'

const adminJs = new AdminJS({
  databases: [],
  rootPath: '/admin',
})

const app = express()

// This line fails with: 
// TS2339: Property 'buildRouter' does not exist on type 'typeof import("/project/path/node_modules/@adminjs/express/lib/index")'
const router = AdminJSExpress.buildRouter(adminJs)

app.use(adminJs.options.rootPath, router)
app.listen(8080, () => console.log('AdminJS is running under localhost:8080/admin'))

Workaround is to add a comment // @ts-ignore TS2339:

// @ts-ignore TS2339
const router = AdminJSExpress.buildRouter(adminJs)

This is necessary when making any calls to AdminJSExpress

Also if helpful for debugging here is a copy of my .tsconfig

{
    "compilerOptions": {
      "target": "es2020",
      "module": "commonjs",
      "strict": true,
      "noImplicitAny": true,
      "moduleResolution": "node",
      "sourceMap": true,
      "outDir": "dist",
      "baseUrl": ".",
      "forceConsistentCasingInFileNames": true,
      "strictPropertyInitialization": false,
      "experimentalDecorators": true,
      "emitDecoratorMetadata": true,
      "paths": {
        "*": [
          "node_modules/*"
        ]
      }
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules"]
  }

missing tslib dependency

node_modules/@admin-bro/express/lib/buildAuthenticatedRouter.js:1
Error: Cannot find module 'tslib'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.