File: /volume1/@appstore/SynologyPhotos/migration/python/dump_photo_share_permission.py
#!/usr/bin/env python3
from collections import namedtuple
import json
import sys
import pg8000
CONFIG_KEYS = ["allow_user_download", "allow_guest_download"]
USER_PERMISSION_KEYS = ["access", "upload", "manage"]
USER_PERMISSION_TABLE_TEMPLATE = "photo_{}_right_for_dsm_account"
Config = namedtuple("Config", CONFIG_KEYS, defaults=[False] * len(CONFIG_KEYS))
def init_cursor():
user = "postgres"
unix_sock = "/var/run/postgresql/.s.PGSQL.5432"
database = "photo"
conn = pg8000.connect(user, unix_sock=unix_sock, database=database)
cursor = conn.cursor()
cursor.execute("SET CLIENT_ENCODING TO 'UTF8'")
return cursor
def get_config(cursor):
cursor.execute(
"""
SELECT config_key, config_value
FROM photo_config
WHERE config_key IN (%s)
"""
% ",".join(["%s"] * len(CONFIG_KEYS)),
tuple(CONFIG_KEYS),
)
d = {}
for key, value in cursor:
d[key] = True if value == "on" else False
return Config(**d)
def get_user_permission_by_table(cursor, table):
cursor.execute(
"""
SELECT userid, shareid
FROM {}
""".format(
table
)
)
share_map = {}
for uid, id_share in cursor:
share_map.setdefault(id_share, []).append(uid)
return share_map
def get_group_permission(cursor):
cursor.execute(
"""
SELECT groupid, shareid, permission
FROM photo_group_permission_for_dsm_account
"""
)
share_map = {}
for gid, id_share, permission in cursor:
role = ""
if permission & 4 > 0:
role = "manage"
elif permission & 2 > 0:
role = "upload"
elif permission & 1 > 0:
role = "access"
if role:
share_map.setdefault(id_share, {})[gid] = role
return share_map
def get_user_permission(cursor):
share_map = {}
for key in USER_PERMISSION_KEYS:
table = USER_PERMISSION_TABLE_TEMPLATE.format(key)
permissions = get_user_permission_by_table(cursor, table)
for id_share, uids in permissions.items():
for uid in uids:
share_map.setdefault(id_share, {})[uid] = key
return share_map
def get_permission_map(cursor):
config = get_config(cursor)
user_share_map = get_user_permission(cursor)
group_share_map = get_group_permission(cursor)
access_role = "view"
if config.allow_user_download:
access_role = "download"
role_map = {
"manage": "manage",
"upload": "upload",
"access": access_role,
}
permission_map = {}
for id_share in user_share_map:
for uid, role in user_share_map[id_share].items():
permission_map.setdefault(id_share, []).append(
{
"member": {
"type": "user",
"id": uid,
},
"role": role_map[role],
}
)
for id_share in group_share_map:
for gid, role in group_share_map[id_share].items():
permission_map.setdefault(id_share, []).append(
{
"member": {
"type": "group",
"id": gid,
},
"role": role_map[role],
}
)
return permission_map
def get_shares(cursor):
config = get_config(cursor)
public_role = "view"
if config.allow_guest_download:
public_role = "download"
# there is no public-upload in PhotoStation
permission_map = get_permission_map(cursor)
cursor.execute(
"""
SELECT shareid, sharename, public, password
FROM photo_share
WHERE sharename NOT LIKE '%/%/%'
"""
)
folders = []
for id_share, name, is_public, md5ed_password in cursor:
# print(id_share, name, is_public, md5ed_password, is_subdir)
normalized_name = "/{}".format(name) if name != "/" else name
folder_type = "private"
if is_public:
folder_type = "public"
if len(md5ed_password) > 0:
folder_type = "password"
permission = permission_map.get(id_share, [])
if folder_type != "private":
permission.append(
{
"member": {
"type": "public",
},
"role": public_role,
}
)
folder = {
"shareid": id_share,
"sharename": name,
"name": normalized_name,
"type": folder_type,
"permission": permission,
}
if folder_type != "private":
folder["public_role"] = public_role
if folder_type == "password":
folder["md5ed_password"] = md5ed_password
folders.append(folder)
return folders
def get_users(cursor):
users = set()
for key in USER_PERMISSION_KEYS:
table = USER_PERMISSION_TABLE_TEMPLATE.format(key)
cursor.execute(
"""
SELECT DISTINCT(userid)
FROM {}
""".format(
table
)
)
for [uid] in cursor:
users.add(uid)
# convert back to list to be JSON serializable
return list(users)
def get_groups(cursor):
cursor.execute(
"""
SELECT DISTINCT(groupid)
FROM photo_group_permission_for_dsm_account
"""
)
groups = set()
for [gid] in cursor:
groups.add(gid)
# convert back to list to be JSON serializable
return list(groups)
def main():
cursor = init_cursor()
result = {}
result["shares"] = get_shares(cursor)
result["users"] = get_users(cursor)
result["groups"] = get_groups(cursor)
return result
if __name__ == "__main__":
result = main()
if len(sys.argv) >= 2:
path = sys.argv[1]
json.dump(result, open(path, "w"))
else:
print(json.dumps(result))