mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-31 18:37:00 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			179 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const Logger = require('../../Logger')
 | |
| const { areEquivalent, copyValue, isNullOrNaN } = require('../../utils')
 | |
| 
 | |
| /**
 | |
|  * @typedef EreaderDeviceObject
 | |
|  * @property {string} name
 | |
|  * @property {string} email
 | |
|  * @property {string} availabilityOption
 | |
|  * @property {string[]} users
 | |
|  */
 | |
| 
 | |
| // REF: https://nodemailer.com/smtp/
 | |
| class EmailSettings {
 | |
|   constructor(settings = null) {
 | |
|     this.id = 'email-settings'
 | |
|     this.host = null
 | |
|     this.port = 465
 | |
|     this.secure = true
 | |
|     this.rejectUnauthorized = true
 | |
|     this.user = null
 | |
|     this.pass = null
 | |
|     this.testAddress = null
 | |
|     this.fromAddress = null
 | |
| 
 | |
|     /** @type {EreaderDeviceObject[]} */
 | |
|     this.ereaderDevices = []
 | |
| 
 | |
|     if (settings) {
 | |
|       this.construct(settings)
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   construct(settings) {
 | |
|     this.host = settings.host
 | |
|     this.port = settings.port
 | |
|     this.secure = !!settings.secure
 | |
|     this.rejectUnauthorized = !!settings.rejectUnauthorized
 | |
|     this.user = settings.user
 | |
|     this.pass = settings.pass
 | |
|     this.testAddress = settings.testAddress
 | |
|     this.fromAddress = settings.fromAddress
 | |
|     this.ereaderDevices = settings.ereaderDevices?.map((d) => ({ ...d })) || []
 | |
| 
 | |
|     // rejectUnauthorized added after v2.10.1 - defaults to true
 | |
|     if (settings.rejectUnauthorized === undefined) {
 | |
|       this.rejectUnauthorized = true
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   toJSON() {
 | |
|     return {
 | |
|       id: this.id,
 | |
|       host: this.host,
 | |
|       port: this.port,
 | |
|       secure: this.secure,
 | |
|       rejectUnauthorized: this.rejectUnauthorized,
 | |
|       user: this.user,
 | |
|       pass: this.pass,
 | |
|       testAddress: this.testAddress,
 | |
|       fromAddress: this.fromAddress,
 | |
|       ereaderDevices: this.ereaderDevices.map((d) => ({ ...d }))
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   update(payload) {
 | |
|     if (!payload) return false
 | |
| 
 | |
|     if (payload.port !== undefined) {
 | |
|       if (isNullOrNaN(payload.port)) payload.port = 465
 | |
|       else payload.port = Number(payload.port)
 | |
|     }
 | |
|     if (payload.secure !== undefined) payload.secure = !!payload.secure
 | |
|     if (payload.rejectUnauthorized !== undefined) payload.rejectUnauthorized = !!payload.rejectUnauthorized
 | |
| 
 | |
|     if (payload.ereaderDevices !== undefined && !Array.isArray(payload.ereaderDevices)) payload.ereaderDevices = undefined
 | |
| 
 | |
|     if (payload.ereaderDevices?.length) {
 | |
|       // Validate ereader devices
 | |
|       payload.ereaderDevices = payload.ereaderDevices
 | |
|         .map((device) => {
 | |
|           if (!device.name || !device.email) {
 | |
|             Logger.error(`[EmailSettings] Update ereader device is invalid`, device)
 | |
|             return null
 | |
|           }
 | |
|           if (!device.availabilityOption || !['adminOrUp', 'userOrUp', 'guestOrUp', 'specificUsers'].includes(device.availabilityOption)) {
 | |
|             device.availabilityOption = 'adminOrUp'
 | |
|           }
 | |
|           if (device.availabilityOption === 'specificUsers' && !device.users?.length) {
 | |
|             device.availabilityOption = 'adminOrUp'
 | |
|           }
 | |
|           if (device.availabilityOption !== 'specificUsers' && device.users?.length) {
 | |
|             device.users = []
 | |
|           }
 | |
|           return device
 | |
|         })
 | |
|         .filter((d) => d)
 | |
|     }
 | |
| 
 | |
|     let hasUpdates = false
 | |
| 
 | |
|     const json = this.toJSON()
 | |
|     for (const key in json) {
 | |
|       if (key === 'id') continue
 | |
| 
 | |
|       if (payload[key] !== undefined && !areEquivalent(payload[key], json[key])) {
 | |
|         this[key] = copyValue(payload[key])
 | |
|         hasUpdates = true
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return hasUpdates
 | |
|   }
 | |
| 
 | |
|   getTransportObject() {
 | |
|     const payload = {
 | |
|       host: this.host,
 | |
|       secure: this.secure
 | |
|     }
 | |
|     // Only set to true for port 465 (https://nodemailer.com/smtp/#tls-options)
 | |
|     if (this.port !== 465) {
 | |
|       payload.secure = false
 | |
|     }
 | |
|     if (this.port) payload.port = this.port
 | |
|     if (this.user && this.pass !== undefined) {
 | |
|       payload.auth = {
 | |
|         user: this.user,
 | |
|         pass: this.pass
 | |
|       }
 | |
|     }
 | |
|     // Allow self-signed certs (https://nodemailer.com/smtp/#3-allow-self-signed-certificates)
 | |
|     if (!this.rejectUnauthorized) {
 | |
|       payload.tls = {
 | |
|         rejectUnauthorized: false
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return payload
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    *
 | |
|    * @param {EreaderDeviceObject} device
 | |
|    * @param {import('../user/User')} user
 | |
|    * @returns {boolean}
 | |
|    */
 | |
|   checkUserCanAccessDevice(device, user) {
 | |
|     let deviceAvailability = device.availabilityOption || 'adminOrUp'
 | |
|     if (deviceAvailability === 'adminOrUp' && user.isAdminOrUp) return true
 | |
|     if (deviceAvailability === 'userOrUp' && (user.isAdminOrUp || user.isUser)) return true
 | |
|     if (deviceAvailability === 'guestOrUp') return true
 | |
|     if (deviceAvailability === 'specificUsers') {
 | |
|       let deviceUsers = device.users || []
 | |
|       return deviceUsers.includes(user.id)
 | |
|     }
 | |
|     return false
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Get ereader devices accessible to user
 | |
|    *
 | |
|    * @param {import('../user/User')} user
 | |
|    * @returns {EreaderDeviceObject[]}
 | |
|    */
 | |
|   getEReaderDevices(user) {
 | |
|     return this.ereaderDevices.filter((device) => this.checkUserCanAccessDevice(device, user))
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Get ereader device by name
 | |
|    *
 | |
|    * @param {string} deviceName
 | |
|    * @returns {EreaderDeviceObject}
 | |
|    */
 | |
|   getEReaderDevice(deviceName) {
 | |
|     return this.ereaderDevices.find((d) => d.name === deviceName)
 | |
|   }
 | |
| }
 | |
| module.exports = EmailSettings
 |