From aabb2d01077e8128ddaf7ca288623c56657545d5 Mon Sep 17 00:00:00 2001
From: shinedday <shinedday@gmail.com>
Date: Tue, 10 May 2022 18:02:55 +0200
Subject: [PATCH] Ping button

---
 .gitignore                      |   7 ++
 db.sqlite3                      | Bin 0 -> 139264 bytes
 iotamak_ihm/__init__.py         |   0
 iotamak_ihm/asgi.py             |  16 +++++
 iotamak_ihm/settings.py         | 124 ++++++++++++++++++++++++++++++++
 iotamak_ihm/urls.py             |  22 ++++++
 iotamak_ihm/wsgi.py             |  16 +++++
 manage.py                       |  22 ++++++
 ping/__init__.py                |   0
 ping/admin.py                   |   5 ++
 ping/apps.py                    |   6 ++
 ping/migrations/0001_initial.py |  22 ++++++
 ping/migrations/__init__.py     |   0
 ping/models.py                  |  10 +++
 ping/templates/ping/index.html  |  19 +++++
 ping/tests.py                   |   3 +
 ping/urls.py                    |   9 +++
 ping/views.py                   |  28 ++++++++
 18 files changed, 309 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 db.sqlite3
 create mode 100644 iotamak_ihm/__init__.py
 create mode 100644 iotamak_ihm/asgi.py
 create mode 100644 iotamak_ihm/settings.py
 create mode 100644 iotamak_ihm/urls.py
 create mode 100644 iotamak_ihm/wsgi.py
 create mode 100644 manage.py
 create mode 100644 ping/__init__.py
 create mode 100644 ping/admin.py
 create mode 100644 ping/apps.py
 create mode 100644 ping/migrations/0001_initial.py
 create mode 100644 ping/migrations/__init__.py
 create mode 100644 ping/models.py
 create mode 100644 ping/templates/ping/index.html
 create mode 100644 ping/tests.py
 create mode 100644 ping/urls.py
 create mode 100644 ping/views.py

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5cc30b1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+desktop.ini
+.git
+.vscode
+.idea
+venv
+*.bat
+__pycache__/
\ No newline at end of file
diff --git a/db.sqlite3 b/db.sqlite3
new file mode 100644
index 0000000000000000000000000000000000000000..432f204be352251f792e0f91a1b7377303918b43
GIT binary patch
literal 139264
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

literal 0
HcmV?d00001

diff --git a/iotamak_ihm/__init__.py b/iotamak_ihm/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/iotamak_ihm/asgi.py b/iotamak_ihm/asgi.py
new file mode 100644
index 0000000..ff61e51
--- /dev/null
+++ b/iotamak_ihm/asgi.py
@@ -0,0 +1,16 @@
+"""
+ASGI config for iotamak_ihm project.
+
+It exposes the ASGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'iotamak_ihm.settings')
+
+application = get_asgi_application()
diff --git a/iotamak_ihm/settings.py b/iotamak_ihm/settings.py
new file mode 100644
index 0000000..fd177df
--- /dev/null
+++ b/iotamak_ihm/settings.py
@@ -0,0 +1,124 @@
+"""
+Django settings for iotamak_ihm project.
+
+Generated by 'django-admin startproject' using Django 4.0.4.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.0/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/4.0/ref/settings/
+"""
+
+from pathlib import Path
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'django-insecure-4k7u!g0ygu8#@231^m&75^_w*28qi_q8#64x5d5u0$j$-*5%2%'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+    'ping.apps.PingConfig',
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+]
+
+MIDDLEWARE = [
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'iotamak_ihm.urls'
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'iotamak_ihm.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': BASE_DIR / 'db.sqlite3',
+    }
+}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/4.0/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'Europe/Paris'
+
+USE_I18N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/4.0/howto/static-files/
+
+STATIC_URL = 'static/'
+
+# Default primary key field type
+# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
diff --git a/iotamak_ihm/urls.py b/iotamak_ihm/urls.py
new file mode 100644
index 0000000..d502811
--- /dev/null
+++ b/iotamak_ihm/urls.py
@@ -0,0 +1,22 @@
+"""iotamak_ihm URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/4.0/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+from django.urls import path, include
+
+urlpatterns = [
+    path('ping/', include('ping.urls')),
+    path('admin/', admin.site.urls),
+]
diff --git a/iotamak_ihm/wsgi.py b/iotamak_ihm/wsgi.py
new file mode 100644
index 0000000..bbe25cc
--- /dev/null
+++ b/iotamak_ihm/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for iotamak_ihm project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'iotamak_ihm.settings')
+
+application = get_wsgi_application()
diff --git a/manage.py b/manage.py
new file mode 100644
index 0000000..0720a2a
--- /dev/null
+++ b/manage.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+    """Run administrative tasks."""
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'iotamak_ihm.settings')
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/ping/__init__.py b/ping/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ping/admin.py b/ping/admin.py
new file mode 100644
index 0000000..7e490c7
--- /dev/null
+++ b/ping/admin.py
@@ -0,0 +1,5 @@
+from django.contrib import admin
+
+from .models import Client
+
+admin.site.register(Client)
\ No newline at end of file
diff --git a/ping/apps.py b/ping/apps.py
new file mode 100644
index 0000000..a57bed9
--- /dev/null
+++ b/ping/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class PingConfig(AppConfig):
+    default_auto_field = 'django.db.models.BigAutoField'
+    name = 'ping'
diff --git a/ping/migrations/0001_initial.py b/ping/migrations/0001_initial.py
new file mode 100644
index 0000000..7eda40b
--- /dev/null
+++ b/ping/migrations/0001_initial.py
@@ -0,0 +1,22 @@
+# Generated by Django 4.0.4 on 2022-05-10 15:39
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Client',
+            fields=[
+                ('hostname', models.CharField(max_length=16, primary_key=True, serialize=False, unique=True)),
+                ('username', models.CharField(max_length=16)),
+                ('password', models.CharField(max_length=16)),
+            ],
+        ),
+    ]
diff --git a/ping/migrations/__init__.py b/ping/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ping/models.py b/ping/models.py
new file mode 100644
index 0000000..7a1725a
--- /dev/null
+++ b/ping/models.py
@@ -0,0 +1,10 @@
+from django.db import models
+
+
+class Client(models.Model):
+    hostname = models.CharField(max_length=16, primary_key=True, unique=True)
+    username = models.CharField(max_length=16)
+    password = models.CharField(max_length=16)
+
+    def __str__(self):
+        return "Hostname : " + self.hostname + " Username : " + self.username
\ No newline at end of file
diff --git a/ping/templates/ping/index.html b/ping/templates/ping/index.html
new file mode 100644
index 0000000..02097b4
--- /dev/null
+++ b/ping/templates/ping/index.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Main menu</title>
+  </head>
+  <body>
+    <form action='pressed' method='GET'>
+        <button type='submit'> Ping clients</button>
+    </form>
+
+    <ul>
+        {% for client in host_list %}
+            <li>{{client}}</li>
+        {% endfor %}
+    </ul>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/ping/tests.py b/ping/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/ping/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/ping/urls.py b/ping/urls.py
new file mode 100644
index 0000000..de7ace3
--- /dev/null
+++ b/ping/urls.py
@@ -0,0 +1,9 @@
+from django.urls import path
+
+from . import views
+
+app_name = 'ping'
+urlpatterns = [
+    path('', views.index, name='index'),
+    path('pressed/', views.pressed, name='pressed'),
+]
\ No newline at end of file
diff --git a/ping/views.py b/ping/views.py
new file mode 100644
index 0000000..948a0fa
--- /dev/null
+++ b/ping/views.py
@@ -0,0 +1,28 @@
+import platform
+import subprocess
+
+from django.http import HttpResponse, HttpResponseRedirect
+from django.template import loader
+from django.urls import reverse
+
+from .models import Client
+
+
+def index(request):
+    template = loader.get_template('ping/index.html')
+    host_list = Client.objects.all()
+    context = {
+        "host_list": host_list,
+    }
+    return HttpResponse(template.render(context, request))
+
+def pressed(request):
+    for client in Client.objects.all():
+        param = '-n' if platform.system().lower() == 'windows' else '-c'
+        command = ['ping', param, '1', client.hostname]
+
+        response = subprocess.call(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0
+
+        print(response)
+
+    return HttpResponseRedirect(reverse('ping:index'))
\ No newline at end of file
-- 
GitLab