2017-03-14 05:02:43 +00:00
|
|
|
'use strict'
|
2016-04-20 10:03:55 +00:00
|
|
|
// external modules
|
2017-03-08 10:45:51 +00:00
|
|
|
var Sequelize = require('sequelize')
|
2020-04-08 18:26:25 +00:00
|
|
|
var Scrypt = require('scrypt-kdf')
|
2016-04-20 10:03:55 +00:00
|
|
|
|
|
|
|
// core
|
2017-04-12 16:20:28 +00:00
|
|
|
var logger = require('../logger')
|
2019-04-12 09:58:18 +00:00
|
|
|
var { generateAvatarURL } = require('../letter-avatars')
|
2016-04-20 10:03:55 +00:00
|
|
|
|
|
|
|
module.exports = function (sequelize, DataTypes) {
|
2017-03-08 10:45:51 +00:00
|
|
|
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: {
|
2017-07-10 18:09:59 +00:00
|
|
|
type: DataTypes.TEXT
|
2017-03-08 10:45:51 +00:00
|
|
|
},
|
|
|
|
refreshToken: {
|
2017-07-10 18:09:59 +00:00
|
|
|
type: DataTypes.TEXT
|
2017-03-08 10:45:51 +00:00
|
|
|
},
|
2018-05-25 16:19:31 +00:00
|
|
|
deleteToken: {
|
|
|
|
type: DataTypes.UUID,
|
|
|
|
defaultValue: Sequelize.UUIDV4
|
|
|
|
},
|
2017-03-08 10:45:51 +00:00
|
|
|
email: {
|
|
|
|
type: Sequelize.TEXT,
|
|
|
|
validate: {
|
|
|
|
isEmail: true
|
|
|
|
}
|
|
|
|
},
|
|
|
|
password: {
|
2020-04-08 18:26:25 +00:00
|
|
|
type: Sequelize.TEXT
|
2017-03-08 10:45:51 +00:00
|
|
|
}
|
2019-04-12 04:05:32 +00:00
|
|
|
})
|
|
|
|
|
2020-04-08 18:42:48 +00:00
|
|
|
User.hashPassword = async function (plain) {
|
|
|
|
return (await Scrypt.kdf(plain, await Scrypt.pickParams(0.1))).toString('hex')
|
2020-04-08 18:26:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
User.prototype.verifyPassword = async function (attempt) {
|
2020-04-08 18:42:48 +00:00
|
|
|
if (await Scrypt.verify(Buffer.from(this.password, 'hex'), attempt)) {
|
2019-04-12 04:05:32 +00:00
|
|
|
return this
|
|
|
|
}
|
2020-04-08 18:26:25 +00:00
|
|
|
|
|
|
|
return false
|
2019-04-12 04:05:32 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 15:15:26 +00:00
|
|
|
User.addHook('beforeCreate', async function (user) {
|
|
|
|
// only do hash when password is presented
|
|
|
|
if (user.password) {
|
|
|
|
user.password = await User.hashPassword(user.password)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
User.addHook('beforeUpdate', async function (user) {
|
|
|
|
if (user.changed('password')) {
|
|
|
|
user.password = await User.hashPassword(user.password)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2019-04-12 04:05:32 +00:00
|
|
|
User.associate = function (models) {
|
|
|
|
User.hasMany(models.Note, {
|
|
|
|
foreignKey: 'ownerId',
|
|
|
|
constraints: false
|
|
|
|
})
|
|
|
|
User.hasMany(models.Note, {
|
|
|
|
foreignKey: 'lastchangeuserId',
|
|
|
|
constraints: false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
User.getProfile = function (user) {
|
|
|
|
if (!user) {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
return user.profile ? User.parseProfile(user.profile) : (user.email ? User.parseProfileByEmail(user.email) : null)
|
|
|
|
}
|
|
|
|
User.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)
|
2017-03-08 10:45:51 +00:00
|
|
|
}
|
2019-04-12 04:05:32 +00:00
|
|
|
}
|
|
|
|
return profile
|
|
|
|
}
|
|
|
|
User.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':
|
2020-04-20 11:18:25 +00:00
|
|
|
const photoURL = new URL(profile.photos && profile.photos[0]
|
|
|
|
? profile.photos[0].value
|
|
|
|
: `https://avatars.githubusercontent.com/u/${profile.id}`)
|
|
|
|
photoURL.searchParams.set('s', bigger ? 400 : 96)
|
|
|
|
photo = photoURL.toString()
|
2019-04-12 04:05:32 +00:00
|
|
|
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)
|
2017-03-08 10:45:51 +00:00
|
|
|
}
|
2019-04-12 04:05:32 +00:00
|
|
|
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)
|
2016-04-20 10:03:55 +00:00
|
|
|
}
|
2019-04-12 04:05:32 +00:00
|
|
|
break
|
|
|
|
case 'dropbox':
|
|
|
|
photo = generateAvatarURL('', profile.emails[0].value, bigger)
|
|
|
|
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':
|
|
|
|
photo = generateAvatarURL(profile.username, profile.emails[0], bigger)
|
|
|
|
break
|
|
|
|
case 'saml':
|
|
|
|
photo = generateAvatarURL(profile.username, profile.emails[0], bigger)
|
|
|
|
break
|
2020-03-12 05:39:27 +00:00
|
|
|
case 'oauth2':
|
|
|
|
photo = profile.photo
|
|
|
|
if (!photo) photo = generateAvatarURL(profile.username, profile.email, bigger)
|
|
|
|
break
|
2017-03-08 10:45:51 +00:00
|
|
|
}
|
2019-04-12 04:05:32 +00:00
|
|
|
return photo
|
|
|
|
}
|
|
|
|
User.parseProfileByEmail = function (email) {
|
|
|
|
return {
|
|
|
|
name: email.substring(0, email.lastIndexOf('@')),
|
|
|
|
photo: generateAvatarURL('', email, false),
|
|
|
|
biggerphoto: generateAvatarURL('', email, true)
|
|
|
|
}
|
|
|
|
}
|
2016-05-11 21:04:45 +00:00
|
|
|
|
2017-03-08 10:45:51 +00:00
|
|
|
return User
|
|
|
|
}
|