Para saber si un portlet en una página web es o no instanciable, es decir si puede haber el mismo portlet más de una vez para la misma página, podemos averiguarlo inspeccionando el código. Sobre este buscaremos el literal: INSTANCE, que nos indicará que es instanciable.
4 de diciembre de 2020
:: Liferay. Tip: Cómo saber si mi portlet es instanciable
Para saber si un portlet en una página web es o no instanciable, es decir si puede haber el mismo portlet más de una vez para la misma página, podemos averiguarlo inspeccionando el código. Sobre este buscaremos el literal: INSTANCE, que nos indicará que es instanciable.
30 de noviembre de 2020
PILAR :: Problemas con la herramienta de Análisis y Gestión de Riesgos
Tras haber instalado la aplicación hace unas semanas, a la hora de abrirla para modificar un fichero, en el menú desplegable: "modo" nos aparecen dos entradas (con el mismo texto en inglés) y al pulsar sobre el botón: "análisis cualitativo" la aplicación no parece funcionar.
En la ventana donde tenemos los logs, concretamente en la pestaña "error", podemos comprobar que hace referencia a un fichero: "commons.txt".
Para solucionar este problema, lo que debemos hacer es -en la herramienta pilar- seleccionar la primera entrada de menú, que indica el fichero .mgr cargada y en el menú desplegable, seleccionar "Configuración".
De acuerdo a la captura de pantalla, en nuestro caso será: "STIC_es" > "Configuración".
En esta ventana, debemos seleccionar el fichero ".cer" y guardar. Tras este cambio, la aplicación vuelve a funcionar como se esperaba.
29 de noviembre de 2020
:: Liferay. Portlet instanciable
En Liferay, un portlet instanciable indica que podemos tener el mismo portlet más de una vez en la misma página.
Esta propiedad se define en el fichero: "liferay-portlet.xml"
<portlet>
<portlet-name>Nombre del porllet</portlet-name>
...
<instanceable>true</instanceable>
...
</portlet>
Si necesitamos que un determinado portlet no sea instanciable, deberemos establece el valor:
<instanceable>false</instanceable>
25 de noviembre de 2020
:: Liferay. Tip: Leer variable del fichero portal-ext.properties
Únicamente a modo de recordatorio, para leer el valor de una variable almacenada en el fichero: "portal-ext.properties", desde nuestra "jsp" deberemos acceder a esta mediante el código siguiente:
String valor = PropsUtil.get("nombre-de-variable")
18 de noviembre de 2020
PILAR :: Herramienta de análisis y gestión de riesgos
PILAR es una aplicación que recopila los activos del sistema, sus relaciones e interdependencias y el valor para la organización. Una vez establecido el inventario de activos, permite introducir las posibles amenazas, calculando los riesgos potenciales.
Aunque visualmente la aplicación utiliza la fuente "Comic Sans" y el aspecto y usabilidad es bastante pobre y anticuado, es la herramienta de referencia en muchos organismos.
El objetivo de la herramienta es:
- Realizar el análisis de riesgos según la metodología Magerit e ISO/IEC 27005.
- Diseño del plan de mejora de la seguridad.
Como ventajas del uso de la herramienta podemos señalar:
- Conocer los riesgos a fin de poder tratarlos.
- Conocer el grado de cumplimiento de diferentes perfiles de seguridad: 27002, protección de datos de carácter personal, esquema nacional de seguridad, etc.
- Implementar la metodología Magerit e ISO/IEC 27005
Más información: https://administracionelectronica.gob.es/ctt/pilar
23 de septiembre de 2020
TLS :: Herramienta para comprobar qué versión se utiliza
Debido a que en marzo de 2020 los principales navegadores (Google Chrome, Mozilla Firefox, Microsoft Edge y Apple Safari) llegaron a un acuerdo para dejar de dar soporte a TLS 1.0 y TLS 1.1, cuando navegamos por diversos portales, nos aparece: "dominio no seguro".
Para comprobar qué versión de TLS está utilizando una web, podemos hacer uso de la siguiente herramienta:
6 de agosto de 2020
Eclipse :: JSTL dependencias .jar
18 de junio de 2020
:: Liferay. Modificar los valores mostrados en el paginador
En los paginadores mostrados en Liferay, se muestran las siguientes opciones -en cuanto al nº de elementos por página se refiere:
5,10,20,30,50,75,100
Para este caso, lo que necesitamos es que nuestros paginadores muestren más opciones, por ejemplo hasta 200 elementos por página.
Para ello, añadiremos la siguiente línea al fichero: "portal-ext.properties"
search.container.page.delta.values=5,10,20,30,50,75,100,125,150,200
Tras reiniciar el servicio, estas opciones estarán disponibles a la hora de seleccionar los elementos por página a mostrar.
search.container.page.default.delta=300
En este caso se mostrarán por defecto, 30 elementos por página.
14 de junio de 2020
:: Liferay 6.2. Uso de caracteres especiales en el nombrado de ficheros
Como prueba de concepto, el cliente nos indica que a la hora de subir un fichero o nombrar una carpeta dentro de: "Documentos y Multimedia" no quiere permitir los que contengan el caracter: "corchete".
Si creamos un fichero o carpeta nombrado con el caracteres: "[", por ejemplo: "test[1]" o "test[1].txt", tanto la carpeta como el fichero se crean correctamente.
De acuerdo a la documentación de Liferay, existen una serie de caracteres no permitidos o desaconsejados para el nombrado de carpetas y ficheros:
"\\\\""//"":""*""?""\"""<"">""|""[""]""'""..\\""../""\\..""/.."
De esta manera, si no queremos permitir el nombrado de carpetas y ficheros que contengan estos caracteres especiales, tendríamos que añadir la siguiente línea al fichero: "portal-ext.properties"
journal.char.blacklist=&,\',@,\\,],},:,=,>,/,<,[,{,%,|,+,#,`,?,\",;,*,~
Para el caso que nos ocupa, la línea a añadir en el fichero: "portal-ext.properties" , será la siguiente, indicando que no puede utilizarse el caracter: "[" y/o "]".
journal.char.blacklist=],[
Una vez iniciado el servicio, al subir el fichero: "test[1].txt" a "Documentos y multimedia" nos mostrará un error indicando que debemos utilizar un nombre válido.
10 de junio de 2020
:: Javascript. Ocultar botón de descarga en un aud
25 de mayo de 2020
:: Liferay. Tema del que heredamos
<property name="theme.parent" value="_styled" />
20 de mayo de 2020
:: Modificar "label" de un formulario desde Javascript
var labels = document.getElementsByTagName('label');
for (var i = 0; i < labels.length; i++) {
if (labels[i].htmlFor == '_58_login') {
labels[i].innerText="Email"
}
}
15 de mayo de 2020
:: Modo oscuro en Chrome
chrome://flags/enable-force-dark
Una vez en esta página de configuración, habilitaremos el modo oscuro.
12 de mayo de 2020
:: Liferay. Login contra LDAP no funciona
A la hora de la validación, no se obtenía ningúnmensaje en el log y unicamente el login en el portal fallaba.
Habilitamos las trazas siguientes:com.liferay.portal.security.auth.LDAPAuth
Tras habilitar las trazas, el error obtenido en el log era este:
09:19:37,676 DEBUG [ajp-bio-8009-exec-38][LDAPAuth:176] Failed to bind to the LDAP server with userDN CN=xxxxxx,OU=xxxxxxx, OU=xxxxx, DC=xxxxxx, DC=LOCAL and password xxxxxxxxxx
javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090442, comment: AcceptSecurityContext error, data 531, v3839_] [Sanitized]
at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3087)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3033)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2835)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2749)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:316)
Para obtener el motivo del fallo en el proceso de login, debemos buscar:
AcceptSecurityContext error, data 531
El motivo por el que los usuarios no pueden loguearse es debido a una restricción impuesta en el propio LDAP:49 / 531 RESTRICTED_TO_SPECIFIC_MACHINES Indicates an Active Directory (AD) AcceptSecurityContext data error that is logon failure caused because the user is not permitted to log on from this computer. Returns only when presented with a valid username and valid password credential.
Más información sobre posibles errores:
https://docs.servicenow.com/bundle/helsinki-platform-administration/page/administer/reference-pages/reference/r_LDAPErrorCodes.html
8 de mayo de 2020
:: Liferay. Cómo determinar el idioma seleccionado desde un script
themeDisplay.getLanguageId();
De esta manera, podríamos tener algo similar a lo siguiente:
var idioma=themeDisplay.getLanguageId();
var txtDescripcion="Lorem ipsum dolor sit amet.";
var txtAceptar="Aceptar";
var txtEnlace="Más información";
if("en_EN"==idioma){
txtDescripcion="Lorem ipsum dolor sit amet.";
txtAceptar="Ok";
txtEnlace="More information";
}
4 de mayo de 2020
:: Unidades em
El em es una unidad que tiene su origen en el diseño tipográfico y equivale al espacio que ocupa el ancho de una letra "M" de un determinado cuerpo y alfabeto.
28 de abril de 2020
::Liferay. Ordenar usuarios desde plantilla velocity
$sortTool.sort($lista_a_ordenar, 'campo:ordenación')
El código sería algo similar al siguiente:
#set($userLocalServiceUtil =
$serviceLocator.findService("com.liferay.portal.service.UserLocalService"))
#set($usuarios = $userLocalServiceUtil.getUsers(-1,-1))
#set($usuariosOrdenados=$sortTool.sort($usuarios, 'lastName:asc'))
24 de abril de 2020
:: Guía de configuración segura para Microsoft Teams
Más información: https://www.ccn-cert.cni.es/pdf/guias/series-ccn-stic/guias-de-acceso-publico-ccn-stic/4519-ccn-stic-885d-guia-de-configuracion-segura-para-microsoft-teams/file.html
22 de abril de 2020
:: Recomendaciones de seguridad en situaciones de teletrabajo
Estas acciones o recomendaciones se podrían englobar en cuanto a:
- Usuarios
- Acceso remoto
- Correo electrónico
- Videoconferencia
- Detección y vigilancia
- Otras
Más información: https://www.ccn-cert.cni.es/informes/informes-ccn-cert-publicos/4691-ccn-cert-bp-18-recomendaciones-de-seguridad-para-situaciones-de-teletrabajo-y-refuerzo-en-vigilancia-1/file.html
21 de abril de 2020
:: Cálculo del cuadrado de un número terminado en 5
Por ejemplo para calcular el cuadrado de 65:
1.- Cogemos la primera cifra (6) y la multiplicamos por el siguiente número (7):
6 x 7 =42
2.- El resultado será el número anterior, seguido del cuadrado de la segunda cifra del número del que queremos calcular su cuadrado (5) y que siempre será: 25De esta manera el resultado será: 4225
Para el cálculo del cuadrado de una cifra terminada en 5, en realidad tendremos que hacer el cálculo del resto de cifras y posteriormente añadir la cifra 25.
Otro ejemplo: calcular el cuadrado de 105:
1.- Cogemos la primera cifra (10) y la multiplicamos por el siguiente número (11):
10 x 11 = 110
2.- Al resultado anterior le añadimos la cifra 25. Es decir el resultado será: 11025
18 de abril de 2020
:: Multiplicación japonesa
Un método, cuanto menos curioso, pero que tiene su base científica, y funciona.
En el siguiente vídeo nos muestran cómo se aplica este método:
4 de abril de 2020
:: Liferay. Error creating Liferay plugin project
La solución que encontramos, fue la siguiente:
- Seleccionar en Eclipse: "Window" > "Preferences" > "Compiler"
- En el desplegable: "Compiler compliance level", seleccionamos 1.7 en lugar de 1.8 que es la que venía por defecto.
Probamos a generar un tema, y en esta ocasión todo funcionó correctamente.
31 de marzo de 2020
:: Liferay. Tiempo de sincronización con el LDAP
En cualquier caso, si necesitásemos modificar este tiempo de comprobación, podríamos hacerlo a través del fichero: "portal-ext.properties" mediante la definición de la siguiente línea:
ldap.import.interval=15
Siendo el valor 15, el número de minutos entre cada comprobación o sincronización.
28 de marzo de 2020
:: Integración de Analytics en nuestro portal. Problema en la generación de informe
Para solventar este problema, lo que debemos hacer es repetir el proceso desde una ventana de incógnito; es decir, accederemos a nuestra cuenta de Google Drive desde una ventana de incógnito y seguiremos los pasos descritos en el post indicado anteriormente.
25 de marzo de 2020
:: Liferay. Error Configuración de autenticación a través del LDAP: invalid attribute description; remaining name
Tras llevar a cabo la definición -desde el panel de control de Liferay- del servidor LDAP y mapeo de los campos correspondientes, verificando que la prueba de conexión era correcta, a la hora de pulsar el botón: "Probar la configuración de usuarios LDAP", no devolvía ningún resultado y los logs se observaba la siguiente traza:
ERROR [ajp-bio-8009-exec-19][IncludeTag:129] Current URL /group/control_panel/manage?p_p_id=130&p_p_lifecycle=0&p_p_state=exclusive&p_p_mode=view&refererPlid=22323&_130_struts_action=%2Fportal_settings%2Ftest_ldap_users generates exception: javax.naming.directory.InvalidSearchFilterException: invalid attribute description; remaining name 'OU=Plantilla, OU=XXXXXXXX, DC=XXXXXXXX, DC=XXXXX'
javax.naming.directory.InvalidSearchFilterException: invalid attribute description; remaining name 'OU=Plantilla, OU=XXXXXXXX, DC=XXXXXXXX, DC=XXXXX'
at com.sun.jndi.ldap.Filter.encodeSimpleFilter(Filter.java:446)
at com.sun.jndi.ldap.Filter.encodeFilter(Filter.java:146)
at com.sun.jndi.ldap.Filter.encodeFilterString(Filter.java:74)
at com.sun.jndi.ldap.LdapClient.search(LdapClient.java:547)
at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1985)
at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1847)
at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1772)
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:386)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:356)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:339)
at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:267)
at com.liferay.portal.security.ldap.PortalLDAPUtil.searchLDAP(PortalLDAPUtil.java:820)
at com.liferay.portal.security.ldap.PortalLDAPUtil.getUsers(PortalLDAPUtil.java:617)
at org.apache.jsp.html.portlet.portal_005fsettings.test_005fldap_005fusers_jsp._jspService(test_005fldap_005fusers_jsp.java:677)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at com.liferay.portal.servlet.DirectRequestDispatcher.include(DirectRequestDispatcher.java:57)
at com.liferay.portal.servlet.ClassLoaderRequestDispatcherWrapper.doDispatch(ClassLoaderRequestDispatcherWrapper.java:78)
at com.liferay.portal.servlet.ClassLoaderRequestDispatcherWrapper.include(ClassLoaderRequestDispatcherWrapper.java:53)
at com.liferay.taglib.util.IncludeTag.include(IncludeTag.java:295)
En nuestro caso el problema era que en el campo: "Filtro de búsqueda para la importación", habíamos puesto -debido a una modificación-: "((objectClass=Person))", cuando debería ser: "(objectClass=Person)", es decir, sobraría el "doble paréntesis".12 de marzo de 2020
:: Coronavirus. Herramienta de seguimiento en tiempo real
En estos días, estamos preocupados por la evolución de la pandemia del coronavirus y la cantidad de información que recibidos a través de todos los medios.
Mediante una herramienta gráfica podemos seguir minuto a minuto la evolución de esta creciente infección global.
Acceso: https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6
14 de febrero de 2020
:: Java. Determinar si dos fechas pertenecen al mismo día
if (DateUtils.isSameDay(date1, date2)) {
System.out.println("Fechas en el mismo día");
} else if (date1.before(date2)) {
System.out.println("Fecha1 es anterior a la fecha2");
} else {
System.out.println("Fecha1 es posterior a la fecha2");
}
10 de febrero de 2020
:: Liferay. Comentarios en un workflow
Dentro del fichero .xml de definición del workflow, tendremos el código al que llamaremos, por ejemplo:
<state>
<name>reject</name>
<metadata> <![CDATA[{"xy":[356,225]}]]> </metadata>
<actions>
<action>
<name>denied</name>
<description/>
<script> <![CDATA[Packages.com.liferay.portal.kernel.workflow.WorkflowStatusManagerUtil.updateStatus(Packages.com.liferay.portal.kernel.workflow.WorkflowConstants.toStatus("denied"), workflowContext);]]> </script>
<script-language>javascript</script-language>
<execution-type>onEntry</execution-type>
</action>
<!-- correo al usuario rechazado -->
<notification>
<name>Review Notification</name>
<description>Denegación de solicitud</description>
<template><![CDATA[<html>
#set ($workflowHandlerRegistryUtil = $portal.getClass().forName("com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil"))
#set ($locale = $localeUtil.getDefault())
#set ($timeZone = $timeZoneUtil.getDefault())
#set ($workflowHandler = $workflowHandlerRegistryUtil.getWorkflowHandler($entryClassName))
#set ($classPK = $getterUtil.getInteger($entryClassPK))
#set ($assetRenderer = $workflowHandler.getAssetRenderer($classPK))
#set ($emailUser = $assetRenderer.getEmailNotificationDenied($locale, $timeZone, $taskComments))
</html>]]> </template>
<template-language>velocity</template-language>
<notification-type>email</notification-type>
<execution-type>onEntry</execution-type>
</notification>
</actions>
</state>
En la función encargada de realizar el envío de correo tras ser rechazada la solicitud,
añadiremos los comentarios al cuerpo del mensaje.
5 de febrero de 2020
:: Accesibilidad web. Enlaces adyacentes
Se consideran enlaces adyacentes aquellos que están separados por un carácter y/o conjunto de espacios en blanco, o por alguna etiqueta que no pertenezca al grupo de etiquetas en línea: a, abbr, acronym, b, big, code, cite, dfn, em, font, img, ins, label, q, s, small, span, strike, strong, sub, sup, u.
NOTA: No se tienen en cuenta los enlaces que apunten al destino: #
31 de enero de 2020
:: Accesibilidad web. Cambio de contexto
¿Pero a qué hace referencia este término?.
Se entiende por cambio de contexto: una nueva página, ventana, pestaña, aplicación o un cambio de foco (window.location, window.history, window.open, window.focus).
De esta manera, a la hora de evaluar la accesibilidad en un portal web, deberemos tener en cuenta el uso de estas técnicas, para obtener la máxima puntuación posible en los informes.
- Verificar que no se produzca ningún cambio de contexto en los eventos: onfocus y onblur
- Verificar que no se produzca ningún cambio de contexto nada más cargarse la página: onload
- Verficar que no se produzca ningún cambio de contexto en el evento onchange de los elementos select
27 de enero de 2020
:: Velocity. Directivas
set
Utilizada para estableer el valor de una referencia. Este valor se puede asignar a una variable o a una propiedad#set($variable="hola mundo")
#set($noticia.titulo=$variable)
if else
Utilizada para definir enunciados condicionales dentro de una plantilla velocity#if ($valor>10)
Valor mayor que 10
#elseif
Valor menor o igual que 10
#end
foreach
Utilizada para definir bucles#foreach($noticia in $noticias)
$noticia.titulo
#end
include
Utilizada para incluir un fichero correspondiente a una plantilla, pero que no será parseado por el motor de velocity#include("plantilla.html")
parse
Utilizada para hacer uso de una plantilla, y esta será parseada por el motor de velocity y rederizará su contenidos#parse("cabecera.vm")
stop
Utilizada para detener la ejecución del motor de plantillas#stop
20 de enero de 2020
:: Velocity. ¿Qué es una plantilla?
Por ejemplo a la hora de desarrollar un tema en Liferay 6.2 podemos tener varios ficheros .vm encargados de mostrar la información oportuna.
Las plantillas velocity - en tiempo de ejecución- son traducidas por el motor de velocity a código html que un navegador puede entender.
<html>
<body>
#set( $foo = "Velocity" )
¡Hola Mundo $foo!
</body>
<html>
</html>
13 de enero de 2020
:: Liferay. Deshabilitar la creación de sitios personales
De esta manera, a través del fichero: "portal-ext.properties" es posible llevar a cabo una configuración, de forma que no se creen los sitios personales de los usuarios.
Deshabilitar los sitios personales de los usuarios
layout.user.public.layouts.enabled=false
layout.user.private.layouts.enabled=false
Deshabilitar la creación de sitios personales
layout.user.public.layouts.auto.create=false
layout.user.private.layouts.auto.create=false
5 de enero de 2020
:: Ejemplo de notificación HTML5 en el navegador
El código correspondiente al envío de notificaciones sería algo similar al siguiente:
<html>
<head>
<script>
//simple function to create a notification
function notificar(title, body) {
new Notification(title, {
body: body,
icon: '/img/favicon.png'
});
};
switch(Notification.permission) {
//El usuario no acepta las notificaciones
case "denied":
window.alert('Permiso denegado. Por favor cambia la configuración del navegador para permitir a esta página recibir notificaciones');
//el usuario ha aceptado las notificaciones
case "granted":
notificar('Permitir notificación', 'Has dado permiso para recibir notificaciones');
break;
//En cualquier otro caso
default:
Notification.requestPermission((status) => {
if (status === "granted") notificar('Permitir notificación', 'Gracias por permitir recibir notificaciones');
});
}
</script>
</head>
<body>
<p>Ejemplo de notificación</p>
<script>notificar("titulo","cuerpo del mensaje");</script>
</body>
</html>
Al cargar esta página, nos aparecerá un mensaje emergente en el que deberemos permitir o denegar las notificaciones. En el caso de aceptarlas, se nos mostrarán dos ventanas en la esquina inferior derecha con la siguiente información:- Has dado permiso para recibir notificaciones
- Cuerpo del mensaje
Este es un ejemplo sencillo de su implementación, si bien existen distintas librerías javascript.
:: Cookies de nuestra página web. ¿Para qué sirve cada una?
A menudo una pregunta que nos hacen es qué cookies se están utilizando en mi página y para qué sirven. Para ver las cookies, podemos selecci...
-
A veces necesitamos obtener las coordenadas geográficas (longitud y latitud) de una serie de direcciones. Una forma rápida de llevar a cabo ...
-
En multitud de ocasiones es útil obtener el modelo de datos de una aplicación para determinar las tablas, consultas, relaciones,... En es...
-
Para deshabilitar la opción de "crear sitio" a todos aquellos usuarios que no sean administradores, debemos seguir los pasos sig...