Skip to content

Commit 22d6693

Browse files
authored
app.py fix
1 parent e9137f4 commit 22d6693

File tree

1 file changed

+157
-157
lines changed

1 file changed

+157
-157
lines changed

app.py

Lines changed: 157 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,47 @@
1-
from flask import Flask, Response, request, jsonify, make_response
2-
import os
3-
import json
4-
import requests
5-
import re
6-
import base64
7-
import logging
8-
from urllib.parse import unquote
9-
10-
app = Flask("Secured Signal Api")
11-
12-
app.logger.setLevel(logging.INFO)
13-
14-
DEFAULT_BLOCKED_ENDPOINTS = [
15-
"/v1/about",
16-
"/v1/configuration",
17-
"/v1/devices",
18-
"/v1/register",
19-
"/v1/unregister",
20-
"/v1/qrcodelink",
21-
"/v1/accounts",
22-
"/v1/contacts"
23-
]
24-
25-
SENDER = os.getenv("SENDER")
26-
DEFAULT_RECIPIENTS = os.getenv("DEFAULT_RECIPIENTS")
27-
SIGNAL_API_URL = os.getenv("SIGNAL_API_URL")
28-
API_TOKEN = os.getenv("API_TOKEN")
29-
30-
BLOCKED_ENDPOINTS = os.getenv("BLOCKED_ENDPOINTS")
31-
VARIABLES = os.getenv("VARIABLES")
32-
33-
secure = False
34-
1+
from flask import Flask, Response, request, jsonify, make_response
2+
import os
3+
import json
4+
import requests
5+
import re
6+
import base64
7+
import logging
8+
from urllib.parse import unquote
9+
10+
app = Flask("Secured Signal Api")
11+
12+
app.logger.setLevel(logging.INFO)
13+
14+
DEFAULT_BLOCKED_ENDPOINTS = [
15+
"/v1/about",
16+
"/v1/configuration",
17+
"/v1/devices",
18+
"/v1/register",
19+
"/v1/unregister",
20+
"/v1/qrcodelink",
21+
"/v1/accounts",
22+
"/v1/contacts"
23+
]
24+
25+
SENDER = os.getenv("SENDER")
26+
DEFAULT_RECIPIENTS = os.getenv("DEFAULT_RECIPIENTS")
27+
SIGNAL_API_URL = os.getenv("SIGNAL_API_URL")
28+
API_TOKEN = os.getenv("API_TOKEN")
29+
30+
BLOCKED_ENDPOINTS = os.getenv("BLOCKED_ENDPOINTS")
31+
VARIABLES = os.getenv("VARIABLES")
32+
33+
secure = False
34+
3535
def fillInVars(obj):
36-
if isinstance(obj, dict):
36+
if isinstance(obj, dict):
3737
for key, value in obj.items():
3838
obj[key] = fillInVars(value)
3939
elif isinstance(obj, list):
4040
for i in range(len(obj)):
4141
obj[i] = fillInVars(obj[i])
4242
elif isinstance(obj, str):
43-
matches = re.findall(r"\${(.*?)}", obj)
44-
for match in matches:
43+
matches = re.findall(r"\${(.*?)}", obj)
44+
for match in matches:
4545
if match in VARIABLES:
4646
value = VARIABLES[match]
4747

@@ -50,123 +50,123 @@ def fillInVars(obj):
5050
return newValue
5151
else:
5252
return value
53-
return obj
54-
55-
def UnauthorizedResponse(prompt=None):
56-
headers = {}
57-
58-
if prompt:
59-
headers = {
60-
"WWW-Authenticate": 'Basic realm="Login Required", Bearer realm="Access Token Required"'
61-
}
62-
63-
return Response(
64-
"Unauthorized", 401,
65-
headers
66-
)
67-
68-
@app.before_request
69-
def middlewares():
70-
for blockedPath in BLOCKED_ENDPOINTS:
71-
if request.path.startswith(blockedPath):
72-
infoLog(f"Client tried to access Blocked Endpoint [{blockedPath}]")
73-
return Response("Forbidden", 401)
74-
75-
if secure:
76-
auth_header = request.headers.get("Authorization", "")
77-
78-
if auth_header.startswith("Bearer "):
79-
token = auth_header.split(" ", 1)[1]
80-
81-
token = unquote(token)
82-
if token != API_TOKEN:
83-
infoLog(f"Client failed Bearer Auth [token: {token}]")
84-
return UnauthorizedResponse()
85-
elif auth_header.startswith("Basic "):
86-
try:
87-
decoded = base64.b64decode(auth_header.split(" ", 1)[1]).decode()
88-
username, password = decoded.split(":", 1)
89-
90-
username = unquote(username)
91-
password = unquote(password)
92-
if username != "api" or password != API_TOKEN:
93-
infoLog(f"Client failed Basic Auth [user: {username}, pw:{password}]")
94-
return UnauthorizedResponse()
95-
except Exception as error:
96-
errorLog(f"Unexpected Error during Basic Auth: {error}")
97-
return UnauthorizedResponse()
98-
else:
99-
infoLog(f"Client did not provide any Auth Method")
100-
return UnauthorizedResponse(True)
101-
102-
103-
@app.route('/', defaults={'path': ''}, methods=['GET', 'POST', 'PUT'])
104-
@app.route('/<path:path>', methods=['GET', 'POST', 'PUT'])
105-
def proxy(path):
106-
method = request.method
107-
incomingJSON = request.get_json(force=True, silent=True)
108-
jsonData = incomingJSON
109-
headers = {k: v for k, v in request.headers if k.lower() != 'host'}
110-
111-
if incomingJSON:
112-
jsonData = fillInVars(incomingJSON)
113-
114-
if "${NUMBER}" in path:
115-
path = path.replace("${NUMBER}", SENDER)
116-
117-
query_string = request.query_string.decode()
118-
119-
if request.query_string.decode():
120-
query_string= "?" + request.query_string.decode()
121-
122-
targetURL = f"{SIGNAL_API_URL}/{path}{query_string}"
123-
124-
infoLog(json.dumps(jsonData))
125-
126-
resp = requests.request(
127-
method=method,
128-
url=targetURL,
129-
headers=headers,
130-
json=jsonData
131-
)
132-
133-
infoLog(f"Forwarded {resp.text} to {targetURL} [{method}]")
134-
135-
# return Response(resp.content, status=resp.status_code, headers=dict(resp.headers))
136-
137-
response = make_response(resp.json())
138-
response.status_code = resp.status_code
139-
140-
return response
141-
142-
def infoLog(msg):
143-
app.logger.info(msg)
144-
145-
def errorLog(msg):
146-
app.logger.error(msg)
147-
148-
if __name__ == '__main__':
149-
if SENDER and SIGNAL_API_URL:
150-
if API_TOKEN == None or API_TOKEN == "":
151-
infoLog("No API Token set (API_TOKEN), this is not recommended!")
152-
else:
153-
secure = True
154-
infoLog("API Token set, use Bearer or Basic Auth (user: api) for authentication")
155-
156-
if DEFAULT_RECIPIENTS != None and DEFAULT_RECIPIENTS != "":
157-
DEFAULT_RECIPIENTS = json.loads(DEFAULT_RECIPIENTS)
158-
159-
if BLOCKED_ENDPOINTS != None and BLOCKED_ENDPOINTS != "":
160-
BLOCKED_ENDPOINTS = json.loads(BLOCKED_ENDPOINTS)
161-
else:
162-
BLOCKED_ENDPOINTS = DEFAULT_BLOCKED_ENDPOINTS
163-
164-
if VARIABLES != None and VARIABLES != "":
165-
VARIABLES = json.loads(VARIABLES)
166-
else:
167-
VARIABLES = {
168-
"NUMBER": SENDER,
169-
"RECIPIENTS": DEFAULT_RECIPIENTS
170-
}
171-
172-
app.run(debug=False, port=8880, host='0.0.0.0')
53+
return obj
54+
55+
def UnauthorizedResponse(prompt=None):
56+
headers = {}
57+
58+
if prompt:
59+
headers = {
60+
"WWW-Authenticate": 'Basic realm="Login Required", Bearer realm="Access Token Required"'
61+
}
62+
63+
return Response(
64+
"Unauthorized", 401,
65+
headers
66+
)
67+
68+
@app.before_request
69+
def middlewares():
70+
for blockedPath in BLOCKED_ENDPOINTS:
71+
if request.path.startswith(blockedPath):
72+
infoLog(f"Client tried to access Blocked Endpoint [{blockedPath}]")
73+
return Response("Forbidden", 401)
74+
75+
if secure:
76+
auth_header = request.headers.get("Authorization", "")
77+
78+
if auth_header.startswith("Bearer "):
79+
token = auth_header.split(" ", 1)[1]
80+
81+
token = unquote(token)
82+
if token != API_TOKEN:
83+
infoLog(f"Client failed Bearer Auth [token: {token}]")
84+
return UnauthorizedResponse()
85+
elif auth_header.startswith("Basic "):
86+
try:
87+
decoded = base64.b64decode(auth_header.split(" ", 1)[1]).decode()
88+
username, password = decoded.split(":", 1)
89+
90+
username = unquote(username)
91+
password = unquote(password)
92+
if username != "api" or password != API_TOKEN:
93+
infoLog(f"Client failed Basic Auth [user: {username}, pw:{password}]")
94+
return UnauthorizedResponse()
95+
except Exception as error:
96+
errorLog(f"Unexpected Error during Basic Auth: {error}")
97+
return UnauthorizedResponse()
98+
else:
99+
infoLog(f"Client did not provide any Auth Method")
100+
return UnauthorizedResponse(True)
101+
102+
103+
@app.route('/', defaults={'path': ''}, methods=['GET', 'POST', 'PUT'])
104+
@app.route('/<path:path>', methods=['GET', 'POST', 'PUT'])
105+
def proxy(path):
106+
method = request.method
107+
incomingJSON = request.get_json(force=True, silent=True)
108+
jsonData = incomingJSON
109+
headers = {k: v for k, v in request.headers if k.lower() != 'host'}
110+
111+
if incomingJSON:
112+
jsonData = fillInVars(incomingJSON)
113+
114+
if "${NUMBER}" in path:
115+
path = path.replace("${NUMBER}", SENDER)
116+
117+
query_string = request.query_string.decode()
118+
119+
if request.query_string.decode():
120+
query_string= "?" + request.query_string.decode()
121+
122+
targetURL = f"{SIGNAL_API_URL}/{path}{query_string}"
123+
124+
infoLog(json.dumps(jsonData))
125+
126+
resp = requests.request(
127+
method=method,
128+
url=targetURL,
129+
headers=headers,
130+
json=jsonData
131+
)
132+
133+
infoLog(f"Forwarded {resp.text} to {targetURL} [{method}]")
134+
135+
# return Response(resp.content, status=resp.status_code, headers=dict(resp.headers))
136+
137+
response = make_response(resp.json())
138+
response.status_code = resp.status_code
139+
140+
return response
141+
142+
def infoLog(msg):
143+
app.logger.info(msg)
144+
145+
def errorLog(msg):
146+
app.logger.error(msg)
147+
148+
if __name__ == '__main__':
149+
if SENDER and SIGNAL_API_URL:
150+
if API_TOKEN == None or API_TOKEN == "":
151+
infoLog("No API Token set (API_TOKEN), this is not recommended!")
152+
else:
153+
secure = True
154+
infoLog("API Token set, use Bearer or Basic Auth (user: api) for authentication")
155+
156+
if DEFAULT_RECIPIENTS != None and DEFAULT_RECIPIENTS != "":
157+
DEFAULT_RECIPIENTS = json.loads(DEFAULT_RECIPIENTS)
158+
159+
if BLOCKED_ENDPOINTS != None and BLOCKED_ENDPOINTS != "":
160+
BLOCKED_ENDPOINTS = json.loads(BLOCKED_ENDPOINTS)
161+
else:
162+
BLOCKED_ENDPOINTS = DEFAULT_BLOCKED_ENDPOINTS
163+
164+
if VARIABLES != None and VARIABLES != "":
165+
VARIABLES = json.loads(VARIABLES)
166+
else:
167+
VARIABLES = {
168+
"NUMBER": SENDER,
169+
"RECIPIENTS": DEFAULT_RECIPIENTS
170+
}
171+
172+
app.run(debug=False, port=8880, host='0.0.0.0')

0 commit comments

Comments
 (0)