How to set push key when pushing to firebase database? - node.js

When I write data to firebase database from both frontend(Angular 4) and backend(firebase functions), there is a push key generated by firebase. With this key, I cannot access data in the future because the key is unique. I am wondering is any way I can set the key myself or I can access the data without knowing the key?
Here is my code from frontend:
this.db.list(`${this.basePath}/`).push(upload);
Here is my code from backend:
admin.database().ref('/messages').push({original: original}).then(function (snapshot) {
res.redirect(303, snapshot.ref);});
All data I pushed will be under path/pushID/data
I cannot access data without knowing the pushID.
The best case I want is path/my own pushID/data
Thanks so much for help!!

If you want to loop through all messages:
var ref = firebase.database().ref("messages");
ref.once("value", function(snapshot) {
snapshot.forEach(function(message) {
console.log(message.key+": "+message.val().original);
});
});
If you want to find specific messages, use a query:
var ref = firebase.database().ref("messages");
var query = ref.orderByChild("original").equalTo("aaaa");
query.once("value", function(snapshot) {
snapshot.forEach(function(message) {
console.log(message.key+": "+message.val().original);
});
});
For much more on this, read the Firebase documentation on reading lists of data, sorting and filtering data, and take the Firebase codelab.

The keys should be unique in any way. You can set your own key like this instead of push
admin.database().ref('/messages/'+ yourUniqueId).set({original: original}).then(function (snapshot) {
res.redirect(303, snapshot.ref);});
yourUniqueId can be auth uid or email of user, like something unique.

Related

Azure keyvault, request for multiple secrets

Im making use of the following node library azure-keyvault to get retrieve stored secrets from azure keyvault. Ive only found the client.getSecret api exposed to retrieve a secret value. Im searching for a way to retrieve multiple secret values in one call. I hav'nt found one yet. Is there a way to do this that i'm missing or its simply not supported.
const { SecretClient } = require('#azure/keyvault-secrets')
const client = new SecretClient(
`https://${KEYVAULT_NAME}.vault.azure.net`,
new DefaultAzureCredential()
)
const [secret1, secret2] = await Promise.all([
client.getSecret(`secret1`),
client.getSecret(`secret2`)
])
Here is the complete code for getting the multiple client secret at once:
var credentials = new KeyVault.KeyVaultCredentials(authenticator);
var client = new KeyVault.KeyVaultClient(credentials);
client.setSecret(vaultUri, 'mysecret', 'my password', options, function (err, secretBundle) {
// List all secrets
var parsedId = KeyVault.parseSecretIdentifier(secretBundle.id);
client.getSecrets(parsedId.vault, parsedId.name, function (err, result) {
if (err) throw err;
var loop = function (nextLink) {
if (nextLink !== null && nextLink !== undefined) {
client.getSecretsNext(nextLink, function (err, res) {
console.log(res);
loop(res.nextLink);
});
}
};
console.log(result);
loop(result.nextLink);
});
});
You can find the complete reference for azure key vault using node js below:
http://azure.github.io/azure-sdk-for-node/azure-keyvault/latest/KeyVaultClient.html#getSecrets
http://azure.github.io/azure-sdk-for-node/azure-keyvault/latest/
Hope it helps.
You can use read-azure-secrets npm package which will return all secrets to you.
E.g.
const secretClient = require('read-azure-secrets');
async function loadKeyVaultValues() {
let applicationID = '';
let applicationSecret = '';
let vaultURL = 'https://<your-key-vault-name>.vault.azure.net/';
let secrets = await secretClient.getSecrets(applicationID, applicationSecret, vaultURL);
secrets.forEach(secret => {
console.log(secret);
});
}
loadKeyVaultValues();
You can try using client.getSecrets(..) method exposed by the REST Api.
Kindly go through the following useful blog, in which all methods have been implemented.
LINK: https://www.red-gate.com/simple-talk/cloud/platform-as-a-service/using-azure-keyvault-with-node-js/
You haven't specified what information about the secret you want to fetch so I am going to assume that you are looking for the secret's value. I am also going to assume you are looking to minimize network traffic for fetching multiple secrets (either for costs or for performance).
Looking at the Azure REST API documentation while there is a route to list multiple secrets it only provides the secret identifier and metadata about the secret (attributes, tags, etc). So if you want to get the secret's value (the actual secret) you will need to make individual calls although get-secrets route can be used to find all the secrets stored in the Key Vault.
As far as the client library, #azure/keyvault-secrets maps pretty closely to the REST API it supports so it will not provide a method that fetches multiple secrets. Even if it did, it would just be a facade over multiple network calls so it would not help reduce the number of network trips.
So to answer your question - it does not look possible today unless all you want is metadata about the secret and not the secret value itself.

Node.js and mongoose - prevent salt and password to return to client

I have a node.js app with mongoose. my problem is that when returning entities with populated user, the user data includes secure data like salt, tokens and password. I used the following method to prevent private data from going back to client:
User.methods.toJSON = function() { // Do not change to lambda expression
const SERVER_ONLY_PROPERTIES = ['tokens', 'salt', 'password'];
var user = this.toObject();
SERVER_ONLY_PROPERTIES.forEach(propKey => {delete user[propKey]});
return user;
}
Everything worked great, until I used the lean() function in my code.
when using lean the toJson method isn't being called and the private data returns to client. what are my options?
Instead of taking out the stuff that you don't want to return, you should instead have a process that builds a new object to return that explicitly includes only the necessary pieces of data. That's the best practice as far as security, if I'm not mistaken.

How to delete on based of subkey using hset in redis in node js app

I am trying to use redis in my nodejs application. I am able to save and retrieve value perfectly. I am using hash which allows me to have single unique key as well sub-keys. Here offer id is my sub key and offer is key.
I am saving offer like below
let offer = {
offerId: req.query.id,
offerName: req.query.offerName,
offerVendor: req.query.offerVendor
}
client.hset('offer', offer.offerId, JSON.stringify(offer), redis.print);
and retrieving value like below
try {
console.log('ping response:', await client.ping());
const offerId = req.query.id;
client.hget('offer', offerId, function(err, reply){
let offer = JSON.parse(reply);
res.send(offer);
});
} catch(err) {
console.log('ping error:', err);
}
I want to delete offer based on id as like saving or getting on based of id. I have gone through documentation https://github.com/NodeRedis/node_redis#usage-example but didn't find there.
What is the way to do delete offer based on id ?
If you already have the offer id, you can delete it from the offer hash using the hdel command. Your code would look something like:
client.hdel('offer', id)
The result from the call will be an integer count of the number of keys deleted. If you don't know the client id, you can look for it using the hscan command.

Redis: How to save (and read) Key-Value pairs at once by namespace/rule?

I want to utilize Redis for saving and reading a dynamic list of users.
Essentially, Redis is Key-Value pair storage. How can I read all the saved users at once? (for example, creating a namespace "users/user_id")
And since I am a Redis beginner,
Do you think the use of Redis in the above case is proper/efficient?
Thanks.
When using key/values for storing objects you should create a domain specific key by combining the domain name plus the unique id. For example, a user object that might look like this:
// typical user data model
var User = function(params) {
if (!params) params = {};
this.id = params.id;
this.username = params.username;
this.email = params.email;
// other stuff...
};
Then domain key could be created like this:
var createUserDomainKey = function(id) {
return 'User:' + id;
};
If the id was 'e9f6671440e111e49f14-77817cb77f36' the key would be this:
User:e9f6671440e111e49f14-77817cb77f36
Since redis will store string values, you need to serialize, probably with json so to save the user object. Assuming a valid use object would would do something like this:
var client = redis.createClient(),
key = createUserDomainKey( user.id ),
json = JSON.stringify( user ) ;
client.set( key, json, function(err, result) {
if (err) throw err; // do something here...
// result is 'OK'
});
For simple fire-hose queries returning all users, you can do this:
var client = redis.createClient();
client.keys( createUserDomainKey( '*' ), function(err, keys) {
if (err) throw err; // do something here
// keys contains all the keys matching 'User:*'
});
Note that the redis folks discourage the use of 'keys' for production, so a better approach is to build your own index using sorted-set, but if your user list is limited to a few hundred, there is no problem.
And since it returns a list of keys, you need to loop through and get each user then parse the json string to recover the real object. Assuming a populated list of keys, you could do something like this:
var client = redis.getClient(),
users = [];
var loopCallback = function(err, value) {
if (!err && value) {
// parse and add the user model to the list
users.push( JSON.parse( value ) );
}
// pull the next key, if available
var key = keys.pop();
if (key) {
client.get( key, loopCallback );
} else {
// list is complete so return users, probably through a callback;
}
}
// start the loop
loopCallback();
This is a good general purpose solution, but there are others that use sorted sets that are move efficient when you want access to the entire list with each access. This solution gives you the ability to get a single user object when you know the ID.
I hope this helps.
ps: a full implementation with unit tests of this can be found in the AbstractBaseDao module of this project.

DocumentDB: Delete a document by ID

I'm using a new database from Microsoft called DocumentDB. Now I want to delete a document by ID, but I cannot figure out, how to do this. Delete operation in DocumentDB requires self-links and they are different from my own ids.
using (var client = new DocumentClient(EndPoint, AuthKey))
{
await client.DeleteDocumentAsync("**self-link here**");
}
I can execute an additional query to find the self-link and then pass it, but this will require two operations instead one and that is what I'd like to avoid. Is there a better way to remove an entry by ID without using queries or stored procedures?
* UPDATE * This feature has now been implemented
* ORIGINAL ANSWER *
Not today, no. You can head to http://feedback.azure.com/forums/263030-documentdb and vote for the feature there.
Here is how I am deleting document
{
var docUri = UriFactory.CreateDocumentUri(_documentDataBaseId, _documentCollectionId, docId);
await _documentClient.DeleteDocumentAsync(docUri);
}
This features has now been implement (as of the 8/2015 - https://feedback.azure.com/forums/263030-documentdb/suggestions/6333050-it-should-be-possible-to-remove-a-document-by-id
as there's no solution for this case I'd recommend to retrieve all the documents in the existing collection to get access to the SelfLink and _rid values.
I just started a mini wrapper to get access to DocumentDB in Universal Apps and hopefully CrossPlatform using Xamarin: https://github.com/JorgeCupi/documentDB-Win10UAP-wrapper feel free to give me any feedback, participate or request some needed methods.
I have tried this code in nodejs to deletebyId and it works for me.
deleteDocumentById: function(params, callback) {
var self = this,
query= params.query,
collection = params.collection;
client.queryDocuments(collection._self, query, function(err, docs) {
if (err) {
return callback(err);
}
client.deleteDocument(docs[0]._self, docs[0], function(err, success) {
if (err) {
return callback(err);
}
callback(null, success);
});
});
}
I was continuously receiving this error: Microsoft.Azure.Documents.DocumentClientException:
Entity with the specified id does not exist in the system.,
The main trick of deleting is PartionKey id. You suppose inside PartionKey provide id
like in the code example.
I have tried many ways, but I was always receiving different errors...Only this solution worked for me.
await client.DeleteDocumentAsync(input[0].SelfLink,
new RequestOptions
{
PartitionKey = new PartitionKey(input[0].Id)
});
Hope this helps :)

Resources