Meteor.users collection - meteor

I'm new to meteor and I've reading a lot however I'm a little confused around the meteor.users collection and the best way to use it. My interpretation of the best practice guide is that meteor.users collection should only be used for managing the accounts.ui package; email, password and username. The guide states that profile is insecure, a flaw in the original meteor design and should not be used.
So my question is, if I want to create a user profile that contains things like first name, last name, age, address, avatar etc do I create a separate collection like 'userProfile' and link it using the meteor.userid or am I suppose to keep it in the meteor.users collection somehow

Common practice is to put user profile information such as the kind you're describing into Meteor.user().profile. In fact people often do much more, for example memberships in groups, arrays of postIds, all kinds of things. Keeping a separate 1:1 profile collection is an option but there's no fundamental reason to do so that I can think of. On the contrary it makes things just a bit more complicated.
Update: As #jonatan points out in the comments, the Meteor Guide has now unrecommended the use of the profile field in the user document.
Instead they recommend storing custom user information as top-level keys in the user document. This is not only more secure but also more performant since incremental updates can get published over DDP on top-level keys but on sub-keys.
Meteor.user().profile is always auto-published for the current user even after the autopublish package has been removed. Information about other users is not published at all unless you explicitly setup a publication. In that case care must be taken to only publish those fields that should be visible to other users. For example you may only want to publish the usernames of other users and not their email addresses for privacy. You would do this with:
Meteor.publish('otherUsers',function(){
return Meteor.users.find({},{ fields: { 'profile.username': 1 }});
});
You might also restrict the set of other users that is published based on them being connected in some way to the current user to avoid publishing all users all the time.
You should also avoid publishing the services key which contains security information about the user (ex: the bcrypt of their password). As #David Weldon points out in the comments, you shouldn't put other security information in the profile either and you probably want a deny rule on the user modifying their own profile from the client.

Related

How to make document accessible to changing group of users in FireStore Security Rules

I've been trying to understand the differences of one-to-many and many-to-one relationships in nosql databases. I purchased a few courses on this and Firestone security rules language and have a basic grasp of it all, but I can't think of an efficient way to make a document accessible with a group of people.
I'm trying to implement an application where a user can have a profile and add users to be able to visit the profile/page as well. The only way I know how to do this is to add a field of allowed users to a document and when a user pulls the document down if their ID isn't in that field of permitted users then the profile won't display. I understand this is horribly flawed in that the user was still able to read the document and could rewrite it if permissions aren't set correctly. The only security in this method is hoping that no malicious users no the file path to where documents are stored.
Does anyone know how to properly add a group of users to be able to access a document in firebase?
So far I've implemented UID authentication in Firestone rules to ensure that a user is authenticated, but still any authenticated user can read or write any document in the app I'm demoing around with right now.
I also know you can create custom user types in firebase. This doesn't seem a valid solution for my application since I want to create a custom 'group' for each user that has a profile. Any advice would be greatly appreciated.

Is it possible to shorten firebase auth UIDs?

I've started designing a referral system and wanted to use firebase auth UIDs as the referral code for each user, however they're longer than I'd like and also not guaranteed to stay small. I've looked into some libraries for short text compression, hashing, etc; But none seem to satisfy my needs. I've recently came across the lovely short-uuid pkg on npm but unfortunately it doesn't seem it works with firebase UIDs(because those aren't UUIDs) but i've been looking for a possible solution that doesn't involve keeping a lookup table of custom IDs to UIDs.
So the real question: is there any good way to compress a short string programmatically and then decompress?
There is no way for you to control the UIDs that Firebase Authentication generates in its various providers.
If you want to use a shorter/friendlier scheme for identifying your users, some options are:
You can generate a shorter ID yourself, and maintain a mapping of those IDs to the ones that Firebase generates. You'll typically want to include a uniqueness check for your shorter IDs, as the chances of collisions rapidly go up for the shorter strings.
A common example of a friendlier identifier for users is to allow users to pick a unique username. This is essentially a variant of the first option, but now with a user-selected ID. Here too you will need to perform a check to prevent duplicates.
You can also creating a custom provider that plugs into Firebase Authentication. When doing this, you control the UID that Firebase uses too. Here you are responsible that the UIDs your provider generates are unique not just within your own provider, but across all providers you've enabled for your project.
As #FrankVanPuffelen explained there is no way for you to control the UIDs that Firebase Authentication automatically generates.
But with the createUser() method of the Admin SDK you can define which UID you want to assign to a new user. As explained in the doc, "if you instead want to specify your own UID for the new user, you can include it as an argument passed to the user creation method"
await admin.auth().createUser(
{
uid: 'some-uid',
email: 'user#example.com',
password: '....',
}
);
You can run this code in a Cloud Function or on a server you own.
Of course, you need to ensure that the user's UID is unique for each user.

Flutter: offline local storage syncing with online e.g. firebase

Is this a common/reasonable Use case?
An app allows a user to save favorites locally so that the user doesn't need to signup.
Then the user afterwards desires to share their favorites.
Therefore favorites data needs to be synced from local to remote. The usual local storage for flutter is sqflite, and firebase/store is the remote. However, this seems cumbersome, as sql to nosql conversion is necessary.
I thought that this would be a general issue for UX etc, but I can't find any discussion of this issue? Maybe forcing the user to create an account is the most general solution?
It's a common understanding that if you don't have user account then you can't have any user data associated with your name. You don't have to force the user to have an account or lock them out.
When they favourite something just show a dialog telling them "If you don't have an account your favourites are stored on the device only. If you want your favourites to be available everywhere please create an account" then show options for "Create account" or "No, Thanks"
Create account: Goes to account creation page
No, Thanks: Adds the device to the favourites list and lets the user continue to do what your app does.
There's no problem to solve here from what I'm seeing. If you don't have an account you don't get account functionality. If you track users without them entering anything it's also a little bit illegal and creepy so no need to push the limits on how you can track the same user.
Another way to think of it is to make signup so easy they don't mind and also guarantee that it's worth it. Won't be used for spam or information selling. Take what's app as an example, even though you need to mobile number to send the messages, it's just used as a unique identifier and has nothing to do with the device's number.
Ask for their phone number or email or just any email, you'll most likely get fake info.
And what does your analytics say? Are you getting requests from users saying they lost all their information on a different device? How many people are using your favourite functionality?
I may have come to the party a little late here but here's my 2 cents worth.
The Sql to NoSql conversion is not cumbersome. In fact, there is a reasonable use case for this. I have the same requirement for an app that I am about to build.
Anyway, to store data in RDMDB or NoSQLDB you will need a data model to ensure consistency in your app. If the user has been using the app offline, and they later choose to go online, you can allow them to create the Remote Account, then check if they have local favorites. If they do, you will HAVE to ask them if they'd like to import them into the remote storage. If they choose to do so, you will then have to read their favorites from the local storage and store them in a List<Model> then map() that back to the online storage.
NoSqlDB can accept the json type data, so your model should include the conversion fromMap() and toJson() for this purpose (and others).
When I have come around to doing this, I will share my code (if I remember to come back here).

using Firebase as read only

I'm looking to move my json file to an database service. I've been looking at Firebase-- Firestore in particular.
What the website is, is a collection of recipes.
Users can search for recipes by category. Or they can search by typing in ingredient.
I dont need to have users signing up and logging in.
Its not overly clear to me:
If this service can be used as a 'read only' database to populate the website with what the user selects.
If the database can be secure yet not have users sign up and log in.
Can anyone direct me to documentation/tutorial on the "how to" to have the data itself secured, but available for read only and without needing users to create log-ins.
Thank you,
Lee
Yes
Yes
You need to look into security rules to make sure your public read-only data is actually read only: Just allow read: if true for each collection that you want to give access.

To use or not to use the user module

We are currently transitioning our website to Drupal 6.x from a non Drupal source. One of the first issues we need to deal with is that of authentication. We have a central database where we keep member information. We will create a module to authenticate against this database however a question of whether or not to create users in the drupal is needed.
I'm worried that if we do not add user to the user tables and have our module keep sync that with the other database, then we will not be able to take advantage of other modules that may use the user module
My colleague on the other hand believes that this is not an issue we can add all necessary attributes to the global $user at authentication with our module.
Is there a standard way of dealing with this problem?
Thanks!
David
Look at the LDAP_integration module, they do something similar. When logging in and a local user cannot be loaded, a user is searched for in another application and when user&pass are equal, the user is copied in the Drupal usertable.
If you want any Drupal functionality (read: core and modules) to be associated with that user account, then you will need to use that user table.
This is especially true for anything node-related, so if you want people to be able to create nodes with referenced data you will need it. uids are stored in the nodes table in order to show who authored the node. Storing a uid in the nodes table with a something that doesn't exist as a relational key to somewhere else will only return an empty object. For instance, if a person wants to see the author of X node they will get an empty user object. Keep it. There's no sense in working harder just to remove it. Besides, you can store as little or as much as you want in the user object for each account.
I'd also suggest looking at the LDAP module. I was able to use it as a jumping in point to interface with a custom WSAPI authentication method for an external database that we have at my company.
Do you need to have both sites running in parallel? If not, then you don't need to sync the user tables. A conversion will be enough then.

Resources