release: v0.16.0
See CHANGELOG.md for the full v0.16.0 entry. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: ralksta <ralksta@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Ralf <rohlenbo79@gmail.com> Co-authored-by: Paul Thies <110185070+ImScheinox@users.noreply.github.com> Co-authored-by: lancetm714 <108419425+lancetm714@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
checkProxyHops,
|
||||
countForwardedHops,
|
||||
checkAlbumIds,
|
||||
checkAlbumSlugCollisions,
|
||||
checkAlbumsShared,
|
||||
checkPasswords,
|
||||
checkWritable,
|
||||
@@ -11,6 +12,14 @@ import {
|
||||
worstLevel,
|
||||
} from '../admin/doctor';
|
||||
|
||||
/** A stand-in for lib/config/schema.ts's slugify(), good enough to test the
|
||||
* grouping logic without doctor.ts importing anything (see its own comment). */
|
||||
const testSlug = (name: string) =>
|
||||
name
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/^-+|-+$/g, '');
|
||||
|
||||
describe('checkAuthSecret', () => {
|
||||
it('accepts a long secret', () => {
|
||||
expect(checkAuthSecret('a'.repeat(64)).level).toBe('ok');
|
||||
@@ -94,6 +103,19 @@ describe('checkProxyHops', () => {
|
||||
it('accepts one configured hop against one corroborated entry', () => {
|
||||
expect(checkProxyHops(1, 1, true).level).toBe('ok');
|
||||
});
|
||||
|
||||
/**
|
||||
* Cloudflare (1 hop) in front of nginx (1 more, 2 total) with the value set
|
||||
* to 1 used to report "matches the observed chain" — the client IP was
|
||||
* actually read from the Cloudflare edge address, so every visitor behind
|
||||
* that PoP shared one rate-limit bucket (#629).
|
||||
*/
|
||||
it('warns, not passes, when fewer hops are configured than arrived', () => {
|
||||
const f = checkProxyHops(1, 2, true);
|
||||
expect(f.level).toBe('warn');
|
||||
expect(f.title).toContain('1');
|
||||
expect(f.title).toContain('2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkAlbumIds', () => {
|
||||
@@ -142,6 +164,71 @@ describe('checkAlbumsShared', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkAlbumSlugCollisions', () => {
|
||||
const known = [
|
||||
{ id: 'a', albumName: 'Japan Trip' },
|
||||
{ id: 'b', albumName: 'Japan-Trip' },
|
||||
{ id: 'c', albumName: 'Iceland' },
|
||||
];
|
||||
|
||||
it('is quiet when nothing collides', () => {
|
||||
const f = checkAlbumSlugCollisions(
|
||||
[{ context: 'gallery.yaml albums', albumIds: ['a', 'c'] }],
|
||||
{},
|
||||
known,
|
||||
testSlug,
|
||||
);
|
||||
expect(f.level).toBe('ok');
|
||||
});
|
||||
|
||||
it('flags two albums in the same group whose Immich names slugify alike', () => {
|
||||
const f = checkAlbumSlugCollisions(
|
||||
[{ context: 'gallery.yaml albums', albumIds: ['a', 'b'] }],
|
||||
{},
|
||||
known,
|
||||
testSlug,
|
||||
);
|
||||
expect(f.level).toBe('error');
|
||||
expect(f.detail).toContain('Japan Trip');
|
||||
expect(f.detail).toContain('Japan-Trip');
|
||||
expect(f.albumIds).toEqual(['a', 'b']);
|
||||
});
|
||||
|
||||
it('does not flag the same collision across two different groups', () => {
|
||||
// /trips-a/japan-trip and /trips-b/japan-trip are different URLs.
|
||||
const f = checkAlbumSlugCollisions(
|
||||
[
|
||||
{ context: 'subpage "Trips A"', albumIds: ['a'] },
|
||||
{ context: 'subpage "Trips B"', albumIds: ['b'] },
|
||||
],
|
||||
{},
|
||||
known,
|
||||
testSlug,
|
||||
);
|
||||
expect(f.level).toBe('ok');
|
||||
});
|
||||
|
||||
it('prefers a title override over the Immich name', () => {
|
||||
const f = checkAlbumSlugCollisions(
|
||||
[{ context: 'gallery.yaml albums', albumIds: ['a', 'c'] }],
|
||||
{ c: 'Japan Trip' }, // overrides "Iceland" — now collides with "a"
|
||||
known,
|
||||
testSlug,
|
||||
);
|
||||
expect(f.level).toBe('error');
|
||||
});
|
||||
|
||||
it('says nothing about an id Immich does not know and has no override', () => {
|
||||
const f = checkAlbumSlugCollisions(
|
||||
[{ context: 'gallery.yaml albums', albumIds: ['a', 'ghost'] }],
|
||||
{},
|
||||
known,
|
||||
testSlug,
|
||||
);
|
||||
expect(f.level).toBe('ok');
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkPasswords', () => {
|
||||
it('passes when everything is hashed', () => {
|
||||
expect(checkPasswords([{ label: 'Site', value: 'scrypt:aa:bb' }]).level).toBe('ok');
|
||||
|
||||
Reference in New Issue
Block a user