loginWithJwt = async (email, password, saltcornApp, res, req) => {
  const loginFn = async () => {
    const publicUserLink = getState().getConfig("public_user_link");
    const jwt_secret = db.connectObj.jwt_secret;
    if (email !== undefined && password !== undefined) {
      // with credentials
      const user = await User.findOne({ email });
      if (user && user.checkPassword(password)) {
        const now = new Date();
        const token = jwt.sign(
          {
            sub: email,
            user: user.session_object,
            iss: "saltcorn@saltcorn",
            aud: "saltcorn-mobile-app",
            iat: now.valueOf(),
            tenant: db.getTenantSchema(),
          },
          jwt_secret
        );
        if (!user.last_mobile_login) await user.updateLastMobileLogin(now);
        res.json(token);
      } else {
        res.json({
          alerts: [
            { type: "danger", msg: req.__("Incorrect user or password") },
          ],
        });
      }
    } else if (publicUserLink) {
      // public login
      const token = jwt.sign(
        {
          sub: "public",
          user: {
            role_id: 100,
            language: "en",
          },
          iss: "saltcorn@saltcorn",
          aud: "saltcorn-mobile-app",
          iat: new Date().valueOf(),
          tenant: db.getTenantSchema(),
        },
        jwt_secret
      );
      res.json(token);
    } else {
      res.json({
        alerts: [
          { type: "danger", msg: req.__("The public login is deactivated") },
        ],
      });
    }
  };
  if (saltcornApp && saltcornApp !== db.connectObj.default_schema) {
    await db.runWithTenant(saltcornApp, loginFn);
  } else {
    await loginFn();
  }
}
Login with jwt
@param {*} email
@param {*} password
@param {*} saltcornApp
@param {*} res