Proper place to store CustomerID per user account in Meteor - meteor

I'm using the accounts-ui package which works great. I need to store additional information for each user account. Things like their CustomerID so I can have multiple users associated with the same Customer. Or maybe isAdmin to flag whether they are an admin user for that Customer or just a normal user.
If there is a simple way to facilitate having multiple user accounts with a Customer and I just haven't seen it, please let me know.
From the docs under Accounts, Meteor.users, the most applicable field would be profile but it also says the following:
profile: an Object which (by default) the user can create and update
with any data.
While this is a great place to store things like their first and last name, I would obviously not want the user to be able to modify/update the CustomerID or isAdmin so I'm not sure if this is the best place to store this type of data. Or maybe it is and I should just use a Deny rule so inappropriate users cannot modify this data.
Should I store the CustomerID here or in a separate Customer collection. Or if I'm going about this entirely wrong, I'd appreciate being pointed in the right direction. I noticed the Roles package but that seems to be mostly extending the accounts package and also not storing accounts and roles on a per Customer basis. Also thought about building my own authentication system instead of using accounts-ui which is certainly an option.

Well it's clear you've done your homework. Here are a few suggestions:
If you only have one role type, then the roles package may be overkill.
It is safe to use the profile to store role data only if you add a deny rule for updates (see below) As the docs point out, user profiles are currently editable by default even when then insecure package has been removed. I have been lobbying the core devs to change this - so far to no avail.
I don't know enough about your data to suggest how to model your customer relationships. You could put an id in the profile, as you suggested, or you could have an array of user ids on the customer objects (you could do something similar with the notion of admins for the customer). It mostly depends on how these documents will be updated/queried/published/etc. Generally I prefer to store only user-specific data in the profile (name, preferences, etc.) and keep the relationships in other collections.
In general, I recommend writing your own login UI. It really isn't that hard and in many cases, it's probably a good investment in flexibility for the future.
Meteor.users.deny({
update: function() {
return true;
}
});

Related

Best way to structure related data in firebase/firestore and manage updates?

If I have User and Profile objects. What is the best way to structure my collections in firestore given that the follow scenarios can take place?
Users have a single Profile
Users can update their Profile
Users can save other users' profiles
Users can deleted their saved profiles
The same profile can't be saved twice
If Users and Profiles are separate collections, what is the best way to store saved profiles?
One way that came to mind was that each user has a sub collection called SavedProfiles. The id of each document is the id of the profile. Each saved Profile only contains a reference to the user who's profile it belongs to.
The other option was to do the same thing but store the whole profile of each saved profile.
The benefits of the first approach is that when a user updates their own profile there's no need to update any of the their profiles that have already been saved as it's only the reference that is stored. However, attempting to read a user's saved profiles may require two read operations (which will be quite often), one to get all the references then querying for all the profiles with those reference (if that's even possible???). This seems quite expensive.
The second approach seems like the right way to go as it solves the problem of reading all the saved profiles. But updating multiple saved profiles seems like an issue as each user's saved profiles may be unique. I understand that it's possible to do a batch update but will it be necessary to query each user in the db for their saved profiles and check if that updated profile exists, if so update it? I'm not too sure which way to go. I'm not super used to NoSQL data structures and it already seems like I've done something wrong since I've used a sub collection since it's advised to keep everything as denormalized as possible so please let me know if the structure to my whole db is wrong too, which is also quite possible...
Please provide some examples of how to get and update profiles/saved profiles.
Thank you.
Welcome to the conundrum that is designing a NoSQL database. There is no right or wrong answer, here. It's whatever works best for you.
As you have identified, querying will be much easier with your second option. You can easily create a Cloud Function which updates any profiles which have been modified.
Your first option will require multiple gets to the database. It really depends how you plan to scale this and how quick you want your app to run.
Option 1 will be a slow user experience, while all of the data is fetched. Option 2 will be a much faster user experience, but will requre your Cloud Function to update every saved profile. However, this is a background task so wouldn't matter if it takes a few seconds.

document creator as username or userId

In a meteor collection for a document I have a creator attribute. Is it advisable to store the username (more intuitive) or userId (which is user._id) as creator attribute? What is the more standard practice?
I always join collections by id, and I'd advise you to do the same. The id will never change, but the underlying data may be altered. In this example, if the user changes his/her username then the join would be broken.
With document databases, the answer is commonly, "both".
Storing the userId is required as it is the only field that is guaranteed to not change (as others have pointed out).
It's often worth it to store "denormalized" data as well. In some cases, its actually required.
Take for example a line item on an invoice. It needs to be static, a snapshot in time. You'd need to store the product info at the time of the purchase even though later that product's name or other characteristic may be changed by the vendor.
In our app, there are times when we store user profile info (name, contact info, etc) in addition to the userId. In some cases its strictly for performance reasons, in others its a snapshot used in audit reporting and must not change.
In the performance case, you'll probably want to have processes in place to update the "denormalized" data if it is ever changed in the "source of authority". In the snapshot case, like invoice line-items, you'll want to explicitly not update them. Sometimes, its just ok for the data to be out-of-date and its not worth the complexity of keeping it updated.
For a good example of this kind of "document vs relational" design discussion, check out these two blogs posts:
http://ayende.com/blog/4465/that-no-sql-thing-the-relational-modeling-anti-pattern-in-document-databases
http://ayende.com/blog/4466/that-no-sql-thing-modeling-documents-in-a-document-database
A couple reasons why you would use User._id over a username
User._id's are more URL friendly (no UTF-8, other languages etc.)
User._id is static
Mongo and Minimongo is good at finding and updating Collections with an _id
The best reason to use the _id from the users collection is that all meteor methods and publish functions provide this.userId to identify the user who made the call. That userId is the only information you have about who is making the client request.
If you use username or some other unique field in Meteor.users you will always need to look up the user by id to get the other field.

Using Collcetions in Meteor JS?

My requirement is :
I need to store all the details about a person manually by (for example)Admin.
Which Collection usage is best for above requirement means using Predefined Collection Accounts or User Defined Collection?
My Doubt is : If using Accounts package must be used password but my requirement doesn't contains password only person details.So what i can do for this problem using Accounts?
In case using User Defined Collection then how to provide security for this?
I didn't get any idea about this problem.So please suggest me what to do?
Create a collection, called something like "people", "customers", "students", etc (whatever makes sense for your particular use case). There are several important things you need to do to make it secure:
Use the built in accounts-password package to have your user log in to maintain the list.
Remove the insecure and autopublish packages.
Conditionally publish the relevant fields of the people collection, only to your authorized user.
Set allow and deny rules for inserting/updating/removing people documents. Your rules should check that the user is authorized.
Do not store sensitive information like passwords, credit card numbers, social security numbers, etc in clear text in your database.
Use SSL.
Read and watch these two links, where Emily Stark discusses security (specifically content security policies) in Meteor:
https://www.meteor.com/blog/2013/10/27/defense-in-depth-securing-meteor-apps-with-content-security-policy
https://www.meteor.com/blog/2013/08/02/meteor-devshop-6-devshop-live-security-meteor-ui
Remember that no matter what framework/system you use, there is no such thing as absolute, 100% security. You must use defense in depth to achieve the best possible security that you can.

Best Practices in User Privileges/Session Variables in MVC3

Hi Stack Community Members,
I am developing an application under MVC3 where users have department-specific CRUD privileges. In other words, all users can view data for all departments, but only certain users can make changes to the data for any one given department. User-department privilege data is held in a join table in a database.
What I typically do in this kind of situation (in PHP) is to create a Session variable (an array) on login which is populated with the id's of the departments which the user is allowed to edit. When a user then goes to access the editing feature a drop-down list is populated with only these specific departments. I also populate a few other session variables which are used frequently like the user's name and the id of the current time period (business quarter).
Is this type of approach a good way to go in MVC3, or is some alternative approach better? While I figure that I'm going to use Forms Authentication and some specific roles (employee, admin, etc.) these types of roles are just too broad to be able to target department-by-department access, and I'm not sure that MVC3 has an out-of-the-box method which is better than what I'm planning to do.
Your guidance is appreciated!
I'm using Forms Authentication, add specific roles, and combine them if needed. I don't mind being specific for the roles, as they can be combined anyway I want. I can still have broad roles for more general actions.
I store similar data (UserId, DepartmentId, etc) in session since it does not change for the user and it is a small amount of data. It is my opinion that session state would be a good approach for you also.

Granting a Drupal role to all users that have a certain role

I need to automatically apply a role, Role X, to all Drupal users that have been granted a separate role, Role Y. In other words, I wish for Role X to be a subset of Role Y. How can I do this?
You could implement hook_user() in a custom module. On the 'insert' and/or 'update' action, you'd check for role Y in the $account->roles array. If present, add role X if not already there. This would ensure that your rule gets applied every time a user account gets created and/or changed.
For a bootstrapping/one time operation, take a look at user_multiple_role_edit(). It lets you add or remove roles for an array of user ids. Alternatively, you could do it directly in the database:
INSERT INTO users_roles (uid, rid)
SELECT uid, [roleX_ID] AS rid FROM users_roles
WHERE uid IN
(SELECT uid FROM users_roles WHERE rid = [roleY_ID])
AND uid NOT IN
(SELECT uid FROM users_roles WHERE rid = [roleX_ID])
;
I agree with Henrik Opel on using hook_user in a custom module would be a good solution to maintain the users and make sure they are up to date all the time.
Normally I wouldn't mind writing SQL or something alike, but in this case, since it's on a production site, I would prefer a different route, since if something can easily go wrong when writing raw SQL, a little typo can cause big troubles. Another good point is that you can run into problems as drupal wont be aware of what raw SQL you run on your database and might get out of sync with some processes, hooks and other processes that's normally run when you do things through the Drupal API.
Instead you can use the drupal user admin interface. I actually think that in this case, it is the easiest way to do what you want. Simply filter all users that are students. Click all the users and give them the member role. This is done with a few clicks in no time, and is very secure since Drupal will handle all the SQL for you.
Updated
With that many users, I'm surprised that you don't have a custom user and content managing page setup using views_bulk_operations. Using a few minutes, you can setup a admin page which you can use to preform bulk operations like changing user status, roles, or perform similar tasks for nodes. You can create your own filters using exposed views filters. So with a few clicks you can select all the users with role of student and that isn't member, select them all and add the member roll to them. The advantage doing this is not only that it's quick and safe, but you can create some nice managing pages for your site administrators, content creators etc. You should consider looking into this module.
The LDAP module allows you to dynamically assign roles based on DN. I actually had to write my own module that is tailored specifically to our system, otherwise I would be more than happy to share it.
link text

Resources