immich: share albums that kaderleden create automatically

Nobody uses the group account anymore, so new albums belong to the
leiding who make them, and share-sync only shared albums the group
account was in. It now first adds the group account as editor to every
album an uploader owns (straight in the database: the API only lets an
album's owner or editors share it), after which the album goes to
everyone like the others. Albums whose name starts with "Privé" or
"Prive" are left alone.
This commit is contained in:
Ruben Hensen committed 2026-10-24 14:10:30 +02:00
1 parent f69b790a58
commit 88f68cd698
1 file changed
+36 -2
+36 -2
View File
@@ -1,5 +1,7 @@
# Shares the Scouting MBG photos with every immich user. immich has no user # Shares the Scouting MBG photos with every immich user. immich has no user
# groups (on its roadmap as "Soon"), so this does it per user: # groups (on its roadmap as "Soon"), so this does it per user:
# - albums that uploaders (kaderleden) create get the group account as
# editor, unless their name starts with "Privé" or "Prive";
# - every album the group account owns or edits gets every user, as editor # - every album the group account owns or edits gets every user, as editor
# when they may upload (quota other than 0, which authentik sets from # when they may upload (quota other than 0, which authentik sets from
# Scouts Online) and as viewer otherwise; # Scouts Online) and as viewer otherwise;
@@ -11,8 +13,9 @@
# - sessions of OAuth users older than SESSION_MAX_AGE_DAYS are ended, so # - sessions of OAuth users older than SESSION_MAX_AGE_DAYS are ended, so
# someone who left the group loses access at the next login at Scouts # someone who left the group loses access at the next login at Scouts
# Online. # Online.
# Albums and partners go through the API; the timeline flag (which only # Albums and partners go through the API. Joining other people's albums
# the receiving user can set through the API), the notifications and the # (the API only lets an album's owner or editors share it), the timeline
# flag (which only the receiving user can set), the notifications and the
# sessions go straight to the database. # sessions go straight to the database.
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
@@ -69,6 +72,34 @@ data:
# says: no uploads. # says: no uploads.
wanted = {u[0]: "viewer" if u[3] == "0" else "editor" for u in users if u[0] in members} wanted = {u[0]: "viewer" if u[3] == "0" else "editor" for u in users if u[0] in members}
# Albums of uploaders that the group account isn't in yet
UNJOINED = """
FROM album_user au
JOIN "user" u ON u.id = au."userId"
JOIN album a ON a.id = au."albumId"
WHERE au.role = 'owner' AND u.id != :'group'
AND u."deletedAt" IS NULL AND a."deletedAt" IS NULL
AND (u."quotaSizeInBytes" IS NULL OR u."quotaSizeInBytes" > 0)
AND a."albumName" !~* '^\\s*priv[eé]'
AND NOT EXISTS (SELECT 1 FROM album_user g WHERE g."albumId" = a.id AND g."userId" = :'group')
"""
if DRY_RUN:
for (name,) in sql("SELECT a.\"albumName\"" + UNJOINED, group=group_id):
print(f"would join {name}", flush=True)
else:
for (name,) in sql(
f"""
WITH joined AS (
INSERT INTO album_user ("albumId", "userId", role)
SELECT a.id, :'group', 'editor' {UNJOINED}
RETURNING "albumId"
)
SELECT a."albumName" FROM joined JOIN album a ON a.id = joined."albumId"
""",
group=group_id,
):
print(f"join {name}", flush=True)
for album in api("GET", "/albums"): for album in api("GET", "/albums"):
roles = {au["user"]["id"]: au["role"] for au in album["albumUsers"]} roles = {au["user"]["id"]: au["role"] for au in album["albumUsers"]}
if roles.get(group_id) not in ("owner", "editor"): if roles.get(group_id) not in ("owner", "editor"):
@@ -181,6 +212,9 @@ spec:
value: immich-postgres-17-rw value: immich-postgres-17-rw
- name: PGSSLMODE - name: PGSSLMODE
value: require value: require
# album names are UTF-8 (and so is the Privé check)
- name: PGCLIENTENCODING
value: UTF8
- name: PGDATABASE - name: PGDATABASE
value: immich value: immich
- name: PGUSER - name: PGUSER