summaryrefslogtreecommitdiffstats
path: root/ogcp
diff options
context:
space:
mode:
authorAlejandro Sirgo Rica <asirgo@soleta.eu>2024-09-03 12:45:49 +0200
committerAlejandro Sirgo Rica <asirgo@soleta.eu>2024-09-03 16:26:22 +0200
commit7613cd8017e978e771552467a4e10141e120fccb (patch)
tree172c69df30ead92bdf6b9fb2619523ad6b4f9f29 /ogcp
parentc1ac88e47c8562699edc9f5304649762366191e0 (diff)
ogcp: add server ip configuration
Enable server view in the main toolbar. Hide Add server and Delete server buttons. Add Update server button. Add server/update view to edit the server addresses.
Diffstat (limited to 'ogcp')
-rw-r--r--ogcp/forms/action_forms.py8
-rw-r--r--ogcp/og_server.py6
-rw-r--r--ogcp/templates/actions/server_update.html69
-rw-r--r--ogcp/templates/base.html3
-rw-r--r--ogcp/templates/servers.html9
-rw-r--r--ogcp/views.py91
6 files changed, 180 insertions, 6 deletions
diff --git a/ogcp/forms/action_forms.py b/ogcp/forms/action_forms.py
index b97ff4d..b4dfe7b 100644
--- a/ogcp/forms/action_forms.py
+++ b/ogcp/forms/action_forms.py
@@ -276,6 +276,14 @@ class ServerForm(FlaskForm):
validators=[InputRequired()])
submit = SubmitField(label=_l('Submit'))
+class ServerConfigurationForm(FlaskForm):
+ server_addr = HiddenField()
+ addr = FieldList(
+ StringField(label=_l('Address')),
+ label=_l('Addresses'),
+ )
+ submit = SubmitField(label=_l('Submit'))
+
class DeleteRepositoryForm(FlaskForm):
repository = SelectField(label=_l('Repository'),
validators=[InputRequired()])
diff --git a/ogcp/og_server.py b/ogcp/og_server.py
index 1b7fa32..4a1b6ff 100644
--- a/ogcp/og_server.py
+++ b/ogcp/og_server.py
@@ -37,6 +37,12 @@ class OGServer:
json=payload)
return r
+ def delete(self, path, payload):
+ r = requests.delete(f'{self.URL}{path}',
+ headers=self.HEADERS,
+ json=payload)
+ return r
+
@property
def id(self):
ip = self.ip.replace('.', '-')
diff --git a/ogcp/templates/actions/server_update.html b/ogcp/templates/actions/server_update.html
new file mode 100644
index 0000000..ae2513b
--- /dev/null
+++ b/ogcp/templates/actions/server_update.html
@@ -0,0 +1,69 @@
+{% extends 'servers.html' %}
+{% import "bootstrap/wtf.html" as wtf %}
+
+{% set sidebar_state = 'disabled' %}
+{% set btn_back = true %}
+
+{% block nav_server_add %}active{% endblock %}
+{% block content %}
+
+<h2 class="mx-5 subhead-heading">{{_('Update server')}}</h2>
+
+<form class="form mx-5" method="POST">
+ {{ form.hidden_tag() }}
+
+ {{ form.server_addr() }}
+
+ <div class="form-group">
+ <div id="ip-fields">
+ {% for addr in form.addr %}
+ <div class="d-flex align-items-center mb-2">
+ {{ addr(class="form-control me-2", placeholder=_("Enter IP Address"), required=True) }}
+ <button type="button" class="btn btn-danger" onclick="removeIPField(this)">{{_('Remove') }}</button>
+ </div>
+ {% endfor %}
+ </div>
+ <button type="button" class="btn btn-primary" onclick="addIPField()">{{_('Add address') }}</button>
+
+ {{ form.submit(class="btn btn-success") }}
+ </div>
+</form>
+
+<script>
+ function addIPField() {
+ const container = document.createElement('div');
+ container.classList.add('d-flex', 'align-items-center', 'mb-2');
+
+ const newField = document.createElement('input');
+ newField.setAttribute('type', 'text');
+ newField.setAttribute('name', 'addr-' + document.querySelectorAll('input[name^="addr-"]').length);
+ newField.classList.add('form-control', 'me-2');
+ newField.setAttribute('placeholder', '{{ _('Enter IP Address') }}');
+ newField.required = true;
+
+ const removeButton = document.createElement('button');
+ removeButton.setAttribute('type', 'button');
+ removeButton.classList.add('btn', 'btn-danger');
+ removeButton.innerText = '{{ _('Remove') }}';
+ removeButton.onclick = function() {
+ removeIPField(this);
+ };
+
+ container.appendChild(newField);
+ container.appendChild(removeButton);
+ document.getElementById('ip-fields').appendChild(container);
+ }
+
+ function removeIPField(elem) {
+ const ipFieldsContainer = document.getElementById('ip-fields');
+ const ipFieldDivs = ipFieldsContainer.querySelectorAll('.d-flex');
+
+ if (ipFieldDivs.length <= 1) {
+ return;
+ }
+ const parentDiv = elem.parentElement;
+ parentDiv.remove();
+ }
+</script>
+
+{% endblock %}
diff --git a/ogcp/templates/base.html b/ogcp/templates/base.html
index cd030e8..5d46135 100644
--- a/ogcp/templates/base.html
+++ b/ogcp/templates/base.html
@@ -40,6 +40,9 @@
<a class="nav-link" href="{{ url_for('manage_repos') }}">{{ _('Repos') }}</a>
</li>
{% if current_user.admin %}
+ <li class="nav-item {% block nav_servers %}{% endblock %}">
+ <a class="nav-link" href="{{ url_for('manage_servers') }}">{{ _('Servers') }}</a>
+ </li>
<li class="nav-item {% block nav_users %}{% endblock %}">
<a class="nav-link" href="{{ url_for('users') }}">{{ _('Users') }}</a>
</li>
diff --git a/ogcp/templates/servers.html b/ogcp/templates/servers.html
index bc09c4f..d555f71 100644
--- a/ogcp/templates/servers.html
+++ b/ogcp/templates/servers.html
@@ -17,7 +17,8 @@
<li class="nav-item">
<input class="form-check-input" type="checkbox" form="serversForm"
value="{{ server_str }}"
- name="selected-server" />
+ name="selected-server"
+ {% if loop.index == 1 %}checked{% endif %} />
{{ server["name"] }}
</li>
{% endfor %}
@@ -26,10 +27,8 @@
{% block commands %}
{% if current_user.is_authenticated %}
- <input class="btn btn-light {% block nav_server_add %}{% endblock %}" type="submit" value="{{ _('Add server') }}"
- form="serversForm" formaction="{{ url_for('server_add_get') }}" formmethod="get">
- <input class="btn btn-light {% block nav_server_delete %}{% endblock %}" type="submit" value="{{ _('Delete server') }}"
- form="serversForm" formaction="{{ url_for('server_delete_get') }}" formmethod="get">
+ <input class="btn btn-light {% block nav_server_update %}{% endblock %}" type="submit" value="{{ _('Update server') }}"
+ form="serversForm" formaction="{{ url_for('server_update_get') }}" formmethod="get">
{% if btn_back %}
<button class="btn btn-danger ml-3" type="button" id="backButton" onclick="history.back()">
{{ _("Back") }}
diff --git a/ogcp/views.py b/ogcp/views.py
index 4fa14a9..692bef1 100644
--- a/ogcp/views.py
+++ b/ogcp/views.py
@@ -14,7 +14,8 @@ from ogcp.forms.action_forms import (
RoomForm, DeleteRoomForm, CenterForm, DeleteCenterForm, OgliveForm,
GenericForm, SelectClientForm, ImageUpdateForm, ImportClientsForm,
ServerForm, DeleteRepositoryForm, RepoForm, FolderForm, CacheForm,
- ClientMoveForm, RunScriptForm, ImageConfigForm, ImageFetchForm
+ ClientMoveForm, RunScriptForm, ImageConfigForm, ImageFetchForm,
+ ServerConfigurationForm
)
from flask_login import (
current_user, LoginManager,
@@ -3278,6 +3279,94 @@ def manage_servers():
return render_template('servers.html', servers=servers)
+@app.route('/server/update', methods=['GET'])
+@login_required
+def server_update_get():
+ params = request.args.to_dict()
+ try:
+ selected_server = get_server_from_ip_port(params['selected-server'])
+ except KeyError:
+ flash(_('Please, select one server'), category='error')
+ return redirect(url_for('manage_servers'))
+
+ r = selected_server.get('/server')
+ if not r:
+ return ogserver_down('manage_servers')
+ if r.status_code != requests.codes.ok:
+ return ogserver_error('manage_servers')
+
+ form = ServerConfigurationForm()
+ server_config = r.json()['servers']
+ for c in server_config:
+ form.addr.append_entry(c['address'])
+
+ form.server_addr.data = selected_server.ip + ":" + str(selected_server.port)
+
+ return render_template('actions/server_update.html', form=form,
+ servers=servers)
+
+@app.route('/server/update', methods=['POST'])
+@login_required
+def server_update_post():
+ form = ServerConfigurationForm(request.form)
+ try:
+ server = get_server_from_ip_port(form.server_addr.data)
+ except Exception:
+ flash(_('Server {} does not exist').format(form.server_addr.data),
+ category='error')
+ return redirect(url_for('manage_servers'))
+
+ addr_list = [ip.data.strip() for ip in form.addr]
+ invalid_ips = []
+ for ip in addr_list:
+ if not is_valid_ip(ip):
+ invalid_ips.append('"' + ip + '"')
+
+ if invalid_ips:
+ flash(_(f'The following addresses are invalid: {" ".join(invalid_ips)}'), category='error')
+ return redirect(url_for('manage_servers'))
+
+ r = server.get('/server')
+ if not r:
+ return ogserver_down('manage_servers')
+ if r.status_code != requests.codes.ok:
+ return ogserver_error('manage_servers')
+ server_config = r.json()['servers']
+
+ # Remove
+ for c in server_config:
+ if c['address'] in addr_list:
+ continue
+
+ payload = {'id': c['id']}
+ rd = server.delete('/server', payload=payload)
+ if not rd:
+ return ogserver_down('manage_servers')
+ if rd.status_code != requests.codes.ok:
+ return ogserver_error('manage_servers')
+
+ # Add
+ for ip in addr_list:
+ found = False
+ for c in server_config:
+ if ip == c['address']:
+ found = True
+ break
+
+ if found:
+ continue
+
+ payload = {'address': ip}
+ ra = server.post('/server', payload=payload)
+ if not ra:
+ return ogserver_down('manage_servers')
+ if ra.status_code != requests.codes.ok:
+ return ogserver_error('manage_servers')
+
+ flash(_('Server update request sent successfully'), category='info')
+ return redirect(url_for('manage_servers'))
+
+
@app.route('/server/add', methods=['GET'])
@login_required
def server_add_get():