fix
This commit is contained in:
@@ -14,129 +14,134 @@ def getenv(name):
|
||||
print(f"[ERROR] Missing environment variable {name}. You should NOT run this script by hand, please use systemd mastodon-kanidm-sync.service.")
|
||||
exit(1)
|
||||
|
||||
|
||||
# Import configuration
|
||||
KANIDM_URL = getenv("KANIDM_URL")
|
||||
KANIDM_TOKEN = read_file(getenv("KANIDM_TOKEN_PATH")).strip()
|
||||
OWNER_USERNAME = getenv("OWNER_USERNAME")
|
||||
SLEEP_TIME = int(getenv("SLEEP_TIME"))
|
||||
|
||||
# Fetch kanidm users list from userdata file
|
||||
# Userdata file is json list with information about what users are configured by kanidm
|
||||
try:
|
||||
USERDATA = read_file(getenv("USERDATA_FILE_PATH")).strip()
|
||||
userdata = json.loads(USERDATA)
|
||||
print("[INFO] ")
|
||||
except FileNotFoundError:
|
||||
userdata = []
|
||||
def sync_mastodon():
|
||||
# Fetch kanidm users list from userdata file
|
||||
# Userdata file is json list with information about what users are configured by kanidm
|
||||
try:
|
||||
USERDATA = read_file(getenv("USERDATA_FILE_PATH")).strip()
|
||||
userdata = json.loads(USERDATA)
|
||||
print("[INFO] ")
|
||||
except FileNotFoundError:
|
||||
userdata = []
|
||||
|
||||
# Load database
|
||||
conn = ps.connect(
|
||||
dbname=getenv("POSTGRES_DBNAME"),
|
||||
user=getenv("POSTGRES_USER"),
|
||||
host=getenv("POSTGRES_HOST")
|
||||
)
|
||||
# Load database
|
||||
conn = ps.connect(
|
||||
dbname=getenv("POSTGRES_DBNAME"),
|
||||
user=getenv("POSTGRES_USER"),
|
||||
host=getenv("POSTGRES_HOST")
|
||||
)
|
||||
|
||||
# Fetch current userdata from database
|
||||
cur = conn.cursor()
|
||||
cur.execute('''
|
||||
SELECT identities.uid, users.id, user_roles.name
|
||||
FROM users
|
||||
JOIN identities
|
||||
ON users.id = identities.id
|
||||
LEFT JOIN user_roles
|
||||
ON users.role_id = user_roles.id;
|
||||
'''
|
||||
)
|
||||
# Fetch current userdata from database
|
||||
cur = conn.cursor()
|
||||
cur.execute('''
|
||||
SELECT identities.uid, users.id, user_roles.name
|
||||
FROM users
|
||||
JOIN identities
|
||||
ON users.id = identities.id
|
||||
LEFT JOIN user_roles
|
||||
ON users.role_id = user_roles.id;
|
||||
'''
|
||||
)
|
||||
|
||||
state = cur.fetchall()
|
||||
state = cur.fetchall()
|
||||
|
||||
users = {}
|
||||
for i in state:
|
||||
users[i[0]] = {
|
||||
"id": i[1],
|
||||
"role": i[2],
|
||||
"isKanidmUser": False
|
||||
}
|
||||
users = {}
|
||||
for i in state:
|
||||
users[i[0]] = {
|
||||
"id": i[1],
|
||||
"role": i[2],
|
||||
"isKanidmUser": False
|
||||
}
|
||||
|
||||
# Fetch Kanidm userdata
|
||||
kanidm_users_raw = requests.get(
|
||||
f"{KANIDM_URL}/v1/person",
|
||||
headers={
|
||||
"Authorization": f"Bearer {KANIDM_TOKEN}",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
timeout=5,
|
||||
).json()
|
||||
# Fetch Kanidm userdata
|
||||
kanidm_users_raw = requests.get(
|
||||
f"{KANIDM_URL}/v1/person",
|
||||
headers={
|
||||
"Authorization": f"Bearer {KANIDM_TOKEN}",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
timeout=5,
|
||||
).json()
|
||||
|
||||
def give_role(uid, role, putUserdata = True):
|
||||
if (uid not in userdata) and (putUserdata):
|
||||
userdata.append(uid)
|
||||
users[uid]["isKanidmUser"] = True
|
||||
users[uid]["role"] = role
|
||||
print(f"[INFO] {uid} is marked as {role}")
|
||||
def give_role(uid, role, putUserdata = True):
|
||||
if (uid not in userdata) and (putUserdata):
|
||||
userdata.append(uid)
|
||||
users[uid]["isKanidmUser"] = True
|
||||
users[uid]["role"] = role
|
||||
print(f"[INFO] {uid} is marked as {role}")
|
||||
|
||||
|
||||
for i in kanidm_users_raw:
|
||||
i = i["attrs"]
|
||||
for uid in i["name"]: # [user].attrs.name is a list
|
||||
if uid in users: # Don't apply anything for users who have no mastodon access (sp.mastodon.users) or didn't register
|
||||
if uid == OWNER_USERNAME:
|
||||
give_role(uid, "Owner", False)
|
||||
for i in kanidm_users_raw:
|
||||
i = i["attrs"]
|
||||
for uid in i["name"]: # [user].attrs.name is a list
|
||||
if uid in users: # Don't apply anything for users who have no mastodon access (sp.mastodon.users) or didn't register
|
||||
if uid == OWNER_USERNAME:
|
||||
give_role(uid, "Owner", False)
|
||||
continue
|
||||
|
||||
for group in i["memberof"]:
|
||||
if group.startswith("sp.mastodon.admins@") or group.startswith("sp.admins@"):
|
||||
give_role(uid, "Admin")
|
||||
break
|
||||
|
||||
elif group.startswith("sp.mastodon.moderators@"):
|
||||
give_role(uid, "Moderator")
|
||||
break
|
||||
|
||||
elif uid in userdata:
|
||||
# If user, who previously had a role, has no roles set by Kanidm, delete them from userdata list so allow setting roles directly by mastodon
|
||||
give_role(uid, None, False)
|
||||
userdata.remove(uid)
|
||||
|
||||
print("[DEBUG]", users)
|
||||
|
||||
# Fetch RoleIDs
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT id, name FROM user_roles;")
|
||||
|
||||
roles_raw = cur.fetchall()
|
||||
roles = {}
|
||||
for i in roles_raw:
|
||||
roles[i[1]] = i[0]
|
||||
|
||||
# Give roles
|
||||
for uid in users:
|
||||
if not users[uid]["isKanidmUser"]:
|
||||
continue
|
||||
|
||||
for group in i["memberof"]:
|
||||
if group.startswith("sp.mastodon.admins@") or group.startswith("sp.admins@"):
|
||||
give_role(uid, "Admin")
|
||||
break
|
||||
if users[uid]["role"]:
|
||||
rolename = users[uid]["role"]
|
||||
roleid = roles[rolename]
|
||||
else:
|
||||
roleid = "NULL"
|
||||
|
||||
elif group.startswith("sp.mastodon.moderators@"):
|
||||
give_role(uid, "Moderator")
|
||||
break
|
||||
sqlcommand = f"UPDATE users SET role_id = {roleid} WHERE id = {users[uid]["id"]};"
|
||||
print("[DEBUG] SQL:", sqlcommand)
|
||||
cur.execute(sqlcommand)
|
||||
|
||||
elif uid in userdata:
|
||||
# If user, who previously had a role, has no roles set by Kanidm, delete them from userdata list so allow setting roles directly by mastodon
|
||||
give_role(uid, None, False)
|
||||
userdata.remove(uid)
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
print("[DEBUG]", users)
|
||||
print("[INFO] Final userdata.json file content: ", userdata)
|
||||
|
||||
# Fetch RoleIDs
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT id, name FROM user_roles;")
|
||||
def write_userdata(mode):
|
||||
with open(getenv("USERDATA_FILE_PATH"), mode) as f:
|
||||
f.write(json.dumps(userdata))
|
||||
f.close()
|
||||
|
||||
roles_raw = cur.fetchall()
|
||||
roles = {}
|
||||
for i in roles_raw:
|
||||
roles[i[1]] = i[0]
|
||||
try:
|
||||
write_userdata("w")
|
||||
except FileNotFoundError:
|
||||
print("[INFO] userdata.json file doesn't exist. Creating it")
|
||||
write_userdata("x")
|
||||
|
||||
# Give roles
|
||||
for uid in users:
|
||||
if not users[uid]["isKanidmUser"]:
|
||||
continue
|
||||
|
||||
if users[uid]["role"]:
|
||||
rolename = users[uid]["role"]
|
||||
roleid = roles[rolename]
|
||||
else:
|
||||
roleid = "NULL"
|
||||
|
||||
sqlcommand = f"UPDATE users SET role_id = {roleid} WHERE id = {users[uid]["id"]};"
|
||||
print("[DEBUG] SQL:", sqlcommand)
|
||||
cur.execute(sqlcommand)
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
print("[INFO] Final userdata.json file content: ", userdata)
|
||||
|
||||
def write_userdata(mode):
|
||||
with open(getenv("USERDATA_FILE_PATH"), mode) as f:
|
||||
f.write(json.dumps(userdata))
|
||||
f.close()
|
||||
|
||||
try:
|
||||
write_userdata("w")
|
||||
except FileNotFoundError:
|
||||
print("[INFO] userdata.json file doesn't exist. Creating it")
|
||||
write_userdata("x")
|
||||
while True:
|
||||
sync_mastodon()
|
||||
time.sleep(SLEEP_TIME)
|
||||
|
14
module.nix
14
module.nix
@@ -91,7 +91,7 @@ in
|
||||
enableUnixSocket = false;
|
||||
configureNginx = true;
|
||||
database.createLocally = true;
|
||||
streamingProcesses = 3;
|
||||
streamingProcesses = 2;
|
||||
|
||||
smtp = {
|
||||
createLocally = false;
|
||||
@@ -105,8 +105,7 @@ in
|
||||
port = 465;
|
||||
};
|
||||
extraConfig = {
|
||||
# "SMTP_ENABLE_STARTTLS" = "never";
|
||||
"SMTP_ENABLE_STARTTLS_AUTO" = "true";
|
||||
"SMTP_ENABLE_STARTTLS_AUTO" = "true"; # Simple NixOS MailServer doesn't allow connections without SSL
|
||||
"SMTP_ENABLE_STARTTLS" = "always";
|
||||
"SMTP_TLS" = "true";
|
||||
"SMTP_SSL" = "true";
|
||||
@@ -114,14 +113,7 @@ in
|
||||
"DISALLOW_UNAUTHENTICATED_API_ACCESS" = lib.boolToString cfg.dissallowUnauthenticatedAPI;
|
||||
};
|
||||
};
|
||||
users.users.mastodon.isSystemUser = lib.mkForce false;
|
||||
users.users.mastodon.isNormalUser = lib.mkForce true;
|
||||
|
||||
users.groups."email-users" = {};
|
||||
users.users."noreply.mastodon" = {
|
||||
isSystemUser = true;
|
||||
group = "email-users";
|
||||
};
|
||||
selfprivacy.emails."noreply.mastodon" = {
|
||||
hashedPasswordFile = secrets.hashedPasswordFile;
|
||||
systemdTargets = [ "mastodon-email-password-setup.service" ];
|
||||
@@ -155,7 +147,6 @@ in
|
||||
|
||||
services.mastodon-kanidm-sync = {
|
||||
after = [
|
||||
# "mastodon.service" # TODO: ??
|
||||
"postgresql.service"
|
||||
"kanidm.service"
|
||||
];
|
||||
@@ -173,6 +164,7 @@ in
|
||||
POSTGRES_HOST = db.host;
|
||||
USERDATA_FILE_PATH = "/var/lib/mastodon/.userdata.json";
|
||||
OWNER_USERNAME = sp.username;
|
||||
SLEEP_TIME = "30";
|
||||
};
|
||||
serviceConfig = {
|
||||
Slice = "mastodon.slice";
|
||||
|
Reference in New Issue
Block a user