26 Commits
docker ... dev

Author SHA1 Message Date
dalvarezgon
4aeec0c31b Modificación y borrado de especialidades 2019-12-21 23:10:13 +01:00
Marcos Garcia Nuñez
b815680649 Configuración de opciones de menú para evitar word-wrap. 2019-12-20 19:05:36 +01:00
Marcos Garcia Nuñez
992fc3e25a Configruación de excepciones y redirección a página de errores. 2019-12-20 17:58:34 +01:00
Marcos Garcia Nuñez
ed78633291 Nuevo método para obtener la causa raiz de una excepción. 2019-12-20 17:57:56 +01:00
Marcos Garcia Nuñez
c8a3f1e933 Adaptación de página general de errores para mostrar diferentes tipos de
excepciones.
2019-12-20 17:57:40 +01:00
Marcos Garcia Nuñez
02ea97195f Gestión de excepciones en el filtro de autorización. 2019-12-20 17:57:07 +01:00
Marcos Garcia Nuñez
ebc33396c7 Ignorar si el archivo existe o no a la hora de eliminarlo .gitlab-ci.yml 2019-12-20 08:19:04 +01:00
Marcos Garcia Nuñez
2dc7c9b8b7 Eliminación de ear anterior desplegado, previo al despliegue del nuevo. 2019-12-20 08:14:21 +01:00
Marcos Garcia Nuñez
83e3fb9867 Update .gitlab-ci.yml 2019-12-20 08:07:58 +01:00
Marcos Garcia Nuñez
a83b273955 Renombrado a nombre sin espacio 02.Datos_prueba.sql 2019-12-20 07:50:20 +01:00
dalvarezgon
310aae76ef Mensajes tipo growl 2019-12-20 00:34:55 +01:00
Marcos Garcia Nuñez
06114b7e2f Redirección de excepciones a la página de error. 2019-12-20 00:19:58 +01:00
Marcos Garcia Nuñez
952417c6ce Control de error con sessión expirada (propiedad nula) 2019-12-20 00:05:22 +01:00
Marcos Garcia Nuñez
1dff9b09e8 Control de parametros nulos. 2019-12-20 00:04:58 +01:00
Marcos Garcia Nuñez
aeb1d300a4 Mejora en el control de excepciones. 2019-12-20 00:04:41 +01:00
Marcos Garcia Nuñez
66a00616e5 Filtro para peticiones AJAX y detección de sesión expirada. 2019-12-20 00:04:17 +01:00
Marcos Garcia Nuñez
318680d5c0 Mensajes diferentes en función del tipo de error. 2019-12-19 23:59:40 +01:00
Marcos Garcia Nuñez
8482b660c1 funcion AJAX para interceptar errores en peticiones AJAX (no funciona). 2019-12-19 23:59:11 +01:00
Marcos Garcia Nuñez
e789cb57d2 omnifaces AjaxExceptionHandler para gestionar las excpeciones AJAX. 2019-12-19 23:57:40 +01:00
Marcos Garcia Nuñez
ffe56f3c68 Cambiados mensajes a tipo growl (superpuestos sobre la interfaz). 2019-12-19 20:48:03 +01:00
dalvarezgon
b2e55231ea Mensajes movidos al pie con autoclose 2019-12-19 16:48:55 +01:00
dalvarezgon
1e3886cc54 Especialidades médicas editables 2019-12-19 13:15:11 +01:00
Marcos Garcia Nuñez
492ddad057 Creación de instrucciones de instalación y despliegue. 2019-12-19 11:30:32 +01:00
Marcos Garcia Nuñez
7891777ecf Update README.md 2019-12-19 11:28:51 +01:00
Marcos Garcia Nuñez
01f0f5627f Gestión de excepciones y fin de sesión 2019-12-19 00:09:48 +01:00
Marcos Garcia Nuñez
25a4896426 Corrección de datos, campo enumerado como string en los datos de prueba. 2019-12-19 00:09:01 +01:00
27 changed files with 572 additions and 317 deletions

View File

@@ -14,7 +14,7 @@ ci_build:
script:
- cd 1.sources/MyHealth
- ant clean
- ant all
- ant ear
ci_test:
stage: test
@@ -25,10 +25,13 @@ ci_test:
deploy_pre:
stage: deploy
script:
- echo "Eliminamos archivo ear anterior..."
- rm -f $JBOSS_HOME/standalone/deployments/MyHealth.*
- echo "Despliegue al servidor de PRE"
- cd 1.sources/MyHealth
- ant deployear
environment:
name: pre
url: https://localhost:8080/MyHealth
@@ -38,6 +41,8 @@ deploy_pre:
deploy_pro:
stage: deploy
script:
- echo "Eliminamos archivo ear anterior..."
- rm -f $JBOSS_HOME/standalone/deployments/MyHealth.*
- echo "Despliegue al servidor de PRO"
- cd 1.sources/MyHealth
- ant deployear

View File

@@ -2,4 +2,7 @@
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd" version="2.3">
<factory>
<exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
</faces-config>

View File

@@ -18,7 +18,10 @@
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
@@ -27,8 +30,6 @@
<param-name>primefaces.FONT_AWESOME</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>#{sessionPreferences.currentTheme}</param-value>
@@ -42,36 +43,59 @@
</servlet>
<!-- Map these files with JSF -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<!-- Filters -->
<filter>
<filter-name>facesExceptionFilter</filter-name>
<filter-class>org.omnifaces.filter.FacesExceptionFilter</filter-class>
</filter>
<!-- Filter mappings -->
<filter-mapping>
<filter-name>facesExceptionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Error pages mapping -->
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/error.xhtml?type=expired</location>
</error-page>
<error-page>
<exception-type>java.sql.SQLException</exception-type>
<exception-type>org.hibernate.exception.GenericJDBCException</exception-type>
<exception-type>java.net.ConnectException</exception-type>
<exception-type>javax.persistence.PersistenceException</exception-type>
<location>/error.xhtml?type=sql</location>
</error-page>
<error-page>
<exception-type>javax.persistence.PersistenceException</exception-type>
<location>/error.xhtml?type=runtime</location>
</error-page>
<error-page>
<exception-type>java.net.ConnectException</exception-type>
<location>/error.xhtml?type=sql</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.xhtml</location>
</error-page>
<error-page>
<error-code>401</error-code>
<location>/error.xhtml?type=expired</location>
</error-page>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<!-- The Welcome File List -->
<welcome-file-list>
<welcome-file>home.xhtml</welcome-file>
<welcome-file>/home.xhtml</welcome-file>
</welcome-file-list>
</web-app>

View File

@@ -2,7 +2,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui">
<ui:composition template="./header.xhtml">
<ui:define name="content">
@@ -12,16 +12,23 @@
<div class="ui-g-8 ui-md-8">
<p:panel id="ErrorPanel">
<f:facet name="header">
<p:outputLabel value="Se ha producido un error de autorización" rendered="#{param.type == 'auth'}" />
<p:outputLabel value="Se ha producido un error desconocido" rendered="#{param.type == null}" />
<p:outputLabel rendered="#{param.type == 'sql'}" value="No se puede conectar con la base de datos" />
<p:outputLabel rendered="#{param.type == 'auth'}" value="Se ha producido un error de autorización" />
<p:outputLabel rendered="#{param.type == 'expired'}" value="Su sesión ha caducado" />
<p:outputLabel rendered="#{param.type == 'runtime'}" value="Se producido un error en tiempo de ejecución" />
<p:outputLabel rendered="#{param.type == '' or param.type == null}" value="Se ha producido un error desconocido" />
</f:facet>
<div class="ui-g ui-fluid">
<div class="ui-g-12">La acción que estaba realizando a causado un error inesperado en el sistema. A continuación podrá ver un descripción detallada del error para que
pueda comunicarlo al equipo de soporte.</div>
<div class="ui-g-12" style="font-weight: bold;">
<!-- <p:outputLabel value="No está autorizado a acceder a la página solicitada. Por favor, utilice el menú principal de la aplicación." rendered="#{param.type == 'auth'}" /> -->
<!-- <p:outputLabel value="Se ha producido un error desconocido. Si vuelve a repetirse, por favor, contacte con el equipo de soporte." rendered="#{param.type == null}" /> -->
<div class="ui-g-12">
<p:outputLabel rendered="#{param.type == 'sql'}"
value="No ha sido posible realizar una conexión con el servidor de base de datos subyante, o ha ocurrido un error grave cuando se intentaba realizar la conexión. Por favor contacte con el equipo de soporte." />
<p:outputLabel rendered="#{param.type == 'auth'}"
value="No está autorizado a ver la url consultada. Por favor, vaya a la página principal y utilice el menú de la aplicación para acceder las funcionalidades disponibles." />
<p:outputLabel rendered="#{param.type == 'expired'}" value="Su sesión ha caducado. Por favor, incie sesión de nuevo en el sistema." />
<p:outputLabel rendered="#{param.type == 'runtime'}"
value="Se ha producido un error en el servidor durante la ejecución de la última acción. Por favor, intentelo de nuevo o contacte con el equipo de soporte." />
<p:outputLabel rendered="#{param.type == '' or param.type == null}"
value="La acción que estaba realizando a causado un error inesperado en el sistema. A continuación podrá ver un descripción detallada del error para que pueda comunicarlo al equipo de soporte." />
</div>
<div class="ui-g-12">

View File

@@ -2,7 +2,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
@@ -25,23 +25,24 @@
function startLogin() {
PF('btnLogin').disable();
}
function onAjaxError() {
alert('Ajax error');
}
</h:outputScript>
<h:body>
<p:growl id="messages" globalOnly="true" sticky="false" showDetail="true" life="15000" />
<div id="layout">
<div id="top" class="top">
<p:growl id="messages" globalOnly="true" sticky="false" showDetail="true" life="15000" />
<h:graphicImage library="images" name="logo-small.png" />
</div>
<hr />
<div id="menuDiv">
<p:ajaxStatus style="width:32px; height:32px; position:fixed; right:32px; bottom:32px">
<div id="menuDiv" style="margin-bottom: 10px;">
<p:ajaxStatus style="width:32px; height:32px; position:fixed; right:32px; bottom:32px" onerror="onAjaxError()">
<f:facet name="start">
<i id="loginSpin" class="pi pi-spin pi-spinner" style="font-size: 3em"></i>
</f:facet>
<f:facet name="complete">
<h:outputText value="" />
</f:facet>
<f:facet name="error">Error!</f:facet>
</p:ajaxStatus>
<h:form id="frmLogin">

View File

@@ -2,7 +2,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui">
<f:metadata>
<f:viewParam name="refresh" value="#{home.refresh}" />
</f:metadata>
@@ -10,7 +10,7 @@
<ui:composition template="./header.xhtml">
<ui:define name="content">
<h:form>
<p:messages id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:growl id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:panel header="Pagina principal">
<div class="ui-g ui-fluid">
<div class="ui-g-2 ui-md-2">

View File

@@ -2,7 +2,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui">
<h:head>
<title>login</title>

View File

@@ -1,51 +0,0 @@
<h:form>
<p:growl id="messages" />
<p:menubar>
<p:submenu label="File" icon="pi pi-file">
<p:submenu label="New" icon="pi pi-briefcase">
<p:menuitem value="Project" url="#" />
<p:menuitem value="Other" url="#" />
</p:submenu>
<p:menuitem value="Open" url="#" />
<p:separator />
<p:menuitem value="Quit" url="#" />
</p:submenu>
<p:submenu label="Edit" icon="pi pi-pencil">
<p:menuitem value="Undo" url="#" icon="pi pi-angle-double-left" />
<p:menuitem value="Redo" url="#" icon="pi pi-angle-double-right" />
</p:submenu>
<p:submenu label="Help" icon="pi pi-question">
<p:menuitem value="Contents" url="#" />
<p:submenu label="Search" icon="pi pi-search">
<p:submenu label="Text">
<p:menuitem value="Workspace" url="#" />
</p:submenu>
<p:menuitem value="File" url="#" />
</p:submenu>
</p:submenu>
<p:submenu label="Actions" icon="pi pi-cog">
<p:submenu label="Ajax" icon="pi pi-refresh">
<p:menuitem value="Save" action="#{menuView.save}" icon="pi pi-save"
update="messages" />
<p:menuitem value="Update" action="#{menuView.update}"
icon="pi pi-refresh" update="messages" />
</p:submenu>
<p:submenu label="Non-Ajax" icon="pi pi-clone">
<p:menuitem value="Delete" action="#{menuView.delete}"
icon="pi pi-times" update="messages" ajax="false" />
</p:submenu>
</p:submenu>
<p:menuitem value="Quit" url="http://www.primefaces.org"
icon="pi pi-times" />
<f:facet name="options">
<p:inputText style="margin:1px 10px 1px 1px;" placeholder="Search" />
<p:commandButton type="button" value="Logout" icon="pi pi-home" />
</f:facet>
</p:menubar>
</h:form>

View File

@@ -7,7 +7,7 @@
<ui:composition template="../header.xhtml">
<ui:define name="content">
<h:form id="frmChangeFD">
<p:messages id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:growl id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:panel id="badProfile" rendered="#{not home.patient}">
<div class="ui-g-3 ui-md-3" />
<div class="ui-g-6 ui-md-6">

View File

@@ -7,7 +7,7 @@
<ui:composition template="../header.xhtml">
<ui:define name="content">
<h:form id="frmChangePHCC">
<p:messages id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:growl id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:panel id="badProfile" rendered="#{not home.familyDoctor}">
<div class="ui-g-3 ui-md-3" />
<div class="ui-g-6 ui-md-6">

View File

@@ -63,7 +63,7 @@
}
}
</h:outputScript>
<p:messages id="mesgs" globalOnly="true" showDetail="true" closable="true" autoupdate="true" />
<p:growl id="mesgs" globalOnly="true" showDetail="true" closable="true" autoupdate="true" />
<p:panel id="tipoUsuario" header="Especifique el tipo de usuario que desea registrarse">
<div class="ui-g ui-fluid">
<div class="ui-g-2 ui-md-2">

View File

@@ -26,7 +26,7 @@
}
}
</h:outputScript>
<p:messages id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:growl id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:panel id="tipoUsuario" header="Tipo de usuario registrado">
<div class="ui-g ui-fluid">

View File

@@ -11,6 +11,11 @@ BODY {
margin: 0 !important;
}
ul.ui-menu-child {
white-space: nowrap;
width: auto !important;
}
.green-button.ui-button.ui-state-default {
background-color: #5cb85c;
border-color: #5cb85c;

View File

@@ -7,24 +7,58 @@
<ui:composition template="../header.xhtml">
<ui:define name="content">
<h:form id="frmManageSpecialties">
<p:messages id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:panel id="PanelMS" header="Página Gestión de Especialidades">
<p:growl id="mesgs" showDetail="true" closable="true" autoupdate="true" />
<p:panel id="PanelMS" header="Modificación y borrado de especialidades">
<div class="ui-g ui-fluid">
<div class="ui-g-2 ui-md-2">
<p:autoComplete id="specialty" dropdown="true" required="true"
value="#{SystemAdmin.medicalSpecialty}" completeMethod="#{SystemAdmin.completeMedicalSpecialty}" var="ms"
placeholder="----- Selecciona una especialidad -----" itemLabel="#{ms.name}" itemValue="#{ms.name}" forceSelection="true">
<o:converter converterId="omnifaces.ListConverter" list="#{RegisterUser.medicalSpecialtiesList}" />
<p:column>
<h:outputText value="#{ms.name}" />
</p:column>
</p:autoComplete>
<p:outputLabel for="ms"/>
<p:selectOneMenu id="ms" value="#{ManageSpecialities.medicalSpecialty}" converter="omnifaces.SelectItemsIndexConverter"
effect="fold" editable="true" filter="true" filterMatchMode="startsWith"
placeholder="- Selecciona una especialidad -">
<f:selectItems value="#{ManageSpecialities.medicalSpecialtiesList}" var="ms" itemValue="#{ms}" itemLabel="#{ms.name}" />
<f:ajax render="name description" />
</p:selectOneMenu>
</div>
<div class="ui-g-1 ui-md-1" >
<p:outputLabel value="Nombre: " for="name"/>
</div>
<div class="ui-g-2 ui-md-2">
<p:inputText id="name" value="#{ManageSpecialities.medicalSpecialty.name}" readonly="false" required="true" requiredMessage="Es necesario un nombre" />
</div>
<div class="ui-g-1 ui-md-1">
<p:outputLabel value="Descripción: " for="description" />
</div>
<div class="ui-g-4 ui-md-4">
<p:message for="specialty" />
<p:inputText id="description" value="#{ManageSpecialities.medicalSpecialty.description}" readonly="false" required="true" requiredMessage="Es necesaria una descripción" />
</div>
</div>
</p:panel>
<div class="ui-g-1 ui-md-1 ">
<p:commandButton validateClient="true" value="Guardar" update="mesgs" action="#{ManageSpecialities.saveData}" icon="pi pi-save" />
</div>
<div class="ui-g-1 ui-md-1 ">
<p:commandButton validateClient="true" value="Borrar" update="mesgs" action="#{ManageSpecialities.deleteData}" icon="fa fa-remove" />
</div>
</div>
</p:panel>
<p:panel id="PanelNewMS" header="Alta de especialidades">
<div class="ui-g ui-fluid">
<div class="ui-g-1 ui-md-1" >
<p:outputLabel value="Nombre: " for="nameNew"/>
</div>
<div class="ui-g-2 ui-md-2">
<p:inputText id="nameNew" value="#{ManageSpecialities.name}" readonly="false" required="ManageSpecialities.medicalSpecialty.name eq null" requiredMessage="Es necesario un nombre" />
</div>
<div class="ui-g-1 ui-md-1">
<p:outputLabel value="Descripción: " for="descriptionNew" />
</div>
<div class="ui-g-6 ui-md-6">
<p:inputText id="descriptionNew" value="#{ManageSpecialities.description}" readonly="false" required="ManageSpecialities.medicalSpecialty.description eq null" requiredMessage="Es necesaria una descripción" />
</div>
<div class="ui-g-2 ui-md-2 ">
<p:commandButton validateClient="true" value="Crear" update="mesgs" action="#{ManageSpecialities.insertData}" icon="pi pi-check" />
</div>
</div>
</p:panel>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -9,7 +9,7 @@ import javax.xml.bind.annotation.XmlRootElement;
* @author Marcos García Núñez (mgarcianun@uoc.edu)
*
*/
@XmlRootElement(name = "medicalspeciality")
@XmlRootElement(name = "medicalSpecialty")
public class MedicalSpecialtyTO implements Serializable {
private static final long serialVersionUID = 1L;

View File

@@ -1,6 +1,7 @@
package common;
import java.text.Normalizer;
import java.util.Objects;
/**
*
@@ -13,7 +14,16 @@ public class Utils {
}
public static String normalizeTerm(String input) {
//return stripAccents(input).toLowerCase();
// return stripAccents(input).toLowerCase();
return input.toLowerCase();
}
public static Throwable getExceptionRootCause(Throwable throwable) {
Objects.requireNonNull(throwable);
Throwable rootCause = throwable;
while (rootCause.getCause() != null && rootCause.getCause() != rootCause) {
rootCause = rootCause.getCause();
}
return rootCause;
}
}

View File

@@ -7,6 +7,7 @@ import javax.persistence.PersistenceContext;
import TO.FamilyDoctorTO;
import TO.LoggedUserTO;
import TO.MedicalSpecialtyTO;
import TO.PatientTO;
import TO.SpecialistDoctorTO;
import common.Constants;
@@ -14,6 +15,7 @@ import common.HashUtils;
import common.UserType;
import ejb.common.CommonFacadeLocal;
import jpa.AdministratorJPA;
import jpa.MedicalSpecialtyJPA;
/**
*
@@ -107,4 +109,40 @@ public class SystemAdminFacadeBean implements SystemAdminFacadeRemote {
return usr;
}
@Override
public MedicalSpecialtyTO updateSpecialtyData(int id, String name, String description) throws Exception {
MedicalSpecialtyJPA ms = entman.find(MedicalSpecialtyJPA.class, id);
if (ms == null) {
throw new Exception("No se pueden actualizar los datos de la especialidad porque no se encuentra en la base de datos ningún registro con id: " + String.valueOf(id));
}
ms.setName(name);
ms.setDescription(description);
entman.persist(ms);
return this.commonServices.getPOJOforMedicalSpecialtyJPA(ms);
}
@Override
public void deleteSpecialtyData(int id, String name, String description) throws Exception {
MedicalSpecialtyJPA ms = entman.find(MedicalSpecialtyJPA.class, id);
if (ms == null) {
throw new Exception("No se puede borrar la especialidad porque no se encuentra en la base de datos ningún registro con id: " + String.valueOf(id));
}
entman.remove(ms);
}
@Override
public MedicalSpecialtyTO insertSpecialtyData(String name, String description) throws Exception {
MedicalSpecialtyJPA ms = new MedicalSpecialtyJPA(name, description);
entman.persist(ms);
return this.commonServices.getPOJOforMedicalSpecialtyJPA(ms);
}
}

View File

@@ -1,12 +1,9 @@
package ejb.systemAdmin;
import java.util.Collection;
import javax.ejb.Remote;
import TO.LoggedUserTO;
import TO.MedicalSpecialtyTO;
import TO.PrimaryHealthCareCenterTO;
/**
*
@@ -19,6 +16,11 @@ public interface SystemAdminFacadeRemote {
* Definimos la interfaz remota
*/
public LoggedUserTO login(String id, String pwd);
public MedicalSpecialtyTO updateSpecialtyData(int id, String name, String description) throws Exception;
public void deleteSpecialtyData(int id, String name, String description) throws Exception;
public MedicalSpecialtyTO insertSpecialtyData(String name, String description) throws Exception;
}

View File

@@ -2,11 +2,9 @@
package managedbean.common;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.persistence.PersistenceException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -18,10 +16,10 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.primefaces.model.menu.DefaultSeparator;
import org.primefaces.model.menu.DefaultSubMenu;
import org.omnifaces.util.Exceptions;
import common.UserType;
import common.Utils;
@WebFilter(filterName = "AuthFilter", urlPatterns = { "*.xhtml" })
public class AuthorizationFilter implements Filter {
@@ -34,25 +32,47 @@ public class AuthorizationFilter implements Filter {
}
private boolean isAJAXRequest(HttpServletRequest request) {
boolean check = false;
String facesRequest = request.getHeader("Faces-Request");
if (facesRequest != null && facesRequest.equals("partial/ajax")) {
check = true;
}
return check;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = null;
HttpServletResponse resp = null;
HttpSession ses = null;
try {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession ses = req.getSession(false);
req = (HttpServletRequest) request;
String reqURI = req.getRequestURI();
// Para recursos publicos permitimos el acceso
resp = (HttpServletResponse) response;
ses = req.getSession(false);
// Para recursos publicos permitimos el acceso exista sesión o no.
if (reqURI.indexOf("/login.xhtml") >= 0 || reqURI.indexOf("/profile/RegisterUser.xhtml") >= 0 || reqURI.indexOf("/home.xhtml") >= 0
|| reqURI.indexOf("/error.xhtml") >= 0 || reqURI.indexOf("/public/") >= 0 || reqURI.contains("javax.faces.resource")) {
chain.doFilter(request, response);
return;
}
// Si el usuario está logeado comprobamos si está autorizado a ver la página
// solicitada.
if (this.isAJAXRequest(req) == true) {
chain.doFilter(request, response);
return;
}
// Sesión expirada
if (req.isRequestedSessionIdValid() == false && req.getRequestedSessionId() != null) {
resp.sendRedirect(req.getContextPath() + "/error.xhtml?type=expired");
return;
}
// Si el usuario está logeado comprobamos si está autorizado a ver la página solicitada.
if (SessionUtils.isLogedIn(ses) == true) {
UserType tipoUsuario = SessionUtils.getUserType(ses);
boolean authorized = false;
@@ -130,21 +150,29 @@ public class AuthorizationFilter implements Filter {
chain.doFilter(request, response);
return;
} else {
SessionUtils.addMessage(ses, FacesMessage.SEVERITY_ERROR, "No está autorizado a acceder a la página solicitada. Por favor, utilice el menú principal de la aplicación.", String.format("Se ha producido una expción de autorización, su usuario no está autorizado a acceder a la página: (%s).", reqURI));
SessionUtils.addMessage(ses, FacesMessage.SEVERITY_ERROR,
"No está autorizado a acceder a la página solicitada. Por favor, utilice el menú principal de la aplicación.",
String.format("Se ha producido una expción de autorización, su usuario no está autorizado a acceder a la página: (%s).", reqURI));
resp.sendRedirect(req.getContextPath() + "/error.xhtml?type=auth");
return;
}
}
resp.sendRedirect(req.getContextPath() + "/login.xhtml");
resp.sendRedirect(req.getContextPath() + "/home.xhtml");
} catch (Exception e) {
System.out.println(e.getMessage());
if (Exceptions.is(e, PersistenceException.class) == true) {
if (ses != null)
SessionUtils.addMessage(ses, FacesMessage.SEVERITY_ERROR, "Error al intentar acceder a la base de datos", Utils.getExceptionRootCause(e).getLocalizedMessage());
resp.sendRedirect(req.getContextPath() + "/error.xhtml?type=sql");
} else
resp.sendRedirect(req.getContextPath() + "/error.xhtml");
}
}
@Override
public void destroy() {
System.out.println("Sessión destruida");
}
}

View File

@@ -1,9 +1,12 @@
package managedbean.common;
import java.io.IOException;
import java.util.Properties;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.naming.Context;
import javax.naming.InitialContext;
@@ -121,6 +124,24 @@ public class ManagedBeanBase {
}
protected void manageException(Exception ex) {
this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Se ha producido un error inesperado", "Descripción del error: " + ex.getLocalizedMessage());
String strType = "";
if (ex.getClass().equals(ViewExpiredException.class)) {
// Sessión expired
strType = "expired";
this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Su sesión ha caducado", "Su sesión ha caducado, vuelva a logarse en el sistema.");
} else {
this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Se ha producido un error inesperado", "Descripción del error: " + ex.getLocalizedMessage());
}
try {
ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();
ctx.redirect(ctx.getApplicationContextPath() + "/error.xhtml?type=" + strType);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View File

@@ -70,6 +70,9 @@ public class ValidationUtils {
public static boolean checkIfNifAlreadyRegistered(CommonFacadeRemote remoteSvc, UserType userType, String nif, Integer id) {
boolean nifExists = false;
if (userType == null || remoteSvc == null)
return nifExists;
switch (userType) {
case ADMINISTRATOR:
break;

View File

@@ -257,6 +257,11 @@ public class UpdateProfileMBean extends ManagedBeanBase implements Serializable
public void saveData() {
int error = 0;
// Si no hay tipo de usuario, es que algo raro ha pasado (sesión caducada?). salimos.
if (this.userType == null)
return;
boolean changePassword = (this.oldPassword != null && this.oldPassword.equals("") == false) || (this.password != null && this.password.equals("") == false);
if (this.isUserTypeFamilyDoctor() && this.primaryHealthCareCenter == null) {

View File

@@ -0,0 +1,162 @@
package managedbean.systemAdmin;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.inject.Named;
import TO.LoggedUserTO;
import TO.MedicalSpecialtyTO;
import common.Constants;
import managedbean.common.ManagedBeanBase;
import managedbean.common.SessionUtils;
@Named("ManageSpecialities")
@RequestScoped
public class ManageSpecialitiesMBean extends ManagedBeanBase implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String description;
private MedicalSpecialtyTO medicalSpecialty;
private List<MedicalSpecialtyTO> medicalSpecialitiesList;
public ManageSpecialitiesMBean() {
}
@PostConstruct
public void init() {
if (this.medicalSpecialty == null) {
this.medicalSpecialty = new MedicalSpecialtyTO();
}
// Recuperamos el usuario logeado actual
LoggedUserTO usr = null;
try {
usr = SessionUtils.getloggedOnUser();
if (usr == null)
this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Sesión no válida",
"Su sesión actual no es válida, por favor cierre su sesión y vuelva a logearse en el sistema.");
else {
this.medicalSpecialitiesList = this.getRemoteManagerCommon().listMedicalSpecialitiesPaged(0, Constants.MAX_ITEMS_AUTOCOMPLETE_SEARCH);
}
} catch (Exception e) {
this.manageException(e);
}
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
private void setSpecialtyData(MedicalSpecialtyTO ms) {
this.id = ms.getId();
this.name = ms.getName();
this.description = ms.getDescription();
}
public List<MedicalSpecialtyTO> getMedicalSpecialtiesList() {
return medicalSpecialitiesList;
}
public MedicalSpecialtyTO getMedicalSpecialty() {
return medicalSpecialty;
}
public void setMedicalSpecialty(MedicalSpecialtyTO value) {
this.medicalSpecialty = value;
}
public void saveData() {
int error = 0;
if (this.medicalSpecialty.getName() == null) {
this.addFacesMessage(FacesMessage.SEVERITY_WARN, "Nombre no relleno", "Por favor, escriba un nombre de especialidad.");
error++;
}
if (this.medicalSpecialty.getDescription() == null) {
this.addFacesMessage(FacesMessage.SEVERITY_WARN, "Descripción no rellena", "Por favor, escriba una descripción.");
error++;
}
if (error == 0) {
try {
MedicalSpecialtyTO ms = this.getRemoteManagerSystemAdmin().updateSpecialtyData(this.medicalSpecialty.getId(), this.medicalSpecialty.getName(), this.medicalSpecialty.getDescription());
this.setSpecialtyData(ms);
this.addFacesMessage(FacesMessage.SEVERITY_INFO, "Los datos se han guardado", "Los datos de la especialidad se han guardado correctamente.");
} catch (Exception e) {
this.manageException(e);
}
}
}
public void deleteData() {
int error = 0;
if (this.medicalSpecialty.getName() == null) {
this.addFacesMessage(FacesMessage.SEVERITY_WARN, "Nombre no relleno", "Por favor, escriba un nombre de especialidad.");
error++;
}
if (this.medicalSpecialty.getDescription() == null) {
this.addFacesMessage(FacesMessage.SEVERITY_WARN, "Descripción no rellena", "Por favor, escriba una descripción.");
error++;
}
if (error == 0) {
try {
this.getRemoteManagerSystemAdmin().deleteSpecialtyData(this.medicalSpecialty.getId(), this.medicalSpecialty.getName(), this.medicalSpecialty.getDescription());
this.addFacesMessage(FacesMessage.SEVERITY_INFO, "Los especialidad se ha borrado", "Los datos de la especialidad se han borrado correctamente.");
} catch (Exception e) {
this.manageException(e);
}
}
}
public void insertData() {
int error = 0;
if (name == null || name.trim().length() == 0) {
this.addFacesMessage(FacesMessage.SEVERITY_WARN, "Nombre no relleno", "Por favor, escriba un nombre de especialidad.");
error++;
}
if (description == null || description.trim().length() == 0) {
this.addFacesMessage(FacesMessage.SEVERITY_WARN, "Descripción no rellena", "Por favor, escriba una descripción.");
error++;
}
if (error == 0) {
try {
MedicalSpecialtyTO ms = this.getRemoteManagerSystemAdmin().insertSpecialtyData(name, description);
this.setSpecialtyData(ms);
this.addFacesMessage(FacesMessage.SEVERITY_INFO, "Los datos se han guardado", "Los datos de la especialidad se han guardado correctamente.");
} catch (Exception e) {
this.manageException(e);
}
}
}
}

View File

@@ -1,71 +0,0 @@
package managedbean.systemAdmin;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.inject.Named;
import TO.LoggedUserTO;
import TO.MedicalSpecialtyTO;
import common.Constants;
import common.UserType;
import managedbean.common.ManagedBeanBase;
import managedbean.common.SessionUtils;
@Named("SystemAdmin")
@RequestScoped
public class SystemAdminMBean extends ManagedBeanBase implements Serializable {
private static final long serialVersionUID = 1L;
private String lastUIQuery;
private MedicalSpecialtyTO medicalSpecialty;
private List<MedicalSpecialtyTO> medicalSpecialitiesList;
public SystemAdminMBean() {
}
@PostConstruct
public void init() {
// Recuperamos el usuario logeado actual
LoggedUserTO usr = null;
this.lastUIQuery = "";
try {
usr = SessionUtils.getloggedOnUser();
if (usr == null)
this.addFacesMessage(FacesMessage.SEVERITY_ERROR, "Sesión no válida",
"Su sesión actual no es válida, por favor cierre su sesión y vuelva a logearse en el sistema.");
else {
this.medicalSpecialitiesList = this.getRemoteManagerCommon().listMedicalSpecialitiesPaged(0, Constants.MAX_ITEMS_AUTOCOMPLETE_SEARCH);
}
} catch (Exception e) {
this.manageException(e);
}
}
public List<MedicalSpecialtyTO> getMedicalSpecialtiesList() {
return medicalSpecialitiesList;
}
public List<MedicalSpecialtyTO> completeMedicalSpecialty(String query) {
if (query != null && query.equals(this.lastUIQuery) == false) {
this.lastUIQuery = query;
// Recuperamos las 200 primeras coincidencias
this.medicalSpecialitiesList = this.getRemoteManagerCommon().listMedicalSpecialitiesFiltered(query, 0, Constants.MAX_ITEMS_AUTOCOMPLETE_SEARCH);
}
return this.medicalSpecialitiesList;
}
public MedicalSpecialtyTO getMedicalSpecialty() {
return medicalSpecialty;
}
public void setMedicalSpecialty(MedicalSpecialtyTO value) {
this.medicalSpecialty = value;
}
}

View File

@@ -81,29 +81,29 @@ INSERT INTO myhealth.patient(personalidentificationcode, password, nif, surname,
,('PAT#109','912EC803B2CE49E4A541068D495AB570','53986482P','Carretero Ayala', 'Eduardo@example.ecom','Eduardo', 10);
INSERT INTO myhealth.question(title, message, status, response, patientid, familydoctorid) VALUES
('titulo de la pregunta número 1', 'Doctor, tengo dolor en la articulación numero 1', 1, null, 1, 1)
,('titulo de la pregunta número 2', 'Doctor, tengo dolor en la articulación numero 2', 1, null, 2, 1)
,('titulo de la pregunta número 3', 'Doctor, tengo dolor en la articulación numero 3', 1, null, 3, 1)
,('titulo de la pregunta número 4', 'Doctor, tengo dolor en la articulación numero 4', 1, null, 4, 1)
,('titulo de la pregunta número 5', 'Doctor, tengo dolor en la articulación numero 5', 1, null, 5, 1)
,('titulo de la pregunta número 6', 'Doctor, tengo dolor en la articulación numero 6', 1, null, 6, 1)
,('titulo de la pregunta número 7', 'Doctor, tengo dolor en la articulación numero 7', 1, null, 7, 1)
,('titulo de la pregunta número 8', 'Doctor, tengo dolor en la articulación numero 8', 1, null, 8, 1)
,('titulo de la pregunta número 9', 'Doctor, tengo dolor en la articulación numero 9', 1, null, 9, 1)
,('titulo de la pregunta número 10', 'Doctor, tengo dolor en la articulación numero 10', 1, null, 10, 1)
,('titulo de la pregunta número 11', 'Doctor, tengo dolor en la articulación numero 11', 1, null, 1, 1)
,('titulo de la pregunta número 12', 'Doctor, tengo dolor en la articulación numero 12', 1, null, 2, 1)
,('titulo de la pregunta número 13', 'Doctor, tengo dolor en la articulación numero 13', 1, null, 3, 1)
,('titulo de la pregunta número 14', 'Doctor, tengo dolor en la articulación numero 14', 1, null, 4, 1)
,('titulo de la pregunta número 15', 'Doctor, tengo dolor en la articulación numero 15', 1, null, 5, 1)
,('titulo de la pregunta número 16', 'Doctor, tengo dolor en la articulación numero 16', 1, null, 6, 1)
,('titulo de la pregunta número 17', 'Doctor, tengo dolor en la articulación numero 17', 1, null, 7, 1)
,('titulo de la pregunta número 18', 'Doctor, tengo dolor en la articulación numero 18', 1, null, 8, 1)
,('titulo de la pregunta número 19', 'Doctor, tengo dolor en la articulación numero 19', 1, null, 9, 1)
,('titulo de la pregunta número 20', 'Doctor, tengo dolor en la articulación numero 20', 1, null, 10, 1)
,('titulo de la pregunta número 21', 'Doctor, tengo dolor en la articulación numero 21', 1, null, 8, 1)
,('titulo de la pregunta número 22', 'Doctor, tengo dolor en la articulación numero 22', 1, null, 9, 1)
,('titulo de la pregunta número 23', 'Doctor, tengo dolor en la articulación numero 23', 1, null, 10, 1);
('titulo de la pregunta número 1', 'Doctor, tengo dolor en la articulación numero 1', 'PENDING', null, 1, 1)
,('titulo de la pregunta número 2', 'Doctor, tengo dolor en la articulación numero 2', 'PENDING', null, 2, 1)
,('titulo de la pregunta número 3', 'Doctor, tengo dolor en la articulación numero 3', 'PENDING', null, 3, 1)
,('titulo de la pregunta número 4', 'Doctor, tengo dolor en la articulación numero 4', 'PENDING', null, 4, 1)
,('titulo de la pregunta número 5', 'Doctor, tengo dolor en la articulación numero 5', 'PENDING', null, 5, 1)
,('titulo de la pregunta número 6', 'Doctor, tengo dolor en la articulación numero 6', 'PENDING', null, 6, 1)
,('titulo de la pregunta número 7', 'Doctor, tengo dolor en la articulación numero 7', 'PENDING', null, 7, 1)
,('titulo de la pregunta número 8', 'Doctor, tengo dolor en la articulación numero 8', 'PENDING', null, 8, 1)
,('titulo de la pregunta número 9', 'Doctor, tengo dolor en la articulación numero 9', 'PENDING', null, 9, 1)
,('titulo de la pregunta número 10', 'Doctor, tengo dolor en la articulación numero 10', 'PENDING', null, 10, 1)
,('titulo de la pregunta número 11', 'Doctor, tengo dolor en la articulación numero 11', 'PENDING', null, 1, 1)
,('titulo de la pregunta número 12', 'Doctor, tengo dolor en la articulación numero 12', 'PENDING', null, 2, 1)
,('titulo de la pregunta número 13', 'Doctor, tengo dolor en la articulación numero 13', 'PENDING', null, 3, 1)
,('titulo de la pregunta número 14', 'Doctor, tengo dolor en la articulación numero 14', 'PENDING', null, 4, 1)
,('titulo de la pregunta número 15', 'Doctor, tengo dolor en la articulación numero 15', 'PENDING', null, 5, 1)
,('titulo de la pregunta número 16', 'Doctor, tengo dolor en la articulación numero 16', 'PENDING', null, 6, 1)
,('titulo de la pregunta número 17', 'Doctor, tengo dolor en la articulación numero 17', 'PENDING', null, 7, 1)
,('titulo de la pregunta número 18', 'Doctor, tengo dolor en la articulación numero 18', 'PENDING', null, 8, 1)
,('titulo de la pregunta número 19', 'Doctor, tengo dolor en la articulación numero 19', 'PENDING', null, 9, 1)
,('titulo de la pregunta número 20', 'Doctor, tengo dolor en la articulación numero 20', 'PENDING', null, 10, 1)
,('titulo de la pregunta número 21', 'Doctor, tengo dolor en la articulación numero 21', 'PENDING', null, 8, 1)
,('titulo de la pregunta número 22', 'Doctor, tengo dolor en la articulación numero 22', 'PENDING', null, 9, 1)
,('titulo de la pregunta número 23', 'Doctor, tengo dolor en la articulación numero 23', 'PENDING', null, 10, 1);

View File

@@ -1,7 +1,10 @@
**Página de inicio del proyecto My Health del Grupo 2**
## Página de inicio del proyecto My Health del Grupo 2
Organización de directorios:
### Organización de directorios:
* sources: Código fuente y proyecto eclipse
* database: Scripts SQL para crear la estructura de base de datos y los datos de prueba
* doc: Directorio para ubicar la documentación compartida.
### Instrucciones de despliegue e instalación
Las instrucciones detalladas de despliegue y configuración están descritas en el documento [install.md](install.md)

26
install.md Normal file
View File

@@ -0,0 +1,26 @@
## Instrucciones de despliegue e instalación
### 1. Crear esquema de base de datos y tablas:
Se debe crear un esquema nuevo en PostgreSQL y conceder permisos al usuario USER. Esto puede realizarse ejecutando el script incluido con la solución llamado:
* 01.CreateTables.sql
### 2. Inserción de datos iniciales:
Se debe ejecutar el script, incluido con la solución, que crea la tabla e inserta los datos de prueba:
* 02.Datos_prueba.sql
### 3. Creación del DataSource:
Para este proyecto se utilizará el mismo datasource que para el caso práctico, si no está creado debe añadirse al fichero JBOSS_HOME\standalone\configuration\standalone.xlm.
El usuario y contraseña de base de datos que se han utilizado en el datasource es USER con contraseña PASSWORD.
<datasource jta="false" jndi-name="java:jboss/postgresDS" pool-name="postgresDS"
enabled="true" use-java-context="true" use-ccm="false" statistics-enabled="true">
<connection-url>jdbc:postgresql://localhost:5432/postgres</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<driver>postgresql</driver>
<security>
<user-name>USER</user-name>
<password>PASSWORD</password>
</security>
</datasource>
### 4. Ejecutar la compilación y despliegue del proyecto
Acceder al directorio con el código fuente ([git-folder]/1.sources/MyHealth), y donde está ubicado el archivo de compilación de ant build.xml, ejecutar `ant` en este directorio, el proyecto debería compilarse y desplegarse automáticamente en el servidor JBOSS local.