mirror of
https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git
synced 2024-11-18 16:39:13 +00:00
Move to JSON controlled server settings
This commit is contained in:
parent
af059c2efd
commit
767c504a1d
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"python.formatting.provider": "black"
|
||||||
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools", "wheel"]
|
requires = ["setuptools", "wheel", "portalocker"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
|
@ -3,3 +3,4 @@ flask
|
||||||
flask_restful
|
flask_restful
|
||||||
flask_socketio
|
flask_socketio
|
||||||
setuptools
|
setuptools
|
||||||
|
portalocker
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from flask_restful import Resource
|
from flask_restful import Resource
|
||||||
|
import portalocker
|
||||||
|
import json
|
||||||
|
|
||||||
from selfprivacy_api.resources.services import api
|
from selfprivacy_api.resources.services import api
|
||||||
|
|
||||||
# Enable Bitwarden
|
# Enable Bitwarden
|
||||||
class EnableBitwarden(Resource):
|
class EnableBitwarden(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/passmgr/bitwarden.nix", "rt")
|
with open("/etc/nixos/userdata/userdata.json", "r+", encoding="utf8") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = false;", "enable = true;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/passmgr/bitwarden.nix", "wt")
|
if "bitwarden" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["bitwarden"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["bitwarden"]["enable"] = True
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "Bitwarden enabled",
|
"message": "Bitwarden enabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,17 +30,21 @@ class EnableBitwarden(Resource):
|
||||||
# Disable Bitwarden
|
# Disable Bitwarden
|
||||||
class DisableBitwarden(Resource):
|
class DisableBitwarden(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/passmgr/bitwarden.nix", "rt")
|
with open("/etc/nixos/userdata/userdata.json", "r+", encoding="utf8") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = true;", "enable = false;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/passmgr/bitwarden.nix", "wt")
|
if "bitwarden" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["bitwarden"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["bitwarden"]["enable"] = False
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "Bitwarden disabled",
|
"message": "Bitwarden disabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from flask_restful import Resource
|
from flask_restful import Resource
|
||||||
|
import portalocker
|
||||||
|
import json
|
||||||
|
|
||||||
from selfprivacy_api.resources.services import api
|
from selfprivacy_api.resources.services import api
|
||||||
|
|
||||||
# Enable Gitea
|
# Enable Gitea
|
||||||
class EnableGitea(Resource):
|
class EnableGitea(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/git/gitea.nix", "rt")
|
with open("/etc/nixos/userdata/userdata.json", "r+", encoding="utf8") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = false;", "enable = true;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/git/gitea.nix", "wt")
|
if "gitea" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["gitea"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["gitea"]["enable"] = True
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "Gitea enabled",
|
"message": "Gitea enabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,17 +30,21 @@ class EnableGitea(Resource):
|
||||||
# Disable Gitea
|
# Disable Gitea
|
||||||
class DisableGitea(Resource):
|
class DisableGitea(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/git/gitea.nix", "rt")
|
with open("/etc/nixos/userdata/userdata.json", "r+", encoding="utf8") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = true;", "enable = false;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/git/gitea.nix", "wt")
|
if "gitea" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["gitea"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["gitea"]["enable"] = False
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "Gitea disabled",
|
"message": "Gitea disabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from flask_restful import Resource
|
from flask_restful import Resource
|
||||||
|
import portalocker
|
||||||
|
import json
|
||||||
|
|
||||||
from selfprivacy_api.resources.services import api
|
from selfprivacy_api.resources.services import api
|
||||||
|
|
||||||
# Enable Nextcloud
|
# Enable Nextcloud
|
||||||
class EnableNextcloud(Resource):
|
class EnableNextcloud(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/nextcloud/nextcloud.nix", "rt")
|
with portalocker.Lock("/etc/nixos/userdata/userdata.json", "r+") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = false;", "enable = true;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/nextcloud/nextcloud.nix", "wt")
|
if "nextcloud" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["nextcloud"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["nextcloud"]["enable"] = True
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "Nextcloud enabled",
|
"message": "Nextcloud enabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,17 +30,21 @@ class EnableNextcloud(Resource):
|
||||||
# Disable Nextcloud
|
# Disable Nextcloud
|
||||||
class DisableNextcloud(Resource):
|
class DisableNextcloud(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/nextcloud/nextcloud.nix", "rt")
|
with portalocker.Lock("/etc/nixos/userdata/userdata.json", "r+") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = true;", "enable = false;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/nextcloud/nextcloud.nix", "wt")
|
if "nextcloud" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["nextcloud"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["nextcloud"]["enable"] = False
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "Nextcloud disabled",
|
"message": "Nextcloud disabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from flask_restful import Resource
|
from flask_restful import Resource
|
||||||
|
import portalocker
|
||||||
|
import json
|
||||||
|
|
||||||
from selfprivacy_api.resources.services import api
|
from selfprivacy_api.resources.services import api
|
||||||
|
|
||||||
# Enable OpenConnect VPN server
|
# Enable OpenConnect VPN server
|
||||||
class EnableOcserv(Resource):
|
class EnableOcserv(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/vpn/ocserv.nix", "rt")
|
with portalocker.Lock("/etc/nixos/userdata/userdata.json", "r+") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = false;", "enable = true;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/vpn/ocserv.nix", "wt")
|
if "ocserv" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["ocserv"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["ocserv"]["enable"] = True
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "OpenConnect VPN server enabled",
|
"message": "OpenConnect VPN server enabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,17 +30,21 @@ class EnableOcserv(Resource):
|
||||||
# Disable OpenConnect VPN server
|
# Disable OpenConnect VPN server
|
||||||
class DisableOcserv(Resource):
|
class DisableOcserv(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/vpn/ocserv.nix", "rt")
|
with portalocker.Lock("/etc/nixos/userdata/userdata.json", "r+") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = true;", "enable = false;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/vpn/ocserv.nix", "wt")
|
if "ocserv" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["ocserv"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["ocserv"]["enable"] = False
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "OpenConnect VPN server disabled",
|
"message": "OpenConnect VPN server disabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from flask_restful import Resource
|
from flask_restful import Resource
|
||||||
|
import portalocker
|
||||||
|
import json
|
||||||
|
|
||||||
from selfprivacy_api.resources.services import api
|
from selfprivacy_api.resources.services import api
|
||||||
|
|
||||||
# Enable Pleroma
|
# Enable Pleroma
|
||||||
class EnablePleroma(Resource):
|
class EnablePleroma(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/social/pleroma.nix", "rt")
|
with portalocker.Lock("/etc/nixos/userdata/userdata.json", "r+") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = false;", "enable = true;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/social/pleroma.nix", "wt")
|
if "pleroma" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["pleroma"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["pleroma"]["enable"] = True
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "Pleroma enabled",
|
"message": "Pleroma enabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,17 +30,21 @@ class EnablePleroma(Resource):
|
||||||
# Disable Pleroma
|
# Disable Pleroma
|
||||||
class DisablePleroma(Resource):
|
class DisablePleroma(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/social/pleroma.nix", "rt")
|
with portalocker.Lock("/etc/nixos/userdata/userdata.json", "r+") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = true;", "enable = false;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/social/pleroma.nix", "wt")
|
if "pleroma" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["pleroma"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["pleroma"]["enable"] = False
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "Pleroma disabled",
|
"message": "Pleroma disabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,29 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from flask import Blueprint, request
|
from flask import Blueprint, request
|
||||||
from flask_restful import Resource, reqparse
|
from flask_restful import Resource, reqparse
|
||||||
|
import portalocker
|
||||||
|
import json
|
||||||
|
|
||||||
from selfprivacy_api.resources.services import api
|
from selfprivacy_api.resources.services import api
|
||||||
|
|
||||||
# Enable SSH
|
# Enable SSH
|
||||||
class EnableSSH(Resource):
|
class EnableSSH(Resource):
|
||||||
def post(self):
|
def post(self):
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/configuration.nix", "rt")
|
with portalocker.Lock("/etc/nixos/userdata/userdata.json", "r+") as f:
|
||||||
fileContent = readOnlyFileDescriptor.read()
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
fileContent = fileContent.replace("enable = false;", "enable = true;")
|
try:
|
||||||
readOnlyFileDescriptor.close()
|
data = json.load(f)
|
||||||
readWriteFileDescriptor = open("/etc/nixos/configuration.nix", "wt")
|
if "ssh" not in data:
|
||||||
writeOperationDescriptor = readWriteFileDescriptor.write(fileContent)
|
data["ssh"] = {}
|
||||||
readWriteFileDescriptor.close()
|
data["ssh"]["enable"] = True
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": writeOperationDescriptor,
|
|
||||||
"message": "SSH enabled",
|
"message": "SSH enabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,41 +39,28 @@ class WriteSSHKey(Resource):
|
||||||
|
|
||||||
publicKey = args["public_key"]
|
publicKey = args["public_key"]
|
||||||
|
|
||||||
print("[INFO] Opening /etc/nixos/configuration.nix...", sep="")
|
with portalocker.Lock("/etc/nixos/userdata/userdata.json", "r+") as f:
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/configuration.nix", "r")
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
print("done")
|
try:
|
||||||
fileContent = list()
|
data = json.load(f)
|
||||||
index = int(0)
|
if "ssh" not in data:
|
||||||
|
data["ssh"] = {}
|
||||||
print("[INFO] Reading file content...", sep="")
|
# Return 400 if key already in array
|
||||||
|
for key in data["ssh"]["rootSshKeys"]:
|
||||||
while True:
|
if key == publicKey:
|
||||||
line = readOnlyFileDescriptor.readline()
|
return {
|
||||||
|
"error": "Key already exists",
|
||||||
if not line:
|
}, 400
|
||||||
break
|
data["ssh"]["rootSshKeys"].append(publicKey)
|
||||||
else:
|
f.seek(0)
|
||||||
fileContent.append(line)
|
json.dump(data, f, indent=4)
|
||||||
print("[DEBUG] Read line!")
|
f.truncate()
|
||||||
|
finally:
|
||||||
for line in fileContent:
|
portalocker.unlock(f)
|
||||||
index += 1
|
|
||||||
if "openssh.authorizedKeys.keys = [" in line:
|
|
||||||
print("[DEBUG] Found SSH key configuration snippet match!")
|
|
||||||
print("[INFO] Writing new SSH key", sep="")
|
|
||||||
fileContent.append('\n "' + publicKey + '"')
|
|
||||||
print("done")
|
|
||||||
break
|
|
||||||
|
|
||||||
print("[INFO] Writing data from memory to file...", sep="")
|
|
||||||
readWriteFileDescriptor = open("/etc/nixos/configuration.nix", "w")
|
|
||||||
print("done")
|
|
||||||
operationResult = readWriteFileDescriptor.writelines(fileContent)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"descriptor": operationResult,
|
"message": "New SSH key successfully written",
|
||||||
"message": "New SSH key successfully written to /etc/nixos/configuration.nix",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
from flask import Blueprint, jsonify, request
|
from flask import Blueprint, jsonify, request
|
||||||
from flask_restful import Resource, Api
|
from flask_restful import Resource, Api
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import portalocker
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
from selfprivacy_api import resources
|
from selfprivacy_api import resources
|
||||||
|
|
||||||
|
@ -24,123 +27,62 @@ class Users(Resource):
|
||||||
hashedPassword = hashedPassword.decode("ascii")
|
hashedPassword = hashedPassword.decode("ascii")
|
||||||
hashedPassword = hashedPassword.rstrip()
|
hashedPassword = hashedPassword.rstrip()
|
||||||
|
|
||||||
print("[TRACE] {0}".format(hashedPassword))
|
with open("/etc/nixos/userdata/userdata.json", "r+", encoding="utf8") as f:
|
||||||
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
print("[INFO] Opening /etc/nixos/users.nix...", sep="")
|
try:
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/users.nix", "r")
|
data = json.load(f)
|
||||||
print("done")
|
# Return 400 if username is not provided
|
||||||
fileContent = list()
|
if request.headers.get("X-User") is None:
|
||||||
index = int(0)
|
return {"error": "username is required"}, 400
|
||||||
|
# Return 400 if password is not provided
|
||||||
print("[INFO] Reading file content...", sep="")
|
if request.headers.get("X-Password") is None:
|
||||||
|
return {"error": "password is required"}, 400
|
||||||
while True:
|
# Check is username passes regex
|
||||||
line = readOnlyFileDescriptor.readline()
|
if not re.match(r"^[a-z_][a-z0-9_]+$", request.headers.get("X-User")):
|
||||||
|
return {"error": "username must be alphanumeric"}, 400
|
||||||
if not line:
|
# Check if username less than 32 characters
|
||||||
break
|
if len(request.headers.get("X-User")) > 32:
|
||||||
else:
|
return {"error": "username must be less than 32 characters"}, 400
|
||||||
fileContent.append(line)
|
# Return 400 if user already exists
|
||||||
print("[DEBUG] Read line!")
|
for user in data["users"]:
|
||||||
|
if user["username"] == request.headers.get("X-User"):
|
||||||
userTemplate = """
|
return {"error": "User already exists"}, 400
|
||||||
|
if "users" not in data:
|
||||||
#begin
|
data["users"] = []
|
||||||
\"{0}\" = {{
|
data["users"].append(
|
||||||
isNormalUser = true;
|
{
|
||||||
hashedPassword = \"{1}\";
|
"username": request.headers.get("X-User"),
|
||||||
}};
|
"hashedPassword": hashedPassword,
|
||||||
#end
|
}
|
||||||
""".format(
|
|
||||||
request.headers.get("X-User"), hashedPassword
|
|
||||||
)
|
|
||||||
|
|
||||||
mailUserTemplate = """
|
|
||||||
\"{0}@{2}\" = {{
|
|
||||||
hashedPassword =
|
|
||||||
\"{1}\";
|
|
||||||
catchAll = [ \"{2}\" ];
|
|
||||||
|
|
||||||
sieveScript = ''
|
|
||||||
require [\"fileinto\", \"mailbox\"];
|
|
||||||
if header :contains \"Chat-Version\" \"1.0\"
|
|
||||||
{{
|
|
||||||
fileinto :create \"DeltaChat\";
|
|
||||||
stop;
|
|
||||||
}}
|
|
||||||
'';
|
|
||||||
}};""".format(
|
|
||||||
request.headers.get("X-User"),
|
|
||||||
hashedPassword,
|
|
||||||
request.headers.get("X-Domain"),
|
|
||||||
)
|
|
||||||
|
|
||||||
for line in fileContent:
|
|
||||||
index += 1
|
|
||||||
if line.startswith(" #begin"):
|
|
||||||
print("[DEBUG] Found user configuration snippet match!")
|
|
||||||
print(
|
|
||||||
"[INFO] Writing new user configuration snippet to memory...", sep=""
|
|
||||||
)
|
)
|
||||||
fileContent.insert(index - 1, userTemplate)
|
f.seek(0)
|
||||||
print("done")
|
json.dump(data, f, indent=4)
|
||||||
break
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
print("[INFO] Writing data from memory to file...", sep="")
|
return {"result": 0}
|
||||||
readWriteFileDescriptor = open("/etc/nixos/users.nix", "w")
|
|
||||||
userConfigurationWriteOperationResult = readWriteFileDescriptor.writelines(
|
|
||||||
fileContent
|
|
||||||
)
|
|
||||||
print("done")
|
|
||||||
|
|
||||||
readOnlyFileDescriptor.close()
|
|
||||||
readWriteFileDescriptor.close()
|
|
||||||
|
|
||||||
print(
|
|
||||||
"[INFO] Opening /etc/nixos/mailserver/system/mailserver.nix.nix for reading...",
|
|
||||||
sep="",
|
|
||||||
)
|
|
||||||
readOnlyFileDescriptor = open("/etc/nixos/mailserver/system/mailserver.nix")
|
|
||||||
print("done")
|
|
||||||
|
|
||||||
fileContent = list()
|
|
||||||
index = int(0)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
line = readOnlyFileDescriptor.readline()
|
|
||||||
|
|
||||||
if not line:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
fileContent.append(line)
|
|
||||||
print("[DEBUG] Read line!")
|
|
||||||
|
|
||||||
for line in fileContent:
|
|
||||||
if line.startswith(" loginAccounts = {"):
|
|
||||||
print("[DEBUG] Found mailuser configuration snippet match!")
|
|
||||||
print(
|
|
||||||
"[INFO] Writing new user configuration snippet to memory...", sep=""
|
|
||||||
)
|
|
||||||
fileContent.insert(index + 1, mailUserTemplate)
|
|
||||||
print("done")
|
|
||||||
break
|
|
||||||
index += 1
|
|
||||||
|
|
||||||
readWriteFileDescriptor = open(
|
|
||||||
"/etc/nixos/mailserver/system/mailserver.nix", "w"
|
|
||||||
)
|
|
||||||
|
|
||||||
mailUserConfigurationWriteOperationResult = readWriteFileDescriptor.writelines(
|
|
||||||
fileContent
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
|
||||||
"result": 0,
|
|
||||||
"descriptor0": userConfigurationWriteOperationResult,
|
|
||||||
"descriptor1": mailUserConfigurationWriteOperationResult,
|
|
||||||
}
|
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
user = subprocess.Popen(["userdel", request.headers.get("X-User")])
|
with open("/etc/nixos/userdata/userdata.json", "r+", encoding="utf8") as f:
|
||||||
user.communicate()[0]
|
portalocker.lock(f, portalocker.LOCK_EX)
|
||||||
return user.returncode
|
try:
|
||||||
|
data = json.load(f)
|
||||||
|
# Return 400 if username is not provided
|
||||||
|
if request.headers.get("X-User") is None:
|
||||||
|
return {"error": "username is required"}, 400
|
||||||
|
# Return 400 if user does not exist
|
||||||
|
for user in data["users"]:
|
||||||
|
if user["username"] == request.headers.get("X-User"):
|
||||||
|
data["users"].remove(user)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return {"error": "User does not exist"}, 400
|
||||||
|
|
||||||
|
f.seek(0)
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
f.truncate()
|
||||||
|
finally:
|
||||||
|
portalocker.unlock(f)
|
||||||
|
|
||||||
|
return {"result": 0}
|
||||||
|
|
Loading…
Reference in a new issue