defmodule Acme.Repo do | |
use Ecto.Repo, | |
otp_app: :acme, | |
adapter: Ecto.Adapters.Postgres | |
def with_prefix(prefix) do | |
module_atom = Module.concat([Acme, Repo, WithPrefix, Macro.camelize(prefix)]) | |
# We could not find a better way to see if this module already existed | |
if !Kernel.function_exported?(module_atom, :prefix, 0) do |
“Don’t move to that London” warned my northern grandfather once. “It’s full of spivs”.
The Oxford Dictionary (somewhat chauvinistically) defines a spiv as:
A man, typically a flashy dresser, who makes a living by disreputable dealings
“But I work in IT” I told him. “engineers aren’t like that”.
TLDR: JWTs should not be used for keeping your user logged in. They are not designed for this purpose, they are not secure, and there is a much better tool which is designed for it: regular cookie sessions.
If you've got a bit of time to watch a presentation on it, I highly recommend this talk: https://www.youtube.com/watch?v=pYeekwv3vC4 (Note that other topics are largely skimmed over, such as CSRF protection. You should learn about other topics from other sources. Also note that "valid" usecases for JWTs at the end of the video can also be easily handled by other, better, and more secure tools. Specifically, PASETO.)
A related topic: Don't use localStorage (or sessionStorage) for authentication credentials, including JWT tokens: https://www.rdegges.com/2018/please-stop-using-local-storage/
The reason to avoid JWTs comes down to a couple different points:
- The JWT specification is specifically designed only for very short-live tokens (~5 minute or less). Sessions
“Don’t move to that London” warned my northern grandfather once. “It’s full of spivs”.
The Oxford Dictionary (somewhat chauvinistically) defines a spiv as:
A man, typically a flashy dresser, who makes a living by disreputable dealings
“But I work in IT” I told him. “engineers aren’t like that”.
defmodule YourAppName.Search do | |
# ... | |
@doc """ | |
Queries listings. | |
""" | |
def query_listings(query, current_user) do | |
default_scope = from l in Listing, where: l.draft == false or l.user_id == ^current_user.id, order_by: [desc: l.updated_at], limit: 50 | |
id = _try_integer(query) |
namespace :nvm do | |
desc "Load nvm and the node environment variables" | |
def file_or_symlink_exists?(path_to_file) | |
File.exist?(path_to_file) || File.symlink?(path_to_file) | |
end | |
desc "Load node if nvm is already installed but not on the path" | |
task :load_node do | |
sh "/bin/bash -c '. ~/.nvm/nvm.sh'" |
By: @BTroncone
Also check out my lesson @ngrx/store in 10 minutes on egghead.io!
Update: Non-middleware examples have been updated to ngrx/store v2. More coming soon!
Table of Contents
val n = 9 | |
val s = Math.sqrt(n).toInt | |
type Board = IndexedSeq[IndexedSeq[Int]] | |
def solve(board: Board, cell: Int = 0): Option[Board] = (cell%n, cell/n) match { | |
case (r, `n`) => Some(board) | |
case (r, c) if board(r)(c) > 0 => solve(board, cell + 1) | |
case (r, c) => | |
def guess(x: Int) = solve(board.updated(r, board(r).updated(c, x)), cell + 1) | |
val used = board.indices.flatMap(i => Seq(board(r)(i), board(i)(c), board(s*(r/s) + i/s)(s*(c/s) + i%s))) |