firebase – seguridad en aplicaciones

Durante un curso de desarrollo de aplicaciones híbridas con ionic que tomé en platzi, me di cuenta que nunca mencionan la seguridad.

La seguridad debe ser una característica principal de las aplicaciones.

If someone else can run arbitrary code on your computer, it’s not YOUR computer any more. — Rich Kulawiec

Mi búsqueda comenzó cuando quise saber si debía ‘limpiar’ los datos que estaba almacenando o antes de desplegarlos en el cliente, para prevenir un ataque de inyección de javascript. Pues resulta que si utilizas el SDK de firebase o librerías soportadas (AngularFire, EmberFire y ReactFire) – y lo más seguro es que utilices alguna de estas – puedes estar tranquilo, ya que estas se aseguran de no incluir datos sin escapar en el HTML.

Lo que si debes hacer es aplicar reglas de acceso a los datos. Lo más común es que al iniciar un proyecto -y en la mayoría de tutoriales se hace así- cambies las reglas para permitir escritura y lectura desde cualquier cliente, obviamente para diferir la implementación de los mecanismos de autenticación y autorización. Creo que siempre debes tener presente quién y qué datos puede acceder, esto te facilitará crear tu estructura de datos en firebase.

Esto lo explica de manera excelente Jacob Wegner en su plática “The key to firebase security – as told with emojis”

Anuncios

angularjs – bootstrap badge with color

We have an old angularjs + bootstrap 3.3 project. We needed to organize information in tabs and show a visual indicator when they had records in them (we used ngTable by the way), we thought using badges fits perfectly into our design. So we added them as follows.

<ul class="nav nav-tabs">
        <li class="active">https://getbootstrap.com/docs/3.3/
            <a href="" data-target="#documentos" data-toggle="tab">
                Documentos <span class="badge">{{tblSeguimientoDocumentos.data.length}}</span>
            </a>            
        </li>
        <li>
            <a href="" data-target="#audiencias" data-toggle="tab">
                Audiencias <span class="badge">{{tblSeguimientoAudiencias.data.length}}</span>
            </a>
        </li>
        <li>
            <a href="" data-target="#solicitudes" data-toggle="tab">
                Solicitudes <span class="badge">{{tblSeguimientoSolicitudes.data.length}}</span>
            </a>
        </li>
    </ul>

then we tried to use colors for the badges to highlight the tabs that had results in it with the ng-class directive

<span ng-class="{'badge-info': tblSeguimientoDocumentos.data.length > 0}" 
class="badge">{{tblSeguimientoDocumentos.data.length}}</span>

well, in previous versions (2.3.2) and later versions (4.3) it worked. But those classes aren’t available in 3.3, so you have to add your own. We added ours into a main.css file thats added in the index.html page.

/**
BADGE COLORS https://codepen.io/MarcosBL/pen/uomCD
**/

.badge:hover {
  color: #ffffff;
  text-decoration: none;
  cursor: pointer;
}
.badge-error {
  background-color: #b94a48;
}
.badge-error:hover {
  background-color: #953b39;
}
.badge-warning {
  background-color: #f89406;
}
.badge-warning:hover {
  background-color: #c67605;
}
.badge-success {
  background-color: #468847;
}
.badge-success:hover {
  background-color: #356635;
}
.badge-info {
  background-color: #3a87ad;
}
.badge-info:hover {
  background-color: #2d6987;
}
.badge-inverse {
  background-color: #333333;
}
.badge-inverse:hover {
  background-color: #1a1a1a;
}

angularjs – bootstrap tabs route conflict

In an old angularjs app where we used bootstrap 2.3.2 we wanted to implement a tab component to separate results from different sources.

We added a tab component as shown in the docs

<ul class="nav nav-tabs">
  <li><a href="#home" data-toggle="tab">Home</a></li>
  <li><a href="#profile" data-toggle="tab">Profile</a></li>
  <li><a href="#messages" data-toggle="tab">Messages</a></li>
  <li><a href="#settings" data-toggle="tab">Settings</a></li>
</ul>

<div class="tab-content">
  <div class="tab-pane active" id="home">...</div>
  <div class="tab-pane" id="profile">...</div>
  <div class="tab-pane" id="messages">...</div>
  <div class="tab-pane" id="settings">...</div>
</div>

but it navigated away from the page (state), instead of switching tabs. The problem is the angularjs routing mechanism, it uses bang hashtag navigation -it means it uses the url address to know which route is active, actual navigation doesn’t happen, remember it is SPA (Single Page Application)-
So, in the previous example when the profile tab is clicked it changed the url to http://myapp/index.html#/profile because of the href we used.

The solution is quite simple and I found it here, just change the href attributes to data-target and add an empty href attribute (to change the cursor as it would do with links).

<ul class="nav nav-tabs">
  <li><a href="" data-target="#home" data-toggle="tab">Home</a></li>
  <li><a href="" data-target="#profile" data-toggle="tab">Profile</a></li>
  <li><a href="" data-target="#messages" data-toggle="tab">Messages</a></li>
  <li><a href="" data-target="#settings" data-toggle="tab">Settings</a></li>
</ul>

<div class="tab-content">
  <div class="tab-pane active" id="home">...</div>
  <div class="tab-pane" id="profile">...</div>
  <div class="tab-pane" id="messages">...</div>
  <div class="tab-pane" id="settings">...</div>
</div>

jhipster – fontawesome icons

I was trying to use another a lock icon to show when a row is locked, but when trying to use the following code

<fa-icon [icon]="'lock'"></fa-icon>

it threw the following exception

angular-fontawesome.js?1dff:89 FontAwesome: Could not find icon with iconName=lock and prefix=fas

well, you just have to import the icon in the src/main/webapp/app/vendor.ts file.
It should be noted in the docs somewhere. At least, it is pointed out in the jhipster mini book.

import {
    // other imports
    faFileSignature,
    faLock
} from '@fortawesome/free-solid-svg-icons';

// other imports
library.add(faFileSignature);
library.add(faLock);

angular – jhipster disable grid row

You always have catalogs in a system. In our case, we wanted to preserve the initial records of them because they were required to be immutable (i.e. they should not change) in order to interchange information with another vendor.

First we added a field to our tables to know if they’re locked or not.

        <addColumn tableName="tc_institucion">
            <column name="blocked" type="varchar(1)"/>
        </addColumn>

then updated the entities extending from an abstract class (you can do it in many different ways)

@MappedSuperclass
public abstract class AbstractLockedEntity {

    @Column(name = "blocked")
    @Convert(converter = BooleanConverter.class)
    private Boolean locked;

    // getters and setters
}

note that we used a converter to convert between Boolean and String. We store ‘S’ for true and ‘N’ for false (idiomatic bias, could be ‘T’ and ‘F’).

@Converter
public class BooleanConverter implements AttributeConverter<Boolean, String> {
    @Override
    public String convertToDatabaseColumn(Boolean value) {
        if(value == null){
            return "N";
        }
        return value? "S": "N";
    }

    @Override
    public Boolean convertToEntityAttribute(String s) {
        if(s == null){
            return false;
        }
        return s.equals("S") ? true: false;
    }
}

we need to update our client entities as well. Since jhispter generates an interface for each of them, we extended them from a new interface called IEntityLocked

export interface IEntityLocked {
    locked?: boolean;
}

then we had

export interface IInstitucion extends IEntityLocked {
    id?: number;
    nombre?: string;
    clave?: string;
}

finally we updated our components (pages, views, you name them) by just adding the ‘table-secondary’ class to every row that is locked, displaying a locked icon instead of the id, and disabling buttons.

            <tr *ngFor="let institucion of institucions ;trackBy: trackId" [ngClass]="{'table-secondary': institucion.locked}">
                <td [ngSwitch]="institucion.locked">
                    <a *ngSwitchCase="false" [routerLink]="['/institucion', institucion.id, 'view' ]">{{institucion.id}}</a>
                    <fa-icon *ngSwitchCase="true" [icon]="'lock'"></fa-icon>
                </td>
                <td>{{institucion.clave}}</td>
                <td>{{institucion.nombre}}</td>
                <td class="text-right">
                    <div class="btn-group flex-btn-group-container">


                            <span class="d-none d-md-inline">View</span>



                            <span class="d-none d-md-inline">Edit</span>



                            <span class="d-none d-md-inline">Delete</span>

                    </div>
                </td>
            </tr>

sources:
https://toddmotto.com/ng-class-angular-classes#property-binding-with-classname
https://getbootstrap.com/docs/4.0/utilities/colors/
https://getbootstrap.com/docs/4.0/content/tables/
https://fontawesome.com/icons?d=gallery&q=lock

jhipster – use description in enums instead of key names

I used jhipster to generate an entity which have a property of type enum.

jhipster entity tipoEstudio
What are the values of your enumeration (separated by comma, no spaces)? SUPERIOR,MEDIA_SUPERIOR,BASICA

because i couldn’t use spaces or special characters (diacritics i.e. accents) in enum names I had to shorten the description a little bit.

It generated the following code

export const enum TipoEducativo {
    SUPERIOR = 'SUPERIOR',
    MEDIA_SUPERIOR = 'MEDIA_SUPERIOR',
    BASICA = 'BASICA'
}

export interface ITipoEstudio {
    id?: number;
    nombre?: string;
    tipoEducativo?: TipoEducativo;
}

export class TipoEstudio implements ITipoEstudio {
    constructor(public id?: number, public nombre?: string, public tipoEducativo?: TipoEducativo) {}
}

The problem was that the values stored in the database came as (note the spaces and diacritics)

    'EDUCACIÓN SUPERIOR',
    'EDUCACIÓN MEDIA SUPERIOR',
    'EDUCACIÓN BÁSICA'

In order to be able to use those values I had to first add a description property in the enum

public enum TipoEducativo {
    SUPERIOR("EDUCACIÓN SUPERIOR"), MEDIA_SUPERIOR("EDUCACIÓN MEDIA SUPERIOR"), BASICA("EDUCACIÓN BÁSICA");

    private String desc;

    TipoEducativo(String desc) {
        this.desc = desc;
    }

    public String getDesc() {
        return desc;
    }

    public static TipoEducativo getTipo(String desc){
        if(desc == null){
            return null;
        }

        for(TipoEducativo tipoEducativo: TipoEducativo.values()){
            if(desc.equals(tipoEducativo.desc)){
                return tipoEducativo;
            }
        }

        throw new IllegalArgumentException("No existe el TipoEducativo para " + desc);
    }

}

And then change the Java class for the Entity by removing the @Enumerated annotation and adding a converter for the enum field.

@Entity
@Table(name = "tipo_estudio")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class TipoEstudio implements Serializable {

    // id, constructor, etc

    @NotNull
    @Convert(converter = TipoEducativoConverter.class)
    @Column(name = "stipo_educativo", nullable = false)
    private TipoEducativo tipoEducativo;

    // getters, setters, etc

}

TipoEducativoConverter.java

@Converter
public class TipoEducativoConverter implements AttributeConverter<TipoEducativo, String> {


    @Override
    public String convertToDatabaseColumn(TipoEducativo tipoEducativo) {
        return tipoEducativo.getDesc();
    }

    @Override
    public TipoEducativo convertToEntityAttribute(String desc) {
        return TipoEducativo.getTipo(desc);
    }
}

With these changes the app was reading correctly the enum type field and was storing the correct description for its value. The only grip I had then was that in the web client UI the underscored descriptions were being showed instead of the long descriptions.

I thought that if I changed the description in the enum type it would use those in the UI, so i changed it like so

export const enum TipoEducativo {
    SUPERIOR = 'EDUCACIÓN SUPERIOR',
    MEDIA_SUPERIOR = 'EDUCACIÓN MEDIA SUPERIOR',
    BASICA = 'EDUCACIÓN BÁSICA'
}

but it changed nothing. I had to change the html and component as follows

<tr *ngFor="let tipoEstudio of tipoEstudios ;trackBy: trackId">
                <td><a [routerLink]="['/tipo-estudio', tipoEstudio.id, 'view' ]">{{tipoEstudio.id}}</a></td>
                <td>{{tipoEstudio.nombre}}</td>
                <td>{{TipoEducativo[tipoEstudio.tipoEducativo]}}</td>
                <!-- button columns --> 
            </tr>

tipo-estudio.component.ts

// other imports
import { ITipoEstudio, TipoEducativo } from 'app/shared/model/tipo-estudio.model';

@Component({
    selector: 'jhi-tipo-estudio',
    templateUrl: './tipo-estudio.component.html'
})
export class TipoEstudioComponent implements OnInit, OnDestroy {
    // other fields
    TipoEducativo = TipoEducativo;

    constructor() {}

    // other methods
}

which led to this error

error TS2476: A const enum member can only be accessed using a string literal.

the key thing is

const in an enum means the enum is fully erased, which means you can’t index it by an arbitrary value. Just remove the const modifier.

as explained here

Finally I removed the const keyword and was able to use the descriptions in the enum instead of key names.

Note however that you still have to replace the code generated by jhipster on select items since they’re hard coded like so.

<select class="form-control" name="tipoEducativo" [(ngModel)]="tipoEstudio.tipoEducativo" id="field_tipoEducativo"  required>
                        <option value="SUPERIOR"> EDUCACIÓN SUPERIOR</option>
                        <option value="MEDIA_SUPERIOR">EDUCACIÓN MEDIA SUPERIOR</option>
                        <option value="BASICA">EDUCACIÓN BÁSICA</option>
                    </select>

sources:
Best approach to JPA enumerated types mapping
Mapping enums with a fixed ID in JPA – An alternative to String and Ordinal
Mapping enums done right with @Convert in JPA 2.1
Get TypeScript enum name from instance
const enum in Typescript
How do the different enum variants work in TypeScript?

ubuntu 18.04 – disable network printer auto discovery

Screenshot from 2019-02-11 11-06-44

Since I upgraded to Ubuntu 18.04 it always bothered me that when I tried to add a specific network printer it would add hundreds of printers in my network (same model so it named them similar).

Well, I found in stackoverflow how to disable auto discovery.

edit /etc/avahi/avahi-daemon.conf and insert below the [server] section this line:

enable-dbus=no

then restart the avahi-daemon service:

sudo service avahi-daemon stop
sudo service avahi-deamon start

The problem later was that the printing dialog in Chrome took a long time to load, so I reverted the configuration back.