Nim web application example

Tagged example, jester, nim  Languages bash, nim
brew install nimlang
nimble install jester
vim hello.nim
nim compile --run hello.nim
import jester, asyncdispatch, strutils, asyncnet, htmlgen, logging
#
# * CLI *
#
# brew install nimlang
# nimble install jester
# vim hello.nim
# nim compile --run hello.nim
#
# * DOCS *
#
# https://nim-lang.org/docs/htmlgen.html
# https://learnxinyminutes.com/docs/nim/
#
var L = newConsoleLogger()
addHandler(L)

settings:
  port = Port(3000)
  appName = "/"
  bindAddr = "127.0.0.1"

proc layout(content: string): string =
  htmlgen.html(htmlgen.body(content))

routes:
  get "/":
    logging.debug("render form $1 $2" % [$status, $headers])
    var content = `div`(
        h1(a(href="http://nim-lang.org", title="Hello", "Hello Nim")),
        """
        <form name="input" action="$1" method="post">
          <input type="text" name="first_name" value="" placeholder="First name" />
          <input type="text" name="last_name" value="" placeholder="Last name" />
          <input type="submit" value="Submit" />
        </form>
        """ % [uri("/", absolute = false)]
        )
    body.add(layout(content))
    status = Http200

  post "/":
    logging.debug("process form $1 $2" % [$status, $headers])
    # TODO: How can we sanitize submitted form data?
    var content = `div`(
        h1(
          a(href="http://nim-lang.org", title="Hello", "Hello $1 $2" % [$request.params["first_name"], $request.params["last_name"]])
        ),
        h4("Form data"),
        p($request.params),
    )
    body.add(layout(content))
    status = Http200

runForever()

SQL for generating a report for each month of the year using PostgreSQL's crosstab

Tagged crosstab, pivot, postgresql, year  Languages sql

This is the report we want to generate:

┌──────────────────────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────┬─────┐
│           key            │  jan  │  feb  │  mar  │  apr  │  may  │  jun  │  jul  │  aug  │  sep  │  oct  │ nov │ dec │
├──────────────────────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────┼─────┤
│ Christian                │ 4209  │ 3627  │ 3686  │ 3109  │ 3605  │ 3506  │ 2892  │ 3380  │ 3262  │ 1821  │ ¤   │ ¤   │
│ Barney                   │ 17188 │ 17139 │ 16622 │ 14096 │ 17302 │ 17063 │ 13372 │ 16277 │ 16672 │ 9263  │ ¤   │ ¤   │
│ Donald                   │ 16078 │ 14627 │ 16518 │ 14241 │ 16397 │ 16655 │ 15739 │ 17639 │ 16178 │ 9588  │ ¤   │ ¤   │
│ Duck                     │ 9369  │ 9099  │ 10640 │ 9184  │ 10489 │ 10332 │ 9711  │ 11108 │ 10405 │ 6338  │ ¤   │ ¤   │
│ Jebus                    │ 17774 │ 16433 │ 18502 │ 15877 │ 17918 │ 17411 │ 15900 │ 18175 │ 17149 │ 10141 │ ¤   │ ¤   │
└──────────────────────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────┴─────┘

You need the crosstab function which can be found in the tablefunc extension:

CREATE EXTENSION tablefunc;

Now generate the report using the crosstab function:

SELECT * 
FROM CROSSTAB(
  'SELECT key, month, SUM(value) FROM people_statistics WHERE month >= ''2017-01-01'' GROUP BY key, month ORDER BY key',
  'SELECT (DATE ''2017-01-01'' + (INTERVAL ''1'' month * generate_series(0,11)))::date')
AS
  ct_result (key bigint, jan bigint, feb bigint, mar bigint, apr bigint, may bigint, jun bigint, jul bigint, aug bigint, sep bigint, oct bigint, nov bigint, dec bigint);

We used the crosstab function that accepts two SQL queries as arguments. The first argument generates the rows for the query:

  • Column 1 is the key or identifier for the data, e.g., person name (Christian)
  • Column 2 contains the categories that will be used to pivot the data, e.g., year and month (2017-01)
  • Column 3 is the value that will be displayed, e.g., number of people (12)

The second argument generates the categories which in this example are the months of the year.

Pattern matching order in Elixir

Tagged elixir, order, pattern matching  Languages elixir
defmodule Greeter do
  def hello(name) do
    "Hello #{name}"
  end
  def hello(:jane), do: "Hello Jane!!!!!"
end

Greeter.hello(:jane) # Prints "Hello Jane"
Greeter.hello(:janet) # Prints "Hello Janet"

defmodule Greeter do
  def hello(:jane), do: "Hello Jane!!!!!"
  def hello(name) do
    "Hello #{name}"
  end
end

Greeter.hello(:jane) # Prints "Hello Jane!!!!!"
Greeter.hello(:janet) # Prints "Hello Janet"

Ecto query using left join, group by, order by, and count

Tagged count, ecto, group_by, left_join, order_by  Languages elixir

This is an example of an Ecto query that uses a left join, group by, order by, and count to produce a count of associated records for a list:

query = from list in List,
  left_join: subscriber in assoc(list, :subscribers),
  group_by: list.id,
  order_by: [asc: :name],
  select_merge: %{ subscriber_count: count(subscriber.id) }
query |> Repo.all

Remember to add a virtual attribute named subscriber_count:

schema "lists" do
  ...
  field :subscriber_count, :integer, virtual: true

Tested with Ecto 2.2.

Copy-to-clipboard with plain Javascript

Tagged clipboard, copy, javascript  Languages javascript
var Copy2Clipboard = {
  init: function(selector) {
    var btns = document.querySelectorAll(selector);
    for (var i = 0, len = btns.length; i < len; i++) {
      var btn = btns[i]
      btn.addEventListener('click', function(event) {
        var btn = event.target
        try {
          console.debug("click")
          var textarea = document.getElementById(btn.getAttribute('data-target'))
          if (textarea == null) {
            alert("copy-to-clipboard target is undefined")
            return
          }
          textarea.select();
          var successful = document.execCommand && document.execCommand('copy')
          if (successful) {
            btn.innerHTML = 'Copied...'
          } else {
            alert("Press Ctrl+C or Cmd+C to copy")
          }
        } catch (err) {
          console.log('Oops, unable to copy')
        }
      })
    }
  }
}

Copy2Clipboard.init('.copy-to-clipboard')
textarea id="embed-code">
  This will be copied to the clipboard.
/textarea>

How to use nmap to find security vulnerabilities

Tagged nmap, security, vulnerability  Languages bash
$ brew install nmap
$ cd /usr/local/share/nmap/scripts
$ git clone git@github.com:scipag/vulscan.git
$ nmap -sV -A -oX nmap-report.xml --script=vulscan/vulscan.nse snippets.aktagon.com
$ xsltproc nmap-report.xml -o nmap-report.html
  • sV: Probe open ports to determine service/version info
  • A: Enable OS detection, version detection, script scanning, and traceroute

Also see: https://nmap.org/ https://github.com/scipag/vulscan http://www.openvas.org/ https://observatory.mozilla.org/

Analyze Nginx's access logs with goaccess

Tagged access, analytics, goaccess, log  Languages bash

Show all statistics

sudo zcat /var/log/nginx/*.access.log.* | goaccess --log-format=COMBINED

Show server errors

sudo zcat /var/log/nginx/*.access.log.* | awk '$9~/500/' | goaccess --log-format=COMBINED

How to test ActiveRecord associations in Rails

Tagged activerecord, rails  Languages ruby

spec_helper.rb

def assert_association(model, name, type, options)
  reflection = model.reflect_on_association(name)
  assert reflection, "#{model} has no association named #{name}"
  assert_equal type, reflection.macro
  assert_equal options.sort, reflection.options.sort
end
require 'spec_helper'

describe Order do
  it "has associations" do
    assert_association Order, :organization, :belongs_to, {}
    assert_association Order, :items, :has_many, class_name: Order::Item
  end
end

How to use the html/template package in Golang

Tagged golang, html, template, reload  Languages go, bash

Features:

  • template reloading
  • view helpers
  • HTML files are embedded in the binary
package main

import (
    rice "github.com/GeertJohan/go.rice"
    "gitlab.com/christianhellsten/go-utils/log"
    "html/template"
    "net/http"
    "os"
    "path/filepath"
    "strings"
)

type renderTemplateFunc func(w http.ResponseWriter, tmpl string, p interface{})

var renderTemplate renderTemplateFunc
var templates = template.New("").Funcs(templateMap)
var templateBox *rice.Box

func loadTemplates() {
    if config.debug {
        renderTemplate = renderTemplateDev
    } else {
        renderTemplate = renderTemplateProd
        newTemplate := func(path string, _ os.FileInfo, _ error) error {
            if path == "" {
                return nil
            }
            templateString, err := templateBox.String(path)
            if err != nil {
                log.Fatal("Unable to parse: path=%s, err=%s", path, err)
            }
            templates.New(filepath.Join("tmpl", path)).Parse(templateString)
            return nil
        }
        // Load and parse templates from binary or disk
        templateBox = rice.MustFindBox("tmpl")
        templateBox.Walk("", newTemplate)
    }
}

var (
    templateMap = template.FuncMap{
        "Upper": func(s string) string {
            return strings.ToUpper(s)
        },
    }
)

func renderTemplateProd(w http.ResponseWriter, tmpl string, p interface{}) {
    err := templates.ExecuteTemplate(w, tmpl, p)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func renderTemplateDev(w http.ResponseWriter, tmpl string, p interface{}) {
    t, _ := template.ParseFiles(tmpl)
    t.Execute(w, p)
}

Usage:

go get
go get github.com/GeertJohan/go.rice/rice
rice embed-go
go build

Reference: https://github.com/jmcfarlane/golang-templates-example