From f5c4f592630b0158d79a84727b0a6a8550157c4e Mon Sep 17 00:00:00 2001 From: Kevin Puertas Ruiz Date: Mon, 17 Jun 2019 14:02:50 +0200 Subject: [PATCH] Enable setting password. Some EXITCODE for api<->control checking. --- README.MD | 4 +- api.py | 23 +++++--- client/client.ps1 | 2 +- client/configpcm_example.ini | 2 +- client/control.pyw | 108 ++++++++++++++++++++++------------- client/translation.py | 9 ++- 6 files changed, 96 insertions(+), 52 deletions(-) diff --git a/README.MD b/README.MD index 53b91ac..2bc70ca 100644 --- a/README.MD +++ b/README.MD @@ -54,4 +54,6 @@ For server you can use Linux or Windows, and in theory any environment that can - Command: powershell.exe - Args: -executionpolicy bypass -windowstyle hidden -noninteractive -nologo -file "\\SERVER\SysVol\DOMAINNAME\scripts\client.ps1" Note: client.ps1 has to have controlpcm.ini file with it -- If you don't have Active Directory, you can do the Task Scheduled task in every computer without problems, and using another Shared folder, it will work \ No newline at end of file +- If you don't have Active Directory, you can do the Task Scheduled task in every computer without problems, and using another Shared folder, it will work +- Start api.py using .bat o .sh file. You can do in systemd way, or a cron, or in a terminal of windows server,... +- Start control.pyw to setup password and start adding computers, groups and cooks \ No newline at end of file diff --git a/api.py b/api.py index 2e12517..90ae552 100644 --- a/api.py +++ b/api.py @@ -32,6 +32,10 @@ def retPassword(): # /get/computerexists? # @param ComputerName -> Computer to deploy it # @param UUID: Check UUID validation of this computer +# Error exit code: +# 1: No params supplied +# 2: Computer and UUID not match database +# 3: Computer doesn't exists in database ## class getComputerExists(object): def on_get(self, request, response): @@ -44,7 +48,7 @@ class getComputerExists(object): UUID = value if ComputerName is None: - response.media = {'TEXT':'No params','RESULT': 'ERROR'} + response.media = {'TEXT':'No params','RESULT': 'ERROR','EXITCODE':'1'} else: result = sql.select("SELECT COUNT(*) 'RESULT' FROM COMPUTERS WHERE Name='"+ComputerName+"' AND UUID='"+UUID+"'") @@ -60,7 +64,7 @@ class getComputerExists(object): sql.insert("INSERT INTO COMPUTERS (`Name`,`UUID`) VALUES('"+ComputerName+"','"+UUID+"')") response.media = {'RESULT': '1'} else: #Computer doesn't exist and you don't want to be added - response.media = {'TEXT':'Error: Computer not exists in database', 'RESULT': 'ERROR','EXITCODE':'1'} + response.media = {'TEXT':'Error: Computer not exists in database', 'RESULT': 'ERROR','EXITCODE':'3'} else: #Exists response.media = {'RESULT': '1'} @@ -684,6 +688,11 @@ class setCookStatus(object): # checkPassword: Check password # /check/password? # @param Password -> SHA-256 of password +# Error exit code: +# 0: No error +# 1: No password supplied +# 2: Password incorrect +# 3: Password not set in app yet ## class checkPassword(object): #Check password (ERROR if password not valid or no password and 1 if valid) def on_get(self, request, response): @@ -694,18 +703,18 @@ class checkPassword(object): #Check password (ERROR if password not valid or no Password = value if Password is None: - response.media = {'TEXT': 'Error, you need to supply a password','RESULT':'ERROR'} + response.media = {'TEXT': 'Error, you need to supply a password','RESULT':'ERROR','EXITCODE':'1'} else: pass res = sql.select("SELECT COUNT(*) 'RESULT' FROM OPTIONS WHERE Option='Password' AND Value='"+Password+"'")[0]['RESULT'] if res == 1: - response.media = {'RESULT':'1','TEXT':'OK'} + response.media = {'RESULT':'1','TEXT':'OK','EXITCODE':'0'} else: res = sql.select("SELECT COUNT(*) 'RESULT' FROM OPTIONS WHERE Option='Password'")[0]['RESULT'] if res == 0: #Password doesn't exists in database - response.media = {'RESULT':'ERROR','TEXT':'No password set. Please set it'} + response.media = {'RESULT':'ERROR','TEXT':'No password set. Please set it','EXITCODE':'3'} else: - response.media = {'RESULT':'ERROR','TEXT':'Password incorrect'} + response.media = {'RESULT':'ERROR','TEXT':'Password incorrect','EXITCODE':'2'} ## # updPassword: Update password @@ -725,7 +734,7 @@ class updPassword(object): #Update password (ERROR if password not valid or no res = sql.select("SELECT COUNT(*) 'RESULT' FROM OPTIONS WHERE Option='Password'")[0]['RESULT'] if res == 0 and NewPassword is not None: #Password doesn't exists in database - response.media = sql.insert("INSERT INTO COMMENTS VALUES('Password','"+NewPassword+"')") + response.media = sql.insert("INSERT INTO OPTIONS VALUES('Password','"+NewPassword+"')") elif res == 0 and NewPassword is None: #No password supplied response.media = {'RESULT':'ERROR','TEXT':'Error, you need to supply a password'} elif res == 1 and OldPassword is not None: # Password exists in database (And you supplied OldPassword) diff --git a/client/client.ps1 b/client/client.ps1 index 17bc9df..7a88543 100644 --- a/client/client.ps1 +++ b/client/client.ps1 @@ -9,7 +9,7 @@ $UUID=(get-wmiobject Win32_ComputerSystemProduct).UUID $exists = Invoke-RestMethod -Method Get -Uri "$server/get/computerexists?ComputerName=$computerName&UUID=$UUID" if ($exists.Result -eq "ERROR"){ - if ($exists.EXITCODE -eq '1'){ + if ($exists.EXITCODE -eq '3'){ Write-Host "Computer outside database:" $computerName }else{ Write-Host "Computer and UUID of $computerName doesn't match" diff --git a/client/configpcm_example.ini b/client/configpcm_example.ini index 650470a..a3f633d 100644 --- a/client/configpcm_example.ini +++ b/client/configpcm_example.ini @@ -1,3 +1,3 @@ server=http://miserver.dominio:3333 resources=\\\\MISERVER\\REPOFOLDER -lang=es \ No newline at end of file +lang=en \ No newline at end of file diff --git a/client/control.pyw b/client/control.pyw index 93e24f7..ca8df83 100644 --- a/client/control.pyw +++ b/client/control.pyw @@ -5,6 +5,7 @@ import configparser import json import requests import subprocess, platform +import hashlib #SHA256 from translation import T def ping(host): @@ -25,10 +26,11 @@ def sendmenudot(text,title,choices): return menu.split('.')[0] else: return menu -## showchoicesapi, apiurl has to have all (Inlcuding server part) -def showchoicesapi(text,title,apiurl,field='Name'): +## showchoicesapi, suburl has to have params (NOT inlcuding server part) +def showchoicesapi(text,title,suburl,field='Name'): + global c_server try: - jsonobj = json.loads(requests.get(apiurl).text) + jsonobj = json.loads(requests.get(c_server+suburl).text) listitems = [] for ite in jsonobj: listitems.append(ite[field]) @@ -59,9 +61,10 @@ def sendsettoapi(suburl,goodtext): # Send a add/del/modify to API. Doesn't retur easygui.msgbox("Error inesperado","Error","Ok") return 1 -def returnvalueapi(apiurl,field="Name"): +def returnvalueapi(suburl,field="Name"): + global c_server try: - jsonobj = json.loads(requests.get(apiurl).text) + jsonobj = json.loads(requests.get(c_server+suburl).text) return jsonobj[field] except: easygui.msgbox(msg='Error en la aplicación al consultar', title="Error", ok_button='OK') @@ -87,7 +90,6 @@ def menuprinc(): mreports() def mcomputers(): - global c_server menu = sendmenudot(T('Computers menu'),T('Select option'),['1.'+T('Add computer'),'2.'+T('Remove computer'),'3.'+T('Add computer to group'),'4.'+T('Computers list'),'5.'+T('Computer status')]) if menu == '1': @@ -95,32 +97,31 @@ def mcomputers(): if easygui.ynbox("Nombre del equipo: '"+newcomputer+"'. ¿Seguro?",T('Add computer')): sendsettoapi("/add/computer?ComputerName="+newcomputer,"Equipo añadido a la base de datos") elif menu == '2': - whatc = showchoicesapi("Seleccione equipo a borrar",T('Remove computer'),c_server+"/get/computers") + whatc = showchoicesapi("Seleccione equipo a borrar",T('Remove computer'),"/get/computers") if whatc is not None and easygui.ynbox("Se va a borrar el equipo '"+whatc+"'. ¿Seguro?",T('Remove computer')): sendsettoapi("/del/computer?ComputerName="+whatc,T('Computer deleted')) elif menu == '3': m_addcomputergroup() elif menu == '4': - showchoicesapi(T('Computers list'),T('Computers list'),c_server+"/get/computers") + showchoicesapi(T('Computers list'),T('Computers list'),"/get/computers") elif menu == '5': - computer = showchoicesapi(T('Select a computer'),T('Computer status'),c_server+"/get/computers") - showchoicesapi(T('Cooks of computer')+' '+computer,T('Computer status'),c_server+"/get/cookpend?ComputerName="+computer+"&SeeAll=1") - showchoicesapi(T('Cooks pending of computer')+' '+computer,T('Computer status'),c_server+"/get/cookpend?ComputerName="+computer) - showchoicesapi(T('Groups of computer')+' '+computer,T('Computer status'),c_server+"/get/groups?ComputerName="+computer) + computer = showchoicesapi(T('Select a computer'),T('Computer status'),"/get/computers") + showchoicesapi(T('Cooks of computer')+' '+computer,T('Computer status'),"/get/cookpend?ComputerName="+computer+"&SeeAll=1",'CookName') + showchoicesapi(T('Cooks pending of computer')+' '+computer,T('Computer status'),"/get/cookpend?ComputerName="+computer,'CookName') + showchoicesapi(T('Groups of computer')+' '+computer,T('Computer status'),"/get/groups?ComputerName="+computer,'Name') elif menu is None: menuprinc() return mcomputers() def mgroups(): - global c_server menu = sendmenudot(T('Groups menu'),T('Select option'),['1.'+T('Add group'),'2.'+T('Remove group'),'3.'+T('Add computer to group'),'4.'+T('Remove computer of a group'),'5.Listado de grupos','6.Listado de equipos de un grupo']) if menu == '1': newgroup = easygui.enterbox(T('New group name'),T('Add group')) if easygui.ynbox("Nombre del grupo: '"+newgroup+"'. ¿Seguro?",T('Add group')): sendsettoapi("/add/group?GroupName="+newgroup,"Grupo añadido a la base de datos") elif menu == '2': - group = showchoicesapi("Lista de grupos. Selecciona uno para borrarlo",T('Remove group'),c_server+"/get/groups",'Name') + group = showchoicesapi("Lista de grupos. Selecciona uno para borrarlo",T('Remove group'),"/get/groups",'Name') if group is not None and easygui.ynbox("Borrar grupo '"+group+"'. ¿Seguro?",T('Remove group')): sendsettoapi("/del/group?GroupName="+group,T('Group deleted')) elif menu == '3': @@ -128,10 +129,10 @@ def mgroups(): elif menu == '4': m_delcomputergroup() elif menu == '5': - showchoicesapi("Listado de grupos","Listado de grupos",c_server+"/get/groups",field='Name') + showchoicesapi("Listado de grupos","Listado de grupos","/get/groups",field='Name') elif menu == '6': - group = showchoicesapi("Lista de grupos","Listado de equipos de un grupo",c_server+"/get/groups") - showchoicesapi("Lista de equipos del grupo "+group,"Listado de equipos de un grupo",c_server+"/get/computersgrp?GroupName="+group) + group = showchoicesapi("Lista de grupos","Listado de equipos de un grupo","/get/groups") + showchoicesapi("Lista de equipos del grupo "+group,"Listado de equipos de un grupo","/get/computersgrp?GroupName="+group) elif menu is None: menuprinc() return @@ -140,16 +141,16 @@ def mgroups(): def mcooks(): global c_server global c_resources - menu = sendmenudot(T('Cooks menu'),T('Select option'),['1.Detalles de una receta','2.Renombrar receta','3.Añadir receta a un grupo','4.Eliminar receta de un grupo','5.Grupos de una receta']) + menu = sendmenudot(T('Cooks menu'),T('Select option'),['1.Detalles de una receta','2.'+T('Rename cook'),'3.Añadir receta a un grupo','4.Eliminar receta de un grupo','5.Grupos de una receta']) if menu == '1': - cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para ver sus datos","Detalles de una receta",c_server+"/get/cookall",'CookName') + cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para ver sus datos","Detalles de una receta","/get/cookall",'CookName') if cook is not None: - showchoicesapi("Lista de grupos de la receta "+cook,"Listado de grupos de una receta",c_server+"/get/grpcook?CookName="+cook) + showchoicesapi("Lista de grupos de la receta "+cook,"Listado de grupos de una receta","/get/grpcook?CookName="+cook) jsonobj = json.loads(requests.get(c_server+'/get/statuscook?CookName='+cook).text) list = [] s_err = 0 s_com = 0 - s_lastrev = returnvalueapi(c_server+'/get/lastrevisioncook?CookName='+cook,"Revision") + s_lastrev = returnvalueapi('/get/lastrevisioncook?CookName='+cook,"Revision") for ite in jsonobj: s_com = s_com + 1 if ite['Error'] == 0: @@ -161,10 +162,10 @@ def mcooks(): easygui.choicebox("Detalles de equipos de la receta "+cook+"\nEquipos: "+str(s_com)+" Con errores: "+str(s_err)+'\nUltima revision: '+str(s_lastrev),"Detalles de una receta",list) elif menu == '2': - cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para renombrarla. Si la receta no está en ningún grupo, se puede renombrar desde fuera.","Renombrar receta",c_server+"/get/cookall",'CookName') + cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para renombrarla. Si la receta no está en ningún grupo, se puede renombrar desde fuera.",T('Rename cook'),c_server+"/get/cookall",'CookName') if cook is not None: newname = easygui.enterbox("Nombre de la nueva receta","Renombrar receta") - if newname is not None and easygui.ynbox("Cambiar nombre de la receta '"+cook+"' por '"+newname+"'. ¿Seguro?","Renombrar receta"): + if newname is not None and easygui.ynbox("Cambiar nombre de la receta '"+cook+"' por '"+newname+"'. ¿Seguro?",T('Rename cook')): sendsettoapi("/upd/cookname?CookName="+cook+"&CookNewName="+newname,"Receta cambiada de nombre") elif menu == '3': cook = easygui.enterbox(T('Name of the cook'),"Añadir receta a un grupo") @@ -172,15 +173,15 @@ def mcooks(): if easygui.ynbox("Añadir la receta "+cook+" al grupo '"+group+"'. ¿Seguro?","Añadir receta a un grupo"): sendsettoapi("/add/cookgrp?CookName="+cook+"&GroupName="+group,"Receta añadida al grupo") elif menu == '4': - cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para elegir un grupo de esa receta para borrar. Si la receta no está en ningún grupo, no saldrá.","Eliminar receta de un grupo",c_server+"/get/cookall",'CookName') + cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para elegir un grupo de esa receta para borrar. Si la receta no está en ningún grupo, no saldrá.","Eliminar receta de un grupo","/get/cookall",'CookName') if cook is not None: - group = showchoicesapi("Lista de grupos que tienen esa receta. Selecciona el grupo a quitar","Eliminar receta de un grupo",c_server+"/get/grpcook?CookName="+cook,'Name') + group = showchoicesapi("Lista de grupos que tienen esa receta. Selecciona el grupo a quitar","Eliminar receta de un grupo","/get/grpcook?CookName="+cook,'Name') if group is not None and easygui.ynbox("Se va a quitar la receta "+cook+" del grupo "+group+". ¿Seguro?","Eliminar receta de un grupo"): sendsettoapi("/del/cookgrp?CookName="+cook+"&GroupName="+group,"Receta quitada del grupo") elif menu == '5': - cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para elegir un grupo de esa receta para borrar. Si la receta no está en ningún grupo, no saldrá.","Eliminar receta de un grupo",c_server+"/get/cookall",'CookName') + cook = showchoicesapi("Lista de recetas implementadas en algún grupo. Selecciona una para elegir un grupo de esa receta para borrar. Si la receta no está en ningún grupo, no saldrá.","Eliminar receta de un grupo","/get/cookall",'CookName') if cook is not None: - showchoicesapi("Lista de grupos que tienen esa receta. Selecciona el grupo a quitar","Eliminar receta de un grupo",c_server+"/get/grpcook?CookName="+cook,'Name') + showchoicesapi("Lista de grupos que tienen esa receta. Selecciona el grupo a quitar","Eliminar receta de un grupo","/get/grpcook?CookName="+cook,'Name') elif menu is None: menuprinc() return @@ -188,22 +189,20 @@ def mcooks(): mcooks() def mreports(): - global c_server - global c_resources menu = sendmenudot(T('Reports menu'),T('Select option'),['1.'+T('Computers list'),'2.'+T('Groups list'),'3.Equipos y recetas de un grupo','4.Grupos de una receta']) if menu == '1': #Listado de equipos - showchoicesapi(T('Computers list'),T('Computers list'),c_server+"/get/computers") + showchoicesapi(T('Computers list'),T('Computers list'),"/get/computers") elif menu == '2': #Listado de grupos - showchoicesapi(T('Groups list'),T('Groups list'),c_server+"/get/groups") + showchoicesapi(T('Groups list'),T('Groups list'),"/get/groups") elif menu == '3': - group = showchoicesapi(T('Groups list')+'. '+T('Select a group'),T('Groups list'),c_server+"/get/groups") - showchoicesapi("Lista de equipos del grupo "+group,T('List of computers and cooks of a group'),c_server+"/get/computersgrp?GroupName="+group) - showchoicesapi("Lista de recetas del grupo "+group,T('List of computers and cooks of a group'),c_server+"/get/cookgrp?GroupName="+group,'CookName') + group = showchoicesapi(T('Groups list')+'. '+T('Select a group'),T('Groups list'),"/get/groups") + showchoicesapi("Lista de equipos del grupo "+group,T('List of computers and cooks of a group'),"/get/computersgrp?GroupName="+group) + showchoicesapi("Lista de recetas del grupo "+group,T('List of computers and cooks of a group'),"/get/cookgrp?GroupName="+group,'CookName') elif menu == '4': - cook = showchoicesapi("Lista de recetas con grupo. Selecciona una para ver sus grupos","Listado de grupos de una receta",c_server+"/get/cookall",'CookName') + cook = showchoicesapi("Lista de recetas con grupo. Selecciona una para ver sus grupos",T('List of groups of a cook'),"/get/cookall",'CookName') if cook is not None: - showchoicesapi("Lista de grupos de la receta "+cook,T('List of groups of a cook'),c_server+"/get/grpcook?CookName="+cook) + showchoicesapi("Lista de grupos de la receta "+cook,T('List of groups of a cook'),"/get/grpcook?CookName="+cook) elif menu is None: menuprinc() return @@ -211,22 +210,49 @@ def mreports(): def m_addcomputergroup(): - whatc = showchoicesapi(T('Select computer to add to a group'),T('Add computer to group'),c_server+"/get/computers") + whatc = showchoicesapi(T('Select computer to add to a group'),T('Add computer to group'),"/get/computers") if whatc is None: return - whatg = showchoicesapi(T('Select group to be added'),T('Add computer to group'),c_server+"/get/groups") + whatg = showchoicesapi(T('Select group to be added'),T('Add computer to group'),"/get/groups") if whatg is None: return sendsettoapi("/add/grpcomputer?ComputerName="+whatc+"&GroupName="+whatg,"Equipo añadido al grupo") def m_delcomputergroup(): - computer = showchoicesapi("Seleccione equipo para buscar un grupo que borrar",T('Remove computer of a group'),c_server+"/get/computers") + computer = showchoicesapi("Seleccione equipo para buscar un grupo que borrar",T('Remove computer of a group'),"/get/computers") if computer is None: return - group = showchoicesapi(T('Select group to delete'),T('Remove computer of a group'),c_server+"/get/groups?ComputerName="+computer) + group = showchoicesapi(T('Select group to delete'),T('Remove computer of a group'),"/get/groups?ComputerName="+computer) if group is None: return if easygui.ynbox("Quitar el equipo "+computer+" del grupo '"+group+"'. ¿Seguro?",T('Remove computer of a group')): sendsettoapi("/del/grpcomputer?ComputerName="+computer+"&GroupName="+group,"Equipo quitado del grupo") -menuprinc() + + +# Check password before starting all +pa = returnvalueapi("/check/password?Password=None",field="EXITCODE") +if pa == "3": # No password stored yet + passw = easygui.passwordbox(T('There is no password yet in PCM. Please set one below'),T('Set password')) + passw2 = easygui.passwordbox(T('Confirm it'),T('Set password')) + + if passw==passw2 and passw is not None: # Password match + passha256 = hashlib.sha256(passw.encode()).hexdigest() + re = returnvalueapi("/upd/password?NewPassword="+passha256,field="RESULT") # Create password in database + if re=='OK': # All right. Start app + menuprinc() + else: # Fail. Not controlled + easygui.msgbox(T('Error unespecified. App will exit'),T('Set password')) + else: # Password not match + easygui.msgbox(T('Password not match. App will exit'),T('Set password')) + #Exit +else: # There is a password + passw = easygui.passwordbox(T('Enter password to start'),T('Enter password')) + if passw is None: + quit() + passha256 = hashlib.sha256(passw.encode()).hexdigest() + re = returnvalueapi("/check/password?Password="+passha256,field="EXITCODE") # Create password in database + if re == '0': # Password is right + menuprinc() + else: + easygui.msgbox(T('Password not match. App will exit'),T('Enter password')) \ No newline at end of file diff --git a/client/translation.py b/client/translation.py index 01cf3b6..84d8c75 100644 --- a/client/translation.py +++ b/client/translation.py @@ -53,7 +53,14 @@ def T_es(textid): 'List of groups of a cook':'Listado de grupos de una receta', 'Select computer to add to a group':'Seleccione equipo para añadir a un grupo', 'Select group to be added':'Seleccione grupo a ser añadido', - 'Select group to delete':'Seleccione grupo a quitar' + 'Select group to delete':'Seleccione grupo a quitar', + 'Rename cook': 'Renombrar receta', + 'Set password':'Establecer contraseña', + 'There is no password yet in PCM. Please set one below':'No hay contraseña aún en PCM. Por favor, escriba una debajo', + 'Confirm it':'Confirmalo', + 'Password not match. App will exit':'Las contraseñas no coinciden. La aplicación se va a cerrar', + 'Enter password':'Introducir contraseña', + 'Enter password to start':'Introduzca la contraseña para empezar' } return dict[textid]