Focus App – Dynamic personal landing page for your browser

Last week I created this little minimalist app with vanilla JavaScript, having features such as current weather, to-do list, etc. It’s entirely open-source. Check its GitHub repository for more details.

From the project’s readme file:

Focus is an application that aims to help you better organize your day. It contains interesting features as well as astonishing background images and beautiful minimalist responsive design. It is built with vanilla JavaScript and its whole code weights less than 25kb!

Online demo: https://focus.dthlabs.com
Source code: https://github.com/xdth/focus
Screenshots:

“GoToTop”: a (scroll to top elevator) styled component for React JS with TypeScript

I am sharing here a “GoToTop” React JS component that I created today. This component will render a button (shaped as an arrow) when the user scrolls down, past a certain point. When clicked, this button will execute a handleGoToTop() function that will smoothly scroll the screen back to the top.

This is a styled component, making it very portable. It also uses React hooks and TypeScript.

1. The “GoToTop” component

// src/components/GoToTop/index.tsx

import React, { useState, useEffect } from 'react';
import { Container } from './styles';

const GoToTop: React.FC = () => {
  const [scrolled, setScrolled] = useState(false);

  useEffect(() => {
    window.addEventListener('scroll',() => {
      const isTop = window.scrollY < 150;

      isTop !== true ? setScrolled(true) : setScrolled(false);
    })
  }, []);

  function handleGoToTop() {
    window.scrollTo({
      top: 0,
      behavior: "smooth"
    });
  } 
  
  return (
    <>
      <Container>
        { scrolled && <button id="goToTop" onClick={() => handleGoToTop()} title="Go to top"></button> }
      </Container>
    </>
  );
}

export default GoToTop;

Read more ““GoToTop”: a (scroll to top elevator) styled component for React JS with TypeScript”

Getting Started with Styled Components in React JS and TypeScript

Among the several strategies aimed at increasing the productivity of a development team, the proper organization of the code related to the software being conceived undoubtedly occupies a preponderant place. Over the years, several methods and tools have been created for this purpose. It is important to know them, especially since they can very concretely result in a substantial saving of time, at least in terms of maintenance activities and bug fixing.

In this context, we’ll take a look at how to deploy styled components in a React JS project with TypeScript using the styled-components library. This technique allows components to contain their own styles. This “encapsulation” of styles also involves CSS in JS, using tagged template literals.

Youtube demo:

Github repository: https://github.com/xdth/styled-components-demo

First step: generation of files and installation of project dependencies

Generate React project files with TypeScript

create-react-app styled-components-demo --template typescript

Read more “Getting Started with Styled Components in React JS and TypeScript”

goMarketplace

One more Rocketseat challenge completed!โœ”๏ธ ๐ ๐จ๐Œ๐š๐ซ๐ค๐ž๐ญ๐ฉ๐ฅ๐š๐œ๐ž is an e-commerce app, built with #ReactNative, #TypeScript and applying techniques such as #TDD, async storage and context API.

Demo

Screenshots

goMarketplace

Source code

Available on my github: https://github.com/xdth/goMarketplace

API security and CORS: a NodeJS implementation

NodeJS logo

What is CORS

By default, browsers will block certain requests if both the client and the server are not in the same origin. Cross-origin resource sharing (CORS) is a specification designed to allow restricted resources from a remote server in a given origin, to be requested by a client associated to a different origin. An origin, as defined by the RFC6454, implies “identical schemes, hosts and ports”.

Usually the request from the browser will be accompanied by its corresponding HTTP headers, including the request’s origin. Example of the HTTP headers on the request:

Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:3001/
Origin: http://localhost:3001
Connection: keep-alive
Cache-Control: max-age=0
If-None-Match: W/”10-iv0euXUvX8F10Ha2yy45d6DFMcI”

How does CORS work?

When CORS is not enabled, the response will not contain the Access-Control-Allow-Origin header and the browser will likely block it, as illustrated by the diagram below.

You will notice that although both the API and the client are in the same domain, the different HTTP ports result in both having different origins.
Read more “API security and CORS: a NodeJS implementation”

Quick user authentication and CRUD in Symfony 5

We will leverage on Symfony’s generators to quickly code a simple user authentication and CRUD system in less than 15 minutes.

Let’s start by creating a new Symfony project, which we will call sym_auth.

symfony new --full sym_auth

Then we will edit the .env file in the root folder, adding our database credentials.

DATABASE_URL=mysql://sym_auth:sym_auth@127.0.0.1:3306/sym_auth?serverVersion=5.7

Read more “Quick user authentication and CRUD in Symfony 5”

Symfony 5 – Select (or check box) for user roles in a form

For choosing between a html select or checkboxes on your form, just toggle the “multiple” parameter on the ChoiceType class. Since the roles are an array, we need a data transformer.

Example:

<?php

namespace App\Form;

use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\CallbackTransformer;

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('email')
            ->add('Roles', ChoiceType::class, [
                    'required' => true,
                    'multiple' => false,
                    'expanded' => false,
                    'choices'  => [
                      'User' => 'ROLE_USER',
                      'Partner' => 'ROLE_PARTNER',
                      'Admin' => 'ROLE_ADMIN',
                    ],
                ])

            ->add('password')
            ->add('groups')

        ;


        // Data transformer
        $builder->get('Roles')
            ->addModelTransformer(new CallbackTransformer(
                function ($rolesArray) {
                     // transform the array to a string
                     return count($rolesArray)? $rolesArray[0]: null;
                },
                function ($rolesString) {
                     // transform the string back to an array
                     return [$rolesString];
                }
        ));


    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => User::class,
        ]);
    }
}

Set a bootstrap menu item as “active” in Symfony 5

In order to define a bootstrap menu item as “active” in a Symfony 5 project, you can add

{% set route_name = app.request.attributes.get('_route') %}

to the top of your base.html.twig. Then a twig condition in the navbar can be implemented as follows:

<li {% if route_name == "user_index" %} class="nav-item active" {% else %} class="nav-item" {% endif %} >

Read more “Set a bootstrap menu item as “active” in Symfony 5″

Installing GitLab on Debian 9 with SSL and custom apache vhost

Before you start

First you need to make sure that:
– Your LAMP is up and running
– You have a working DNS for the domain you want to use for gitlab
– You have certbot already installed

Part I – gitlab

Prepare the system for the gitlab install

apt-get update && apt-get upgrade

Install dependencies. Choose “internet site” and press enter.

apt-get install -y curl openssh-server ca-certificates postfix

Add the gitlab repositories

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash

Read more “Installing GitLab on Debian 9 with SSL and custom apache vhost”

qFirewall (qfw) – a quick iptables firewall script

This is my new basic firewall script. For updates, check my github: https://github.com/xdth

Screenshot

Code

#! /bin/bash

# ######################### qFirewall (qfw) 0.1 ########################
#
# This is a basic iptables firewall script.
#
# Usage:
# ./qfw {start|stop}
#
# Notes:
# 1. Comment or uncomment the firewall rules below according to your
#    needs.
# 2. For convenience, add this script to your /usr/bin or alike with
#    chmod +x permissions.
# 2. License: MIT
# 3. Author: dth at dthlabs dot com
#    Site:   https://dthlabs.com
#    github: https://github.com/xdth
#
# Brussels, Jan 23, 2018
# note: https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
# #######################################################################


# #######################################################################
# ## Rules function -- edit this according to your needs

function qfw_rules {
  # Block everything
  iptables -t filter -P INPUT DROP
  iptables -t filter -P FORWARD DROP
  iptables -t filter -P OUTPUT DROP
  echo "     > Block everything"

  # Don't break established connections
  iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  echo "     > Don't break established connections"

  # Authorize loopback (127.0.0.1)
  iptables -t filter -A INPUT -i lo -j ACCEPT
  iptables -t filter -A OUTPUT -o lo -j ACCEPT
  echo "     > Authorize Loopback"

  # ICMP (ping)
  iptables -t filter -A INPUT -p icmp -j ACCEPT
  iptables -t filter -A OUTPUT -p icmp -j ACCEPT
  echo "     > Authorize ICMP (ping)"

  # SSH in/out
  iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 22 -j ACCEPT
  iptables -t filter -A INPUT -p tcp --dport 9000 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 9000 -j ACCEPT
  echo "     > Authorize SSH"

  # DNS in/out
  iptables -t filter -A OUTPUT -p tcp --dport 53 -j ACCEPT
  iptables -t filter -A OUTPUT -p udp --dport 53 -j ACCEPT
  iptables -t filter -A INPUT -p tcp --dport 53 -j ACCEPT
  iptables -t filter -A INPUT -p udp --dport 53 -j ACCEPT
  echo "     > Authorize DNS"

  # NTP Out
  iptables -t filter -A OUTPUT -p udp --dport 123 -j ACCEPT
  echo "     > Authorize NTP outbound"

  # HTTP + HTTPS Out
  iptables -t filter -A OUTPUT -p tcp --dport 80 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 443 -j ACCEPT
  # iptables -t filter -A OUTPUT -p tcp --dport 8080 -j ACCEPT

  # HTTP + HTTPS In
  iptables -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
  iptables -t filter -A INPUT -p tcp --dport 443 -j ACCEPT
  # iptables -t filter -A INPUT -p tcp --dport 8443 -j ACCEPT
  # iptables -t filter -A INPUT -p tcp --dport 8080 -j ACCEPT
  echo "     > Authorize http and https"

  # FTP Out
  iptables -t filter -A OUTPUT -p tcp --dport 21 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 20 -j ACCEPT

  # FTP In
  iptables -t filter -A INPUT -p tcp --dport 20 -j ACCEPT
  iptables -t filter -A INPUT -p tcp --dport 21 -j ACCEPT
  iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
  echo "     > Authorize FTP"

  # Mail SMTP
  iptables -t filter -A INPUT -p tcp --dport 25 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 25 -j ACCEPT
  iptables -t filter -A INPUT -p tcp --dport 587 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 587 -j ACCEPT
  iptables -t filter -A INPUT -p tcp --dport 465 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 465 -j ACCEPT

  # Mail POP3:110
  iptables -t filter -A INPUT -p tcp --dport 110 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 110 -j ACCEPT

  # Mail IMAP:143
  iptables -t filter -A INPUT -p tcp --dport 143 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 143 -j ACCEPT

  # Mail POP3S:995
  iptables -t filter -A INPUT -p tcp --dport 995 -j ACCEPT
  iptables -t filter -A OUTPUT -p tcp --dport 995 -j ACCEPT
  echo "     > Authorize mail"

  # OpenVZ Web Pannel
  # iptables -t filter -A OUTPUT -p tcp --dport 3000 -j ACCEPT
  # iptables -t filter -A INPUT -p tcp --dport 3000 -j ACCEPT
  # echo "     > Authorize OpenVZ panel"

  # Allow WMs
  # iptables -P FORWARD ACCEPT
  # iptables -F FORWARD
  # echo "WMs ok"
  # echo "     > Authorize WMs"

  # Saltstack
  # iptables -t filter -A OUTPUT -p tcp --dport 4505 -j ACCEPT
  # iptables -t filter -A INPUT -p tcp --dport 4505 -j ACCEPT
  # iptables -t filter -A OUTPUT -p tcp --dport 4506 -j ACCEPT
  # iptables -t filter -A INPUT -p tcp --dport 4506 -j ACCEPT
  # echo "     > Authorize Saltstack"

  # Block UDP attack
  # iptables -A INPUT -m state --state INVALID -j DROP
  # echo "     > Block UDP attack"

}


# #######################################################################
# ## Other functions

function qfw_help {
  echo "qFirewall usage: ./qfw {start|stop}"
  exit 1
}

function qfw_seeya {
  echo "     > Thanks for using qFirewall (qfw) v1. Have a good day."
  echo ""
  echo ""
}

function qfw_separator {
  echo ""
  echo ""
  echo "===================== qFirewall (qfw) v0.1 ====================="
  echo ""
}

function qfw_reset {
  iptables -F
  iptables -X
  iptables -t nat -F
  iptables -t nat -X
  iptables -t mangle -F
  iptables -t mangle -X
  iptables -P INPUT ACCEPT
  iptables -P FORWARD ACCEPT
  iptables -P OUTPUT ACCEPT
  iptables -t filter -F
  iptables -t filter -X
}

function qfw_start {
  qfw_separator
  echo "     > Starting qFirewall..."
  qfw_clean
  echo "     > Loading the rules..."
  qfw_rules
  echo "     > Rules loaded"
  echo "     > qFirewall started"
}

function qfw_clean {
  echo "     > Cleaning rules..."
  qfw_reset
  echo "     > Rules cleaned"
}

function qfw_stop {
  qfw_separator
  echo "     > Stopping qFirewall..."
  qfw_clean
  echo "     > qFirewall stopped"
}


# #######################################################################
# ## Main

case "$1" in
  start)
  qfw_start
  ;;
  stop)
  qfw_stop
  ;;
  *)
  qfw_help
  exit 1
  ;;
esac

qfw_seeya

exit 0