Vulcan/packages/telescope-users/lib/users.js

306 lines
6.2 KiB
JavaScript
Raw Normal View History

/**
* Vote schema
* @type {SimpleSchema}
*/
Telescope.schemas.votes = new SimpleSchema({
itemId: {
type: String
},
power: {
type: Number,
optional: true
},
votedAt: {
type: Date,
optional: true
}
});
/**
* User Data schema
* @type {SimpleSchema}
*/
Telescope.schemas.userData = new SimpleSchema({
2015-05-11 11:46:18 +09:00
/**
Bio (Markdown version)
*/
bio: {
type: String,
optional: true,
editableBy: ["member", "admin"],
autoform: {
rows: 5
}
},
2015-05-11 11:46:18 +09:00
/**
Total comment count
*/
commentCount: {
type: Number,
public: true,
optional: true
},
2015-05-11 11:46:18 +09:00
/**
The name displayed throughout the app. Can contain spaces and special characters, doesn't need to be unique
*/
displayName: {
type: String,
optional: true,
2015-05-16 12:05:53 +09:00
public: true,
profile: true,
editableBy: ["member", "admin"]
},
2015-05-11 11:46:18 +09:00
/**
An array containing comment downvotes
*/
downvotedComments: {
type: [Telescope.schemas.votes],
public: true,
optional: true
},
2015-05-11 11:46:18 +09:00
/**
An array containing posts downvotes
*/
downvotedPosts: {
type: [Telescope.schemas.votes],
public: true,
optional: true
},
2015-05-11 11:46:18 +09:00
/**
The user's email. Modifiable.
2015-05-11 11:46:18 +09:00
*/
email: {
type: String,
optional: true,
regEx: SimpleSchema.RegEx.Email,
required: true,
editableBy: ["member", "admin"]
// unique: true // note: find a way to fix duplicate accounts before enabling this
},
2015-05-11 11:46:18 +09:00
/**
A hash of the email, used for Gravatar // TODO: change this when email changes
*/
emailHash: {
type: String,
public: true,
optional: true
},
2015-05-11 11:46:18 +09:00
/**
The HTML version of the bio field
*/
htmlBio: {
type: String,
2015-05-16 12:05:53 +09:00
public: true,
profile: true,
optional: true,
autoform: {
omit: true
},
template: "user_profile_bio"
},
2015-05-11 11:46:18 +09:00
/**
The user's karma
*/
karma: {
type: Number,
2015-05-11 11:09:26 +09:00
decimal: true,
public: true,
optional: true
},
2015-05-11 11:46:18 +09:00
/**
Total post count
*/
postCount: {
type: Number,
public: true,
optional: true
},
2015-05-11 11:46:18 +09:00
/**
A blackbox modifiable object to store the user's settings
*/
2015-05-11 11:09:26 +09:00
settings: {
type: Object,
optional: true,
editableBy: ["member", "admin"],
2015-05-11 18:20:05 +09:00
blackbox: true,
autoform: {
omit: true
}
2015-05-11 11:09:26 +09:00
},
2015-05-11 11:46:18 +09:00
/**
The user's profile URL slug // TODO: change this when displayName changes
*/
slug: {
type: String,
public: true,
optional: true
},
2015-05-11 11:46:18 +09:00
/**
The user's Twitter username
*/
twitterUsername: {
type: String,
optional: true,
2015-05-16 12:05:53 +09:00
public: true,
profile: true,
editableBy: ["member", "admin"],
template: "user_profile_twitter"
},
2015-05-11 11:46:18 +09:00
/**
An array containing comments upvotes
*/
upvotedComments: {
type: [Telescope.schemas.votes],
public: true,
optional: true
},
2015-05-11 11:46:18 +09:00
/**
An array containing posts upvotes
*/
upvotedPosts: {
type: [Telescope.schemas.votes],
public: true,
optional: true
},
2015-05-11 11:46:18 +09:00
/**
A link to the user's homepage
*/
website: {
type: String,
regEx: SimpleSchema.RegEx.Url,
2015-05-16 12:05:53 +09:00
public: true,
profile: true,
optional: true,
editableBy: ["member", "admin"]
}
});
/**
* Users schema
* @type {SimpleSchema}
*/
2015-05-11 12:15:10 +09:00
Users.schema = new SimpleSchema({
_id: {
type: String,
public: true,
optional: true
},
username: {
type: String,
regEx: /^[a-z0-9A-Z_]{3,15}$/,
public: true,
optional: true
},
emails: {
type: [Object],
optional: true
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email,
optional: true
},
"emails.$.verified": {
type: Boolean,
optional: true
},
createdAt: {
type: Date,
public: true,
optional: true
},
isAdmin: {
type: Boolean,
2015-05-17 12:08:08 +09:00
optional: true,
editableBy: ["admin"],
autoform: {
omit: true
}
},
profile: {
type: Object,
optional: true,
blackbox: true
},
telescope: { // telescope-specific data
type: Telescope.schemas.userData,
optional: true
},
services: {
type: Object,
optional: true,
blackbox: true
}
});
2015-05-11 12:15:10 +09:00
Users.schema.internationalize();
/**
* Attach schema to Meteor.users collection
*/
2015-05-11 12:15:10 +09:00
Users.attachSchema(Users.schema);
/**
* Users collection permissions
*/
Users.allow({
update: _.partial(Telescope.allowCheck, Meteor.users),
remove: _.partial(Telescope.allowCheck, Meteor.users)
2015-05-03 13:09:57 -04:00
});
//////////////////////////////////////////////////////
// Collection Hooks //
// https://atmospherejs.com/matb33/collection-hooks //
//////////////////////////////////////////////////////
/**
* Generate HTML body from Markdown on user bio insert
*/
Users.after.insert(function (userId, user) {
// run create user async callbacks
2015-05-19 15:17:27 +09:00
Telescope.callbacks.runAsync("onCreateUserAsync", user);
// check if all required fields have been filled in. If so, run profile completion callbacks
if (Users.hasCompletedProfile(user)) {
Telescope.callbacks.runAsync("profileCompletedAsync", user);
}
});
/**
* Generate HTML body from Markdown when user bio is updated
*/
Users.before.update(function (userId, doc, fieldNames, modifier) {
// if bio is being modified, update htmlBio too
if (Meteor.isServer && modifier.$set && modifier.$set["telescope.bio"]) {
modifier.$set["telescope.htmlBio"] = Telescope.utils.sanitize(marked(modifier.$set["telescope.bio"]));
}
});
2015-05-16 13:13:45 +09:00
/**
* If user.telescope.email has changed, check for existing emails and change user.emails if needed
2015-05-16 13:13:45 +09:00
*/
if (Meteor.isServer) {
Users.before.update(function (userId, doc, fieldNames, modifier) {
var user = doc;
// if email is being modified, update user.emails too
if (Meteor.isServer && modifier.$set && modifier.$set["telescope.email"]) {
var newEmail = modifier.$set["telescope.email"];
// check for existing emails and throw error if necessary
var userWithSameEmail = Users.findByEmail(newEmail);
if (userWithSameEmail && userWithSameEmail._id !== doc._id) {
throw new Meteor.Error("email_taken2", i18n.t("this_email_is_already_taken") + " (" + newEmail + ")");
}
// if user.emails exists, change it too
if (!!user.emails) {
user.emails[0].address = newEmail;
modifier.$set.emails = user.emails;
}
}
});
}