diff options
-rw-r--r-- | ogcp/forms/action_forms.py | 8 | ||||
-rw-r--r-- | ogcp/og_server.py | 6 | ||||
-rw-r--r-- | ogcp/templates/actions/server_update.html | 69 | ||||
-rw-r--r-- | ogcp/templates/base.html | 3 | ||||
-rw-r--r-- | ogcp/templates/servers.html | 9 | ||||
-rw-r--r-- | ogcp/views.py | 91 |
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(): |