70df29790a
In the current setup users could be tricked into deleting their data by providing a malicious link like `[click me](/me/delete)`. This commit prevents such an easy attack and need the user's deleteToken to get his data deleted. In case someone requests his deletion by email you can also ask him for this token. We can add a GUI that shows it later on. Signed-off-by: Sheogorath <sheogorath@shivering-isles.com>
177 lines
5.2 KiB
JavaScript
177 lines
5.2 KiB
JavaScript
'use strict'
|
|
// external modules
|
|
var md5 = require('blueimp-md5')
|
|
var Sequelize = require('sequelize')
|
|
var scrypt = require('scrypt')
|
|
|
|
// core
|
|
var logger = require('../logger')
|
|
var {generateAvatarURL} = require('../letter-avatars')
|
|
|
|
module.exports = function (sequelize, DataTypes) {
|
|
var User = sequelize.define('User', {
|
|
id: {
|
|
type: DataTypes.UUID,
|
|
primaryKey: true,
|
|
defaultValue: Sequelize.UUIDV4
|
|
},
|
|
profileid: {
|
|
type: DataTypes.STRING,
|
|
unique: true
|
|
},
|
|
profile: {
|
|
type: DataTypes.TEXT
|
|
},
|
|
history: {
|
|
type: DataTypes.TEXT
|
|
},
|
|
accessToken: {
|
|
type: DataTypes.STRING
|
|
},
|
|
refreshToken: {
|
|
type: DataTypes.STRING
|
|
},
|
|
deleteToken: {
|
|
type: DataTypes.UUID,
|
|
defaultValue: Sequelize.UUIDV4
|
|
},
|
|
email: {
|
|
type: Sequelize.TEXT,
|
|
validate: {
|
|
isEmail: true
|
|
}
|
|
},
|
|
password: {
|
|
type: Sequelize.TEXT,
|
|
set: function (value) {
|
|
var hash = scrypt.kdfSync(value, scrypt.paramsSync(0.1)).toString('hex')
|
|
this.setDataValue('password', hash)
|
|
}
|
|
}
|
|
}, {
|
|
instanceMethods: {
|
|
verifyPassword: function (attempt) {
|
|
if (scrypt.verifyKdfSync(new Buffer(this.password, 'hex'), attempt)) {
|
|
return this
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
},
|
|
classMethods: {
|
|
associate: function (models) {
|
|
User.hasMany(models.Note, {
|
|
foreignKey: 'ownerId',
|
|
constraints: false
|
|
})
|
|
User.hasMany(models.Note, {
|
|
foreignKey: 'lastchangeuserId',
|
|
constraints: false
|
|
})
|
|
},
|
|
getProfile: function (user) {
|
|
if (!user) {
|
|
return null
|
|
}
|
|
return user.profile ? User.parseProfile(user.profile) : (user.email ? User.parseProfileByEmail(user.email) : null)
|
|
},
|
|
parseProfile: function (profile) {
|
|
try {
|
|
profile = JSON.parse(profile)
|
|
} catch (err) {
|
|
logger.error(err)
|
|
profile = null
|
|
}
|
|
if (profile) {
|
|
profile = {
|
|
name: profile.displayName || profile.username,
|
|
photo: User.parsePhotoByProfile(profile),
|
|
biggerphoto: User.parsePhotoByProfile(profile, true)
|
|
}
|
|
}
|
|
return profile
|
|
},
|
|
parsePhotoByProfile: function (profile, bigger) {
|
|
var photo = null
|
|
switch (profile.provider) {
|
|
case 'facebook':
|
|
photo = 'https://graph.facebook.com/' + profile.id + '/picture'
|
|
if (bigger) photo += '?width=400'
|
|
else photo += '?width=96'
|
|
break
|
|
case 'twitter':
|
|
photo = 'https://twitter.com/' + profile.username + '/profile_image'
|
|
if (bigger) photo += '?size=original'
|
|
else photo += '?size=bigger'
|
|
break
|
|
case 'github':
|
|
photo = 'https://avatars.githubusercontent.com/u/' + profile.id
|
|
if (bigger) photo += '?s=400'
|
|
else photo += '?s=96'
|
|
break
|
|
case 'gitlab':
|
|
photo = profile.avatarUrl
|
|
if (photo) {
|
|
if (bigger) photo = photo.replace(/(\?s=)\d*$/i, '$1400')
|
|
else photo = photo.replace(/(\?s=)\d*$/i, '$196')
|
|
} else {
|
|
photo = generateAvatarURL(profile.username)
|
|
}
|
|
break
|
|
case 'mattermost':
|
|
photo = profile.avatarUrl
|
|
if (photo) {
|
|
if (bigger) photo = photo.replace(/(\?s=)\d*$/i, '$1400')
|
|
else photo = photo.replace(/(\?s=)\d*$/i, '$196')
|
|
} else {
|
|
photo = generateAvatarURL(profile.username)
|
|
}
|
|
break
|
|
case 'dropbox':
|
|
// no image api provided, use gravatar
|
|
photo = 'https://www.gravatar.com/avatar/' + md5(profile.emails[0].value)
|
|
if (bigger) photo += '?s=400'
|
|
else photo += '?s=96'
|
|
break
|
|
case 'google':
|
|
photo = profile.photos[0].value
|
|
if (bigger) photo = photo.replace(/(\?sz=)\d*$/i, '$1400')
|
|
else photo = photo.replace(/(\?sz=)\d*$/i, '$196')
|
|
break
|
|
case 'ldap':
|
|
// no image api provided,
|
|
// use gravatar if email exists,
|
|
// otherwise generate a letter avatar
|
|
if (profile.emails[0]) {
|
|
photo = 'https://www.gravatar.com/avatar/' + md5(profile.emails[0])
|
|
if (bigger) photo += '?s=400'
|
|
else photo += '?s=96'
|
|
} else {
|
|
photo = generateAvatarURL(profile.username)
|
|
}
|
|
break
|
|
case 'saml':
|
|
if (profile.emails[0]) {
|
|
photo = 'https://www.gravatar.com/avatar/' + md5(profile.emails[0])
|
|
if (bigger) photo += '?s=400'
|
|
else photo += '?s=96'
|
|
} else {
|
|
photo = generateAvatarURL(profile.username)
|
|
}
|
|
break
|
|
}
|
|
return photo
|
|
},
|
|
parseProfileByEmail: function (email) {
|
|
var photoUrl = 'https://www.gravatar.com/avatar/' + md5(email)
|
|
return {
|
|
name: email.substring(0, email.lastIndexOf('@')),
|
|
photo: photoUrl + '?s=96',
|
|
biggerphoto: photoUrl + '?s=400'
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
return User
|
|
}
|