Add option to make http functions private (Require authentication, currently just redirects to login page; Should look into cookie + JWT + api key)

This commit is contained in:
Peter Stockings
2023-12-21 14:03:25 +11:00
parent 14e4672be6
commit 7c7dbae05a
6 changed files with 64 additions and 15 deletions

20
app.py
View File

@@ -106,7 +106,7 @@ def dashboard_http_functions():
@ app.route("/dashboard/http_functions/add_form", methods=["GET"])
@login_required
def get_http_function_add_form():
return render_template("dashboard/http_functions/new.html", name=DEFAULT_FUNCTION_NAME, script=DEFAULT_SCRIPT, environment_info=DEFAULT_ENVIRONMENT)
return render_template("dashboard/http_functions/new.html", name=DEFAULT_FUNCTION_NAME, script=DEFAULT_SCRIPT, environment_info=DEFAULT_ENVIRONMENT, is_public=False)
@ app.route("/dashboard/http_functions/create", methods=["POST"])
@login_required
@@ -116,8 +116,9 @@ def create_http_function():
name = request.json.get('name')
script_content = request.json.get('script_content')
environment_info = json.dumps(eval(request.json.get('environment_info')))
is_public = request.json.get('is_public')
db.create_new_http_function(user_id, name, script_content, environment_info)
db.create_new_http_function(user_id, name, script_content, environment_info, is_public)
http_functions = db.get_http_functions_for_user(user_id)
http_functions = create_http_functions_view_model(http_functions)
@@ -136,7 +137,8 @@ def get_http_function_edit_form():
return jsonify({'error': 'Function not found'}), 404
script = http_function['script_content']
environment_info = json.dumps(http_function['environment_info'], indent=2)
return render_template("dashboard/http_functions/edit.html", user_id=user_id, name=name, script=script, environment_info=environment_info)
is_public = http_function['is_public']
return render_template("dashboard/http_functions/edit.html", user_id=user_id, name=name, script=script, environment_info=environment_info, is_public=is_public)
@ app.route("/dashboard/http_functions/edit", methods=["POST"])
@login_required
@@ -146,8 +148,9 @@ def edit_http_function():
name = request.json.get('name')
script_content = request.json.get('script_content')
environment_info = json.dumps(eval(request.json.get('environment_info')))
is_public = request.json.get('is_public')
db.edit_http_function(user_id, name, script_content, environment_info)
db.edit_http_function(user_id, name, script_content, environment_info, is_public)
return { "status": "success", "message": f'{name} updated' }
except Exception as e:
print(e)
@@ -227,6 +230,15 @@ def execute_http_function(user_id, function):
code = http_function['script_content']
environment = http_function['environment_info']
is_public = http_function['is_public']
# Check if the function is public, if not check if the user is authenticated and owns the function
if not is_public:
if not current_user.is_authenticated:
return login_manager.unauthorized()
if int(current_user.id) != user_id:
return jsonify({'error': 'Function belongs to another user', 'current_user_id': current_user.id, 'user_id': user_id}), 404
request_data = {
'method': request.method,

18
db.py
View File

@@ -49,21 +49,27 @@ class DataBase():
def get_http_functions_for_user(self, user_id):
http_functions = self.execute(
'SELECT id, user_id, NAME, script_content, invoked_count, environment_info FROM http_functions WHERE user_id=%s ORDER by id DESC', [user_id])
'SELECT id, user_id, NAME, script_content, invoked_count, environment_info, is_public FROM http_functions WHERE user_id=%s ORDER by id DESC', [user_id])
return http_functions
def get_http_function(self, user_id, name):
http_function = self.execute(
'SELECT id, user_id, NAME, script_content, invoked_count, environment_info FROM http_functions WHERE user_id=%s AND NAME=%s', [user_id, name], one=True)
'SELECT id, user_id, NAME, script_content, invoked_count, environment_info, is_public FROM http_functions WHERE user_id=%s AND NAME=%s', [user_id, name], one=True)
return http_function
def create_new_http_function(self, user_id, name, script_content, environment_info):
def create_new_http_function(self, user_id, name, script_content, environment_info, is_public=False):
self.execute(
'INSERT INTO http_functions (user_id, NAME, script_content, environment_info) VALUES (%s, %s, %s, %s)', [user_id, name, script_content, environment_info], commit=True)
'INSERT INTO http_functions (user_id, NAME, script_content, environment_info, is_public) VALUES (%s, %s, %s, %s, %s)',
[user_id, name, script_content, environment_info, is_public],
commit=True
)
def edit_http_function(self, user_id, name, script_content, environment_info):
def edit_http_function(self, user_id, name, script_content, environment_info, is_public):
self.execute(
'UPDATE http_functions SET script_content=%s, environment_info=%s WHERE user_id=%s AND NAME=%s', [script_content, environment_info, user_id, name], commit=True)
'UPDATE http_functions SET script_content=%s, environment_info=%s, is_public=%s WHERE user_id=%s AND NAME=%s',
[script_content, environment_info, is_public, user_id, name],
commit=True
)
def update_http_function_environment_info_and_invoked_count(self, user_id, name, environment_info):
self.execute(

View File

@@ -5,7 +5,8 @@ def create_http_function_view_model(http_function):
"name": http_function['name'],
"script_content": http_function['script_content'],
"invoked_count": http_function['invoked_count'],
"environment_info": http_function['environment_info']
"environment_info": http_function['environment_info'],
"is_public": http_function['is_public']
}
return function_view_model

View File

@@ -42,4 +42,5 @@
</div>
</div>
{{ render_partial('function_editor.html', name=name, script=script, environment_info=environment_info, is_edit=True) }}
{{ render_partial('function_editor.html', name=name, script=script, environment_info=environment_info,
is_public=is_public, is_edit=True) }}

View File

@@ -8,4 +8,5 @@
</div>
{{ render_partial('function_editor.html', name=name, script=script, environment_info=environment_info, is_add=True) }}
{{ render_partial('function_editor.html', name=name, script=script, environment_info=environment_info,
is_public=is_public, is_add=True) }}

View File

@@ -141,6 +141,32 @@
editor_environment.session.setMode("ace/mode/json");
</script>
{% if is_add|default(false, true) or is_edit|default(false, true) %}
<div class="flex">
<div class="inline-flex items-center">
<label class="relative flex items-center p-3 rounded-full cursor-pointer" htmlFor="is_public">
<input type="checkbox"
class="before:content[''] peer relative h-5 w-5 cursor-pointer appearance-none rounded-md border border-blue-gray-200 transition-all before:absolute before:top-2/4 before:left-2/4 before:block before:h-12 before:w-12 before:-translate-y-2/4 before:-translate-x-2/4 before:rounded-full before:bg-blue-gray-500 before:opacity-0 before:transition-opacity checked:border-gray-900 checked:bg-gray-900 checked:before:bg-gray-900 hover:before:opacity-10"
id="is_public" {% if is_public|default(false, true) %} checked {% endif %} />
<span
class="absolute text-white transition-opacity opacity-0 pointer-events-none top-2/4 left-2/4 -translate-y-2/4 -translate-x-2/4 peer-checked:opacity-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"
stroke="currentColor" stroke-width="1">
<path fill-rule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clip-rule="evenodd"></path>
</svg>
</span>
</label>
<label class="mt-px font-light text-gray-700 cursor-pointer select-none" htmlFor="is_public">
Public
</label>
</div>
</div>
{% endif %}
<div class="flex">
{% if is_edit|default(false, true) %}
<button
@@ -170,13 +196,14 @@
let name = '{{ name }}';
let script_content = editor.getValue().trim();
let environment_info = editor_environment.getValue().trim();
let is_public = document.querySelector('#is_public').checked
fetch("{{ url_for('edit_http_function') }}", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, script_content, environment_info }),
body: JSON.stringify({ name, script_content, environment_info, is_public }),
})
.then(response => response.json())
.then(json => showAlert(json.message, json.status))
@@ -201,13 +228,14 @@
let name = document.querySelector('#function-name').value;
let script_content = editor.getValue().trim();
let environment_info = editor_environment.getValue().trim();
let is_public = document.querySelector('#is_public').checked
fetch("{{ url_for('create_http_function') }}", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, script_content, environment_info }),
body: JSON.stringify({ name, script_content, environment_info, is_public }),
})
.then(response => response.text())
.then(text => {