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

using server only session data in filter #29

Open
Rohithzr opened this issue Oct 11, 2017 · 7 comments
Open

using server only session data in filter #29

Rohithzr opened this issue Oct 11, 2017 · 7 comments

Comments

@Rohithzr
Copy link

Rohithzr commented Oct 11, 2017

I have a situation where the user sends a token from client via query params and I use the same to validate the session and store the the userId in the RP session.

options.sessionCreator = function (params) {
  let token = params.token;
  let user = params.user;
  if (!token || token == "" || !user || user == "") {
    return Promise.reject('Invalid auth token');
  } else {
    // use teade to validate the user from user service
    const clients = {
      users: {
        host: process.env.SERVICE_RPC_HOST,
        port: process.env.CXI_USER_PORT
      }
    }
    const data = {
      token: token,
      user: user
    }
    const authenticator = require('./middlewares/authenticator');

    return Promise.promisify(authenticator.auth)(clients, data)
      .then(function(result){
        return Promise.resolve({userId: result.data.id});
      }).catch(function(err){
        return Promise.reject(err.message);
    })
  }
};

now I want to add this userId in the filter of a query but I dont have this id in the frontend.

So I am looking for a way to either

  1. add a filter to the query on the server (maybe in validate) and not send the aforementioned filter from frontend
  2. modify the filter data on the server no matter what is sent from the front end.
// whitelisted query
r.table("trades").orderBy({index: allowSpecificFieldOrderBy(RP, "datetime")})
            .filter(r.row("currency").eq(allowAnyString(RP)))
            .filter(r.row("isExecuted").eq(true))
            .filter(r.row('userId').eq(
                 /* what can I use here? */
             ))
            .pluck("datetime", "rate", "id")
            .changes({"includeInitial": true}).opt("db", r.db("cxihub"))
            .validate(function (refs, session) {
                // console.log(refs, session)
                // { userId: '' } { userId: 1 }
                return true;
            })
@mikemintz
Copy link
Owner

I think you want something like this:

// whitelisted query
r.table("trades").orderBy({index: allowSpecificFieldOrderBy(RP, "datetime")})
            .filter(r.row("currency").eq(allowAnyString(RP)))
            .filter(r.row("isExecuted").eq(true))
            .filter(r.row('userId').eq(RP.ref('userId'))
            .pluck("datetime", "rate", "id")
            .changes({"includeInitial": true}).opt("db", r.db("cxihub"))
            .validate(function (refs, session) {
                return refs.userId === session.userId;
            })

@Rohithzr
Copy link
Author

Rohithzr commented Oct 12, 2017

@mikemintz hello, thank you for your reply, the issue is that I do not have this userId on the frontend, so I send a token and it gives me userId inside session. I want to modify the incomining query to use it.

so my frontend sends {userId: "token"} while what rethinkdb sees {userId: "abcd"}

@Rohithzr
Copy link
Author

I have been playing a lot with the lbrary, I can see it converts data to binary buffer and sends to rethinkdb, I tried to interept that buffer, converted to string and replaced it to my desired value and then forwarded it, but it does not work, the connection just hangs.

so I have been trying to find a suitable place in the library to modify the query beforeit is sent to the rethinkdb

@mikemintz
Copy link
Owner

This is not currently possible without modifying the library, but it is one of the goals of #2.

One approach would be to refactor validateQueryCmd, so that instead of returning a boolean, it returns one two response types: like {type: "passthrough", allow: false/true} and {type: "rewrite", newQueryCmdBuf: ...}. You'd have to thread that through. And then you'd either refactor the API so that validate can return a rewritten query in addition to returning a boolean, or make a new API method like RP.rewrite.

I haven't fully thought this through, but I'm definitely open to ideas on refactoring so query rewriting is supported.

@Rohithzr
Copy link
Author

Hello I have been trying to play with the code, find a workaround. I actually thought i succeded but that was not the case. look at this file https://github.com/Rohithzr/rethinkdb-ws-server/blob/077f41d31c97779d6f04d4c19445dbdae6ef2ffc/src/Connection.js#L127
and readme (of the idea, i tried to apply) https://github.com/Rohithzr/rethinkdb-ws-server

@mikemintz
Copy link
Owner

Rather than doing string manipulations like rawQuery.indexOf and rawQuery.replace, I would recommend manipulating the query as JSON using JSON.parse and JSON.stringify. I would also run validateQueryCmd before doing the query manipulation, so that you guarantee you're only manipulating a valid query.

@mikemintz
Copy link
Owner

You may also want to read through https://www.rethinkdb.com/docs/writing-drivers/ to get an idea of how the JSON is formatted, so it's more clear what part of the query you should manipulate.

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

2 participants