I am building an application that has two types of users. Professional users and their clients. The account types are completely distinct with no overlap. So, emails registered as Pro could still be used to register as a Client, and if a Pro user tried to log in using the client form, their account would not exist.
The problem:
Meteor automatically prevents duplicate emails from being used when creating user accounts. My thought was to use a custom validation to allow the behavior and essentially create two different sets of users. Here is an example of the validation I tried for a 'Pro' user.
Accounts.onCreateUser(function(options, user) {
var email = user.email;
if (Meteor.users.find({emails: email, isPro : true}).count() > 0) {
throw new Meteor.Error(403, "This email address is already registered");
}
user.isPro = true;
return user;
});
But meteor still uses its default duplicate email rejection instead. Any ideas on how I can override this behavior, or is there a better way to create two distinct sets of users?
You can do this in a mongo shell
db.users.dropIndex('emails.address_1');
Doing this is probably not the best idea and may have unintended consequences. I too think the solution discussed in the comments would be better.
Related
I have created a chat message functionality. The message stores the userid of sender and receiver. How can I get other details of the user just based on the userid?
Is creating a Meteor method the best way or I have to create publish/subscribe pattern for it.
I want to avoid sending all users data to client side.
I tried creating a meteor method but I don't think its the best approach.
Meteor.methods({
getUserInfoById: function (usrId) {
//console.log("BEGIN");
//console.log(usrId);
var user = Meteor.users.findOne(usrId);
//console.log(user);
//console.log("END");
return user;
}
});
Create a publisher (and also a subscriber) for the data about other users that you want a given user to see. You can restrict the fields returned using the {fields: ...} qualifier in the query.
This is a very common pattern. Using a method for this is an anti-pattern due to the extra round-trip delay for something you're likely to show quite often, i.e. another user's username or avatar.
I'm working on an application where only the admin should be able to create users for the system; meaning the user is restricted from creating an account but can login if login credentials were made for him/her.
I'm thinking about using houston:admin to manually create users, but how can I restrict users from creating an account using accounts-ui?
Should I use different packages to achieve this altogether?
You have several ways to prevent users from creating accounts:
throwing an error in the Accounts.onCreateUser() callback (server only):
Accounts.onCreateUser(function(options, user) {
if (/* some logic to figure out if current user is an admin */) {
return user;
}
throw new Meteor.Error("user creation disabled.");
});
This will prevent the account from being created if the current user is not an admin.
configuring Accounts to forbid account creation (both client and server):
Accounts.config({
forbidClientAccountCreation: true
});
which rejects calls to createUser() from the client (but will not prevent user creation using oAuth services).
A combination of both is a likely course of action.
Take a look at the linked documentation for more details.
I want to use AutoForm to create a register form which subsequetnly creates users. Furtehremore, new users should be signed in automatically after registering.
Therefore, I created an AutoForm and supplied a meteormethod called signUp:
Meteor.methods({
signUp: function (doc) {
check(doc, Schema.signUp);
Accounts.createUser({username: doc.username, password: doc.password});
}
});
This works perfect. However, I don't know how I can login users from server side? Is this even possible?
If not, how can I solve this issue? Do I need to include Accounts.createUser({username: doc.username, password: doc.password}); in my Schema custom validation function?
To use aldeed:autoform with any collection, you first need to define schema to that collection because autoform relies on simple-schema attached to that collection. Without schema, the form won't appear and you'll see an uncaught exception thrown by autoform.
So at first, you need to define schema. After that, it's possible to update or insert users into Meteor.users collection. See the official docs for the typical plain-object structure of a users collection entity, at first you may just console.log currently authenticated Meteor.user() to see what required fields it has.
My personal advice would be to not use autoform to mess around with users. It's not very secure and you need to explicitly control what users (or roles) can CRUD your users and what users do not. That's just extra pain to solve, and it may simply negate the convenience of autoform.
I'm using Firebase 2.x. If I enable email/password security, how do I prevent a malicious pre-existing user from writing their own javascript code that would do authenticate with my Firebase and then launch a createUser attack? Hypothetically, it might look like this:
var ref = new Firebase(my_fire_base);
ref.authWithPassword({ email : 'pre#existing.com', password: 'validpassword' },
function(error, authData) {
if (!error) {
ref.createUser( ... ); // do this a bunch of times
}
});
Since this question was cross-posted to Google Groups, I'll quote the answer that was given there:
You do not need to be authenticated to call createUser(). This is by design and how all registration systems work. It is possible for a malicious client to call createUser() a gazillion times, but this is where we build rate limiting into the service we provide and prevent people from doing this. You cannot restrict by specific origins, and even if you could, as you mentioned, this can be easily spoofed.
I'm building a Meteor app for contracts. A signed in user can create a contract. But I'd like for them to be able to send a contract to another party, who can view the contract without signing up or creating an account. The problem is that, even if the URL is long and random, www.example.com/docs/bM7GjrRq1wABYdxws3 -- I'm not sure it is private enough -- because maybe all these contracts could be easily crawled or end up in search like this.
I'd like the creator of the contract to set a password that can be emailed to the other party along with the link to the contract. Before the party can view the contract, they need to enter the password.
My solution is to allow a user to password protect the page (but without a username/email). But I'm not sure how to do it. How can I password protect a page with a password set by a user?
You could save password within the page object on mongodb.
Then when he creates or edit the page, he might choose to share publicly or with password.
The publish method could look somewhat like this.
Meteor.publish("page", function (){
if (!this.userId) {
return Pages.find({
_id: Session.get("pageId"),
private: true,
password: Session.get("pagePassword")
});
} else {
// code for logged in users
}
});
Of course it's a good idea to store a hash for the password and compare to the hash the user entered, instead of storing the raw password.