Categories
Vuetify

Vuetify — Slide Group

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Slide Item Active Class

We can change the active class of the slide items with the active-class prop:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-sheet class="mx-auto" elevation="8" max-width="800">
          <v-slide-group
            v-model="model"
            class="pa-4"
            prev-icon="mdi-minus"
            next-icon="mdi-plus"
            show-arrows
            active-class="success"
          >
            <v-slide-item v-for="n in 15" :key="n" v-slot:default="{ active, toggle }">
              <v-card
                :color="active ? 'primary' : 'grey lighten-1'"
                class="ma-4"
                height="200"
                width="100"
                [@click](http://twitter.com/click "Twitter profile for @click")="toggle"
              >
                <v-row class="fill-height" align="center" justify="center">
                  <v-scale-transition>
                    <v-icon
                      v-if="active"
                      color="white"
                      size="48"
                      v-text="'mdi-close-circle-outline'"
                    ></v-icon>
                  </v-scale-transition>
                </v-row>
              </v-card>
            </v-slide-item>
          </v-slide-group>
        </v-sheet>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    model: undefined,
  }),
};
</script>

The show-arrows prop make the navigation arrow show on both sies.

Also, we have the active-class prop to style the selected item differently.

Mandatory

We can make at least one item be selected in the group with the mandatory prop:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-sheet class="mx-auto" elevation="8" max-width="800">
          <v-slide-group
            v-model="model"
            class="pa-4"
            prev-icon="mdi-minus"
            next-icon="mdi-plus"
            show-arrows
            mandatory
          >
            <v-slide-item v-for="n in 15" :key="n" v-slot:default="{ active, toggle }">
              <v-card
                :color="active ? 'primary' : 'grey lighten-1'"
                class="ma-4"
                height="200"
                width="100"
                @click="toggle"
              >
                <v-row class="fill-height" align="center" justify="center">
                  <v-scale-transition>
                    <v-icon
                      v-if="active"
                      color="white"
                      size="48"
                      v-text="'mdi-close-circle-outline'"
                    ></v-icon>
                  </v-scale-transition>
                </v-row>
              </v-card>
            </v-slide-item>
          </v-slide-group>
        </v-sheet>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    model: undefined,
  }),
};
</script>

Now the first item will be selected by default.

Pseudo Carousel

We can display content below the selected slide.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-sheet class="mx-auto" elevation="8" max-width="800">
          <v-slide-group v-model="model" class="pa-4" show-arrows>
            <v-slide-item v-for="n in 15" :key="n" v-slot:default="{ active, toggle }">
              <v-card
                :color="active ? 'primary' : 'grey lighten-1'"
                class="ma-4"
                height="200"
                width="100"
                @click="toggle"
              >
                <v-row class="fill-height" align="center" justify="center">
                  <v-scale-transition>
                    <v-icon
                      v-if="active"
                      color="white"
                      size="48"
                      v-text="'mdi-close-circle-outline'"
                    ></v-icon>
                  </v-scale-transition>
                </v-row>
              </v-card>
            </v-slide-item>
          </v-slide-group>

          <v-expand-transition>
            <v-sheet v-if="model != null" color="grey lighten-4" height="200" tile>
              <v-row class="fill-height" align="center" justify="center">
                <h3 class="title">{{ model }}</h3>
              </v-row>
            </v-sheet>
          </v-expand-transition>
        </v-sheet>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    model: undefined,
  }),
};
</script>

We added the v-expand-transition component below the v-slide-group to show what we want to the user.

We’ll see a transition effect when we click on the item.

model has the index of the item we clicked on.

Conclusion

We can add slides with the v-slide-group component and let us select items when we click on it.

Categories
Vuetify

Vuetify — List Items and Slide Items

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Mandatory List Item

We can add the mandatory prop to make choosing an item mandatory:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-list flat>
          <v-list-item-group v-model="model" color="indigo" active-class="border">
            <v-list-item v-for="(item, i) in items" :key="i">
              <v-list-item-icon>
                <v-icon v-text="item.icon"></v-icon>
              </v-list-item-icon>

<v-list-item-content>
                <v-list-item-title v-text="item.text"></v-list-item-title>
              </v-list-item-content>
            </v-list-item>
          </v-list-item-group>
        </v-list>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    items: [
      {
        icon: "mdi-wifi",
        text: "Wifi",
      },
      {
        icon: "mdi-bluetooth",
        text: "Bluetooth",
      },
      {
        icon: "mdi-chart-donut",
        text: "Data Usage",
      },
    ],
    model: undefined
  }),
};
</script>

Custom Active Class

The active-class prop can be set to set a custom class for an active item.

For example, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-list flat>
          <v-list-item-group v-model="model" color="indigo" active-class="border">
            <v-list-item v-for="(item, i) in items" :key="i">
              <v-list-item-icon>
                <v-icon v-text="item.icon"></v-icon>
              </v-list-item-icon>

<v-list-item-content>
                <v-list-item-title v-text="item.text"></v-list-item-title>
              </v-list-item-content>
            </v-list-item>
          </v-list-item-group>
        </v-list>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    items: [
      {
        icon: "mdi-wifi",
        text: "Wifi",
      },
      {
        icon: "mdi-bluetooth",
        text: "Bluetooth",
      },
      {
        icon: "mdi-chart-donut",
        text: "Data Usage",
      },
    ],
    model: undefined
  }),
};
</script>

<style scoped>
.border {
  border: 1px solid red;
}
</style>

We just added the border class to see a red outline.

Slide Groups

The v-slide-group component is used to display paginated information.

For instance, we can write:

<template>
  <v-container class="grey lighten-5">
    <v-row>
      <v-col>
        <v-sheet class="mx-auto" elevation="8" max-width="800">
          <v-slide-group
            v-model="model"
            class="pa-4"
            prev-icon="mdi-minus"
            next-icon="mdi-plus"
            show-arrows
          >
            <v-slide-item v-for="n in 15" :key="n" v-slot:default="{ active, toggle }">
              <v-card
                :color="active ? 'primary' : 'grey lighten-1'"
                class="ma-4"
                height="200"
                width="100"
                @click="toggle"
              >
                <v-row class="fill-height" align="center" justify="center">
                  <v-scale-transition>
                    <v-icon
                      v-if="active"
                      color="white"
                      size="48"
                      v-text="'mdi-close-circle-outline'"
                    ></v-icon>
                  </v-scale-transition>
                </v-row>
              </v-card>
            </v-slide-item>
          </v-slide-group>
        </v-sheet>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
export default {
  name: "HelloWorld",
  data: () => ({
    model: undefined,
  }),
};
</script>

to add the v-slide-group component with the v-slide-item components inside for the items.

We use the active boolean to check if the item is selected.

And the toggle function lets us toggle the active state.

Conclusion

We can group items with list item groups and slide item groups.

Categories
Node.js Best Practices

Node.js Best Practices — Tokens and Secrets

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices we should follow when writing Node apps.

Support Blacklisting JWTs

We should be able to blacklist JSON web tokens so that we can lock out malicious users,

There are no mechanisms to do this for most systems.

We can add a list of untrusted tokens to prevent them from logging in.

Prevent Brute-Force Attacks Against Authorization

Brute-force attacks against authorization can be prevented with rate limiting.

For instance, we can limit the login attempts by the block repeated failed login requests.

Run Node.js as a Non-root User

Non-root user should be used to run Node apps.

This way, they can do whatever they want in our system.

We can bake that into the Docker image or set it with the -u flag.

Limit Payload Size Using a Reverse Proxy or a Middleware

Payload size should be limited to avoid overloading our systems.

This can help with preventing DOS attacks.

If the requests’ body size is small, less damage can be done.

We can set express body parser to accept small size payloads with the limit option.

Avoid JavaScript eval Statements

We can avoid JavaScript eval statements.

They’re insecure since code is run from a string.

It also makes optimizations and debugging impossible.

setTimeout , setInterval , and the Function constructor also run code from strings.

So we should avoid passing strings to them as well.

Prevent Evil RegEx from Overloading Single Thread Execution

There’s some regex that we should avoid.

To make data validation easy, we can use a library like validator.js or look up safe regex we can use with safe-regex to detect vulnerable regex patterns to avoid.

Bad regex can make our app susceptible to DOS attacks that block the event loop.

This will make our app hang.

Avoid Module Loading Using a Variable

We shouldn’t call require with a variable.

This way, we can’t let attackers pass anything into the require function.

For instance, instead of writing:

const insecure = require(helperPath);

We write:

const uploadHelpers = require('./helpers/upload');

This also applies to other paths we pass in like when we read a file with fs.readFile .

Run Unsafe Code in a Sandbox

If we have any unsafe code, we should run them in a sandbox.

This way, they can’t get to the outside world and potentially do damage.

NPM packages can be sandboxed. A dedicated process can also be sandboxed.

Take Extra Care When Working with Child Processes

If we run child processes in our Node app, we should sanitize the command string so that we can run without risks.

If we don’t escape them, then attackers can run anything they want, which can be catastrophic.

Hide Error Details from Clients

If there are any details about errors that expose the internals of our system, we should hide them from clients.

This way, the chance of attackers finding ways to attack our app is much lower.

Anything like paths, stack traces, and more should be hidden.

Conclusion

We should hide sensitive data, isolate risky code, and escape any strings that are potentially malicious.

Categories
Node.js Best Practices

Node.js Best Practices — Test and Arrow Functions

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices we should follow when writing Node apps.

Use Arrow Function Expressions

Arrow functions are a great feature of modern JavaScript.

It lets us write callbacks without binding to a new value of this inside the callback.

Also, it’s more compact.

We should use to avoid bugs and have easier to read code.

Write API Tests

API tests let us check the results of our APIs.

We’ll know right away from the tests if we don’t get what we want.

They’re fast so we can test without lifting a finger.

Also, they’re great for documenting how to call our APIs.

There’re other kinds of tests like performance tests, database tests, etc. that we can do as well.

Include 3 Parts in Each Test Name

Our tests should be self explanatory.

So we should state in the test name what’s being tested.

Also, we should state what circumstances are being tested and what’s the expected result.

This way, no one will be confused with what we’re testing.

For instance, we can write:

describe('Item Service', () => {  
  describe('Add new item', () => {  
    it('When no price is specified, then the item status rejected', () => {  
      const item = new ItemService().add(...);  
      expect(item.status).to.equal('rejected');  
    });  
  });  
});

We have the describes labeling what unit we’re testing.

And the string we pass into it has the scenario we’re testing.

The expect call and the it string have the expectation.

Detect Code Issues with a Linter

We can detect code issues with a linter so that we can detect antipatterns early.

To make this easy, we can add a pre-commit hook that runs before a commit is made to do the check.

Avoid Global Test Fixtures and Seeds and Add Data Per Test

Test fixtures should be added per test.

And the data should be scrubbed after each test.

This way, we won’t have tests that are dependent on each other.

With this done, every test should run in isolation so we can run them in any order.

Inspect for Vulnerable Dependencies

We should inspect for vulnerable dependencies so that we can update them.

This way, we can update them and avoid attackers attacking our app with those vulnerabilities.

To do this, we can run npm audit or other tools.

Tag Our Tests

We can tag our tests so that they run before a commit is made.

We run the ones that must be run to prevent committing any that breaks out code.

Otherwise, we’ll run all tests all the time, which is probably too slow for most apps before commit.

Check Test Coverage

Checking for test coverage lets us identify any decreases and check for things we missed in our tests.

Tools like Istanbul/nyc can check test coverage in our code so that we get a clear idea of what’s needed to be tested.

Conclusion

We should use arrow functions.

And we should have good test coverage in our code.

Categories
Node.js Best Practices

Node.js Best Practices — Syntax Issues

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices we should follow when writing Node apps.

Start a Code Block’s Curly Braces on the Same Line

The curly braces should be one the same line as the opening statement.

For example, instead of writing:

function foo()
{
  // code block
}

We write:

function foo() {
  // code block
}

This helps us avoid unexpected results.

If we have:

function foo()
{
  return;
  {
    bar: "fantastic"
  };
}

Then the return and the object is considered separate.

If we put the opening curly brace beside the return , then they’ll be considered one statement.

Separate Statements Properly

We have should separate statements properly.

For example, we can write:

function doThing() {
  // ...
}

doThing()

const items = [1, 2, 3]
items.forEach(console.log)

On the other hand, we should avoid typos like:

const m = new Map()
const a = [1,2,3]
[...m.values()].forEach(console.log)

The last 2 lines are considered to be the same statement and will throw a syntax error.

Another example would be:

const count = 2
(function foo() {
  // do something
}())

2 is considered to be a function with the parentheses on the new line.

To avoid all these issues, we should put semicolons to separate them.

Name Our Functions

We should name our functions so that we can trace functions by name when debugging.

Debugging using the core dump might be a challenge if we see significant issues with memory consumption from anonymous functions.

Use Naming Conventions for Variables, Constants, Functions, and Classes

Naming conventions for variables, constants, functions, and classes should follow common conventions.

Lower camel case should be used for naming constants, variables, and functions.

Upper camel case should be used for classes.

This helps us distinguish between plain variables or functions and classes.

Also, we should use descriptive names but keep them short.

Prefer const over let and Ditch the var

var shouldn’t be used for declaring variables anymore.

Their scope is tricky.

let and const are block-scoped, so where they’re available are clear.

const is better than let since we can’t reassign them to a new value.

Require Modules First, not Inside Functions

Modules should be required at the top of modules so that we can find errors and other issues when the module loads.

If they’re inside functions, then we see the issues with require only when we run the code.

So this just isn’t a good idea.

Also, requires are run synchronously by Node, so if they take a long time, then they may block code that is after the require.

Require Modules by Folders as Opposed to the Files Directly

We should place an index.js file that exposes the module’s intervals so consumers will pass through it.

This lets us create an interface that makes future changes easier without breaking the contract.

For example, we can write:

module.exports.foo = require("./foo");
module.exports.bar = require("./bar");

rather than:

module.exports.foo = require("./foo/foo.js");
module.exports.bar = require("./bar/bar.js");

to avoid importing JavaScript modules directly inside their folder.

Conclusion

We should consider syntax changes that make our lives easier and avoid errors.