Best-Practices

Type Script Linting

To create a uniform coding style you should lint your typescript code. We base all of our typescript configuration on the tslint-config-airbnb package.

tslint.json
{
  "extends": "tslint-config-airbnb",
}


Yarn

Yarn is the package manager used in JavaScript projects.

Keeping your dependencies up to date

In modern JavaScript application you usually a lot of dependencies. You should take good care to keep all you dependencies up to date.

You can generate a report of the dependencies that are out of date by running:

Yarn - generate out of date report
yarn outdated

You can find more information about the command in the yarn outdated documentation.


You can now update your packages by using the yarn upgrade command:

Upgrading dependencies will probably break some stuff in your project, so make sure you have enough time to fix the problems that will occur (Lächeln)


yarn upgrade
yarn upgrade --latest

This will update all dependencies in your package.  More information about the command can be found in the yarn upgrade documentation.

Scanning for vulnerability

Yarn also provides a way to scan for known vulnerabilities in your dependencies. You can do this by running:

yarn audit
yarn audit

Supported Packages

This is a list of packages that are used in many VSETH projects and if possible you should also prefer these packages over other packages that do the same thing.


PackageDescription
historyManaging browser history (back and forward)
js-cookieSimple library for managing cookies.
Papaparse


TODO


Removing Unused dependencies


Run `npx depcheck` to see which dependencies are no longer needed.


Translations with i18next

A lot of members of ETH Zurich do not speak german, so it is very important for the IT tohave tools that can be easily translated into multiple languages. I18next is an internationalization-framework written in and for JavaScript

Conventions

It is encouraged to keep the translations in JSON Files that are imported in the i18next configuration. 

  • Use one object to hold the translation for each page or component.
  • Give the object holding the translation of a page the name of the page.
  • Give the object holding the translation of a component the name of the compontent.
  • Give descriptive names to the properties of every object.
  • Eliminating redundancies is not a goal. However, there are some useful translations that are described not in the object for the page it is used on, but in special utility objects. They are used to increase the recognition of the translations. These are
    • buttons translations for buttons in the VSETH Webinterface
    • formValidation translations for validations of forms
    • forms  translations for the fields in forms
    • and whatever is important in your project

Below is an example for a translation JSON file that is for a website that has 

  • three pages HelloPage, I18nPage, AccountEditPage
  • a Navbar component
  • an ErrorScreen component
  • some buttons and forms


yarn audit
export const i18n_english = {
  translation: {
    lang: "en",
	buttons: {
      edit: "Edit",
      save: "Save",
      cancel: "Cancel",
      back: "Back",
	  changeLanguage: "Change language",
    },
    formValidation: {
      required: "Required",
      tooShort: "Too short",
      emailInvalid: "Invalid Email",
    },
    forms: {
      username: "Username",
      firstName: "First Name",
      lastName: "Last Name",
      email: "Email",
    },
    HelloPage: {
      title: "Welcome to VSETH Account",
      body: "THis service provides you a centralized place to manage all your VSETH data.",
    },
    I18nPage: {
      title: "Translations are important!",
      introduction:
        "A lot of members of ETH Zurich do not speak german, so it is very important for the IT to tools that can be easily translated into multiple languages. This template showcases how this can be achieved.",
    },
    AccountEditPage: {
      editBasicInfo: "Edit Basic Information",
      editAddress: "Edit Address",
      editBankingInfo: "Edit Banking Information",
    },
    Navbar: {
      home: "Home",
      account: "Account",
    },
    ErrorScreen: {
      title: "An error occurred.",
      body: "Try reloading the page and contact the administrator if the error persists.",
    }
  }
};

Redirects

Redirects can be dangerous and are commonly misused for phishing. Thus, we recommend you follow some general best practices when using redirects in your apps.

  1. Don't let a user-controlled input specify the redirect URL. (Open Redirects)
    This is a common mistake where one creates a `/redirect?url=<path>` route, which then handles all redirects on the page. This is dangerous as it allows to create URLs that look trustworthy ("vseth.ethz.ch/...") but could lead anywhere.
    (See https://cwe.mitre.org/data/definitions/601.html for more info)
  2. If you can't follow (1) for some reason, filter/validate the target URL
    For example, only allow redirects to pages that you expect these redirects to go to. Keep this validation as strict as possible.
  3. Set specific parameters according to best practices
    When a new tab is opened, this tab's content generally has access to the referrer's content! This can be abused in various malicious ways.
    Thus, one should set the following parameter on the redirect anker "rel="noopener noreferrer"". This way the new page/tab doesn't have access to the original page's content and doesn't learn anything about it.
    If the redirect is done programmatically (i.e., "newWindow=window.open("<url>", target="_blank"), one should additionally set the "newWindow.opener=null" after the call.
    (More about this: https://owasp.org/www-community/attacks/Reverse_Tabnabbing)