- Open dev tools
- Search for the
<video…
tag. - Copy the source URL
- Right click on the
body
tag and clickEdit as HTML
- Add an a link with the src right inside the body tag like:
<body>
<a href="url-you-copied">download</a>
...
<video…
tag.body
tag and click Edit as HTML
<body>
<a href="url-you-copied">download</a>
...
From April 10 to May 2, 2024, I did all the work myself to get SOC 2 Type II certified. I'm now half way through the observation period to get Type II. The observation period is easy, you just have to babysit the controls. Getting to Type I is much harder. It took me somewhere around 100 hours.
SOC 2 is a security framework that, for many customers, eliminates the need to have you, as a vendor, fill out a lengthy security questionnaire. The SOC 2 controls and audits ask pretty much all the questions you'd get from a customer's security team. In fact, that is a great way to think about SOC 2. It's essentially a very thorough questionnaire you fill out once, an independent auditor forms an opinion of it in a report, and you share with all your customers.
There are two parts to SOC 2. The initial audit, where an auditor writes a Type I report sharing their opinion of your current setup. Then there's a 3 month observ
I will often run this command to make sure all my docker containers are stopped and removed before running docker-compose up. Sometimes when you restart your system, old containers will start back up automatically in the background.
docker stop $(docker ps -aq) && docker rm $(docker ps -aq)
<video id="player" autoplay muted playsinline> </video> | |
<button id="capture">Capture</button> | |
<canvas id="canvas" width=320 height=240></canvas> | |
<script> | |
const player = document.getElementById('player'); | |
const canvas = document.getElementById('canvas'); | |
const context = canvas.getContext('2d'); | |
const captureButton = document.getElementById('capture'); | |
const constraints = { |
Here's an ecto changeset validation for urls:
@doc """
validates field is a valid url
## Examples
iex> Ecto.Changeset.cast(%ZB.Account{}, %{"website" => "https://www.zipbooks.com"}, [:website])
...> |> Utils.Changeset.validate_url(:website)
...> |> Map.get(:valid?)
import UIKit | |
// All you do is assign this class to a segue in your storyboard and you're done | |
class BottomCardSegue: UIStoryboardSegue { | |
private var selfRetainer: BottomCardSegue? = nil | |
override func perform() { | |
destination.transitioningDelegate = self |
import parseCsv from 'zipbooks/utils/parse-csv' | |
import { module, test } from 'qunit' | |
module('Unit | Utility | parse-csv', function(_hooks) { | |
test('parses csv successfully', function(assert) { | |
let result = parseCsv('name,age\nadam,31\ntim,32\n"St, clair",26') | |
assert.equal(JSON.stringify(result), '[["name","age"],["adam","31"],["tim","32"],["St, clair","26"]]') | |
}) |
I have this abstraction in my application code called a "CloudFile". This is where I store in the database information about
files on S3 and it gives me a resource for other resources to own. For example, a user would have an avatar_cloud_file_id
.
On the front-end, I would load this relationship and display the avatar with user.avatar_cloud_file.download_url
defmodule RL.CloudFile do
use Ecto.Schema
import Ecto.Changeset
@timestamps_opts type: :utc_datetime_usec
defmodule Hungarian do | |
@moduledoc """ | |
Written by Adam Kirk – Jan 18, 2020 | |
Most helpful resources used: | |
https://www.youtube.com/watch?v=dQDZNHwuuOY | |
https://www.youtube.com/watch?v=cQ5MsiGaDY8 | |
https://www.geeksforgeeks.org/hungarian-algorithm-assignment-problem-set-1-introduction/ |
INSERT INTO "public"."gis__objects"("id","layer","geometry","properties","inserted_at") | |
VALUES | |
(E'udotreg1',E'udot_regions',E'SRID=4326;POLYGON((-113.47488600498771 41.9933094053436,-113.47701796048186 41.993290592340216,-113.47965799142257 41.993267513722095,-113.48183048968212 41.993248275413805,-113.48442960325997 41.9932255219256,-113.48659558154715 41.993206333678295,-113.48914726497632 41.99318405086824,-113.49136078839656 41.99316446201844,-113.492336364185 41.993155700446096,-113.49386453053565 41.99313573035917,-113.49620402201325 41.99310529484248,-113.49858127956367 41.99307443869104,-113.50104721969728 41.99304241079656,-113.50292987922532 41.993017833210615,-113.50597269767145 41.99297851586337,-113.50791966759073 41.99295317178795,-113.51089816756081 41.99291467895187,-113.51203139408835 41.99289968747675,-113.51290988984236 41.99289062542413,-113.51576741908306 41.99286132012711,-113.51790018395923 41.9928393870467,-113.5206364298568 41.99281127081749,-113.52289058677229 41.992788109236464,-113 |