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

Can't protect route with async check (at least not easily) #23

Open
eric-burel opened this issue Aug 27, 2020 · 0 comments
Open

Can't protect route with async check (at least not easily) #23

eric-burel opened this issue Aug 27, 2020 · 0 comments

Comments

@eric-burel
Copy link

eric-burel commented Aug 27, 2020

I've made some initial tests with protected, in order to be able to check if an user can access the document before serving it.
Sadly, protected does not seem to support async calls. We can't even get the currentUser in the callback, so it becomes useless. I open this ticket so that people that stumble upon this package don't try to setup a private file system with Meteor Files: it won't work, at least not in Vulcan, and won't allow for complex permission system.

Edit: according to Meteor Files dev, you can have async code, but you'll have to use Fibers and future which is pretty Meteor-specific.

Still I've written some code that would have worked if async access check was supported in Meteor Files. I paste it here in case it ever happens:

/**
 * Helpers to setup the "protected" method of FSCollection
 *
 * Since we don't rely on normal Meteor auth, we have to write custom logic to get the userId/user
 *
 * NOTE: we currently have no way to check more properties. If you need to handle customizable permissions,
 * use a specific collection to store permission, and find relevant permissions based on the fileId or userId in the protected callback.
 */

// TODO: this logic is duplicated from Vulcan. In ulterior versions we might refactor
import { Meteor } from "meteor/meteor";
import { Accounts } from "meteor/accounts-base";
import { check } from "meteor/check";
// @see https://github.com/meteor/apollo/blob/master/src/server.js
export const getUserFromToken = async (loginToken) => {
  if (loginToken) {
    check(loginToken, String);

    const hashedToken = Accounts._hashLoginToken(loginToken);

    const user = await Meteor.users.rawCollection().findOne({
      "services.resume.loginTokens.hashedToken": hashedToken,
    });

    if (user) {
      // find the right login token corresponding, the current user may have
      // several sessions logged on different browsers / computers
      const tokenInformation = user.services.resume.loginTokens.find(
        (tokenInfo) => tokenInfo.hashedToken === hashedToken
      );

      const expiresAt = Accounts._tokenExpiration(tokenInformation.when);

      const isExpired = expiresAt < new Date();

      if (!isExpired) {
        return user;
      }
    }
  }
};
const getAuthToken = (req) => {
  return (
    req.headers.authorization ||
    new Cookies(req.cookies).get("meteor_login_token")
  );
};
const getUserFromReq = async (req) => {
  const user = await getUserFromToken(getAuthToken(req));
  if (user) {
    return {
      userId: user._id,
      currentUser: user,
    };
    // identify user to any server-side analytics providers
    // runCallbacks("events.identify", user);
  }
  return {};
};

export const getUser = async (protectedContext) => {
  const { request } = protectedContext;
  const { userId, currentUser: user } = await getUserFromReq(request);
  return { userId, user };
};

You would then use it like this:

  protected: async function(fileObj) { // fat arrow won't work, we need `this`
    const { userId, user } = await getUser(this);
    if (!userId) return false;
    return true;
  },

Again, it doesn't work because you can't have an async function.

@eric-burel eric-burel changed the title Can't protect Can't protect route with async check Aug 27, 2020
@eric-burel eric-burel changed the title Can't protect route with async check Can't protect route with async check (at least not easily) Sep 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant