fogine / couchbase-odm

CouchbaseODM is a promise-based Node.js ODM for Couchbase
https://fogine.github.io/couchbase-odm
MIT License
12 stars 3 forks source link

[Question] How to deal with a refDoc like a model? #27

Closed RezaOwliaei closed 5 years ago

RezaOwliaei commented 5 years ago

Hi @fogine Is it a good practice to add some props to refDocs? If so, would you please give a sample code how to do this?

What you are doing?

I'm looking for a clean solution to store user's secrets, not in the user model, but something like this:

user_123
  - _id:123
  - username: johnsmith
  - firstname: john
  - lastname: smith
  - someOtherMeta: ...
secret_user_123
  - pass: ...
  - otp: ...
  - aSecretToken: ...
 - emailVerficationCode: ...
 - mobileVerificationCode: ...
 - security:
    - question: ...
   - password: ...

This way, I should be able to fetch a user secret, when needed, just by having the user key:

getSecretByUser(user._id)

If the refDoc isn't a proper way, your recommendation is highly appreciated.

fogine commented 5 years ago

You could approach this by making use of model's associations. Define separated model lets say Secret and associate it with User:

//user-schema
{
    type: 'object',
    properties: {
        username: {type: 'string', format: 'email'},
        secret: {
            type: 'object',
            $relation: {type: 'Secret'}
        },
        //other properties....
    }
}

//Schema of the Secret model:
{
    type: 'object',
    properties: {
        pass: { type: 'string'},
        //other properties....
    }
}

You could then populate the secret object of an user by:

userInstance.populate('secret').then(function(user) {
    //user.secret instanceof Secret
   //user.secret.pass etc...
});

Related API documentation:
https://fogine.github.io/couchbase-odm/Instance.html#populate

However I don't see a reason why would you wanna do that in this case? Users credentials are inherent to the user so I'd keep them in the user document.
A bit more complicated would be if you were to store the documents with users secrets in different bucket than the user document itself eg.: to restrict access to the data and you would not want to keep reference to the secret document in the user document. This is also solvable though:

You'd create separated Secret model as in the first solution but instead of associating it with the User, you'd assign it a different primary key generation strategy.
https://fogine.github.io/couchbase-odm/tutorial-7.customizingDocumentsKey.html

'use strict';
//file secretKey.js

const couchbaseODM = require('kouchbase-odm');
const util         = require('util');
const Key          = couchbaseODM.Key;

module.exports = SecretKey;

function SecretKey(options) {
    Key.call(this, options);
}

SecretKey.dataType = 'string';
util.inherits(SecretKey, Key);

/**
 * generate
 *
 * @param {Instance} instance
 */
SecretKey.prototype.generate = function (instance) {
    return Promise.reject(new Error('Can not generate a secret key id, it must be statically created based on user key'));
};

Then assign it to the Secret model:


const SecretKey = require('path/to/secretKey.js');

const Secret = couchbase.define('Secret', {
    type: 'object',
    //....
}, {
    //options object
    key: SecretKey  // ==> provide constructor function as the option when defining a Model
});

You can then load a document with user credentials by:


Secret.getById(user.getKey().toString());

We can continue the discussion on gitter.