Update docs
This commit is contained in:
parent
e17137d1a8
commit
6608d8ca5b
@ -1,6 +1,6 @@
|
|||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
|
|
||||||
interface Payload {
|
interface EncryptedPayload {
|
||||||
iv: string;
|
iv: string;
|
||||||
cr: string; // Encrypted data
|
cr: string; // Encrypted data
|
||||||
}
|
}
|
||||||
@ -9,7 +9,7 @@ interface Payload {
|
|||||||
const key = crypto.randomBytes(32)
|
const key = crypto.randomBytes(32)
|
||||||
const algorithm = 'aes-256-cbc'
|
const algorithm = 'aes-256-cbc'
|
||||||
|
|
||||||
export function encrypt (text: string): Payload {
|
export function encrypt (text: string): EncryptedPayload {
|
||||||
try {
|
try {
|
||||||
const ivBuf = crypto.randomBytes(16)
|
const ivBuf = crypto.randomBytes(16)
|
||||||
const cipher = crypto.createCipheriv(algorithm, Buffer.from(key), ivBuf)
|
const cipher = crypto.createCipheriv(algorithm, Buffer.from(key), ivBuf)
|
||||||
@ -27,7 +27,7 @@ export function encrypt (text: string): Payload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decrypt (payload: Payload) {
|
export function decrypt (payload: EncryptedPayload) {
|
||||||
try {
|
try {
|
||||||
const decipher = crypto.createDecipheriv(algorithm, Buffer.from(key), Buffer.from(payload.iv, 'hex'))
|
const decipher = crypto.createDecipheriv(algorithm, Buffer.from(key), Buffer.from(payload.iv, 'hex'))
|
||||||
let decrypted = decipher.update(payload.cr, 'hex', 'utf8')
|
let decrypted = decipher.update(payload.cr, 'hex', 'utf8')
|
||||||
|
@ -9,7 +9,7 @@ try {
|
|||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a configuration option using dotted notation.
|
* Get a configuration option fron config.json using dotted notation.
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
* @param [defaultOption] - Specify a default option to return if no configuation value is found
|
* @param [defaultOption] - Specify a default option to return if no configuation value is found
|
||||||
@ -39,6 +39,9 @@ export function getSize (req: Request) {
|
|||||||
return req.query?.size === 'thumbnail' ? ImageSize.thumbnail : ImageSize.original
|
return req.query?.size === 'thumbnail' ? ImageSize.thumbnail : ImageSize.original
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force a value to be a string
|
||||||
|
*/
|
||||||
export function toString (value: unknown) {
|
export function toString (value: unknown) {
|
||||||
return typeof value === 'string' ? value : ''
|
return typeof value === 'string' ? value : ''
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,8 @@ class Immich {
|
|||||||
*/
|
*/
|
||||||
async handleShareRequest (request: IncomingShareRequest, res: Response) {
|
async handleShareRequest (request: IncomingShareRequest, res: Response) {
|
||||||
addResponseHeaders(res)
|
addResponseHeaders(res)
|
||||||
|
// Check that the key is a valid format
|
||||||
if (!immich.isKey(request.key)) {
|
if (!immich.isKey(request.key)) {
|
||||||
// This is not a valid key format
|
|
||||||
log('Invalid share key ' + request.key)
|
log('Invalid share key ' + request.key)
|
||||||
res.status(404).send()
|
res.status(404).send()
|
||||||
} else {
|
} else {
|
||||||
@ -61,13 +61,14 @@ class Immich {
|
|||||||
res.status(401).send()
|
res.status(401).send()
|
||||||
} else if (sharedLinkRes.passwordRequired) {
|
} else if (sharedLinkRes.passwordRequired) {
|
||||||
// Password required - show the visitor the password page
|
// Password required - show the visitor the password page
|
||||||
// `req.params.key` should already be sanitised at this point, but it never hurts to be explicit
|
// `req.params.key` is already sanitised at this point, but it never hurts to be explicit
|
||||||
const key = request.key.replace(/[^\w-]/g, '')
|
const key = request.key.replace(/[^\w-]/g, '')
|
||||||
res.render('password', { key, lgConfig: render.lgConfig })
|
res.render('password', { key, lgConfig: render.lgConfig })
|
||||||
} else if (sharedLinkRes.link) {
|
} else if (sharedLinkRes.link) {
|
||||||
// Valid shared link
|
// Valid shared link
|
||||||
const link = sharedLinkRes.link
|
const link = sharedLinkRes.link
|
||||||
if (!link.assets.length) {
|
if (!link.assets.length) {
|
||||||
|
// Immich didn't return any assets for this link (empty array)
|
||||||
log('No assets for key ' + request.key)
|
log('No assets for key ' + request.key)
|
||||||
res.status(404).send()
|
res.status(404).send()
|
||||||
} else if (link.assets.length === 1) {
|
} else if (link.assets.length === 1) {
|
||||||
@ -105,8 +106,7 @@ class Immich {
|
|||||||
password
|
password
|
||||||
})
|
})
|
||||||
const res = await fetch(url)
|
const res = await fetch(url)
|
||||||
const contentType = res.headers.get('Content-Type') || ''
|
if ((res.headers.get('Content-Type') || '').includes('application/json')) {
|
||||||
if (contentType.includes('application/json')) {
|
|
||||||
const jsonBody = await res.json()
|
const jsonBody = await res.json()
|
||||||
if (jsonBody) {
|
if (jsonBody) {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
@ -20,7 +20,7 @@ class Render {
|
|||||||
const subpath = asset.type === AssetType.video ? '/video/playback' : '/' + size
|
const subpath = asset.type === AssetType.video ? '/video/playback' : '/' + size
|
||||||
const headers = { range: '' }
|
const headers = { range: '' }
|
||||||
|
|
||||||
// Stream the video in 2.5MB chunks
|
// For videos, request them in 2.5MB chunks rather than the entire video
|
||||||
if (asset.type === AssetType.video) {
|
if (asset.type === AssetType.video) {
|
||||||
const range = (req.range || '').replace(/bytes=/, '').split('-')
|
const range = (req.range || '').replace(/bytes=/, '').split('-')
|
||||||
const start = parseInt(range[0], 10) || 0
|
const start = parseInt(range[0], 10) || 0
|
||||||
@ -39,12 +39,12 @@ class Render {
|
|||||||
|
|
||||||
// Return the response to the client
|
// Return the response to the client
|
||||||
if (data.status >= 200 && data.status < 300) {
|
if (data.status >= 200 && data.status < 300) {
|
||||||
// Populate the response headers
|
// Populate the whitelisted response headers
|
||||||
headerList.forEach(header => {
|
headerList.forEach(header => {
|
||||||
const value = data.headers.get(header)
|
const value = data.headers.get(header)
|
||||||
if (value) res.setHeader(header, value)
|
if (value) res.setHeader(header, value)
|
||||||
})
|
})
|
||||||
// Return the body
|
// Return the Immich asset binary data
|
||||||
await data.body?.pipeTo(
|
await data.body?.pipeTo(
|
||||||
new WritableStream({
|
new WritableStream({
|
||||||
write (chunk) { res.write(chunk) }
|
write (chunk) { res.write(chunk) }
|
||||||
|
Loading…
Reference in New Issue
Block a user