Skip to content

Instantly share code, notes, and snippets.

View oscarduignan's full-sized avatar
🐢
Catching up

Oscar Duignan oscarduignan

🐢
Catching up
View GitHub Profile
@oscarduignan
oscarduignan / Example.scala
Created September 22, 2025 12:45
Example of the stuff I was saying about "explicitly"? mapping rather than using functional combinators
//> using scala 2.13
//> using dep org.playframework::play-json:3.0.5
//> using dep com.lihaoyi::pprint:0.9.3
import play.api.libs.json._
sealed trait Content
case object Empty extends Content
case class Text(value: String) extends Content
case class HtmlContent(value: String) extends Content
@oscarduignan
oscarduignan / SearchGitHubForCompromisedPackages.scala
Created September 18, 2025 14:13
We are seeing more supply chain attacks where a large number of packages are compromised at once, given a long list of packages, we want to quickly check for vulnerable projects in hmrc that are using the compromised dependency, this script reduces and packs the package names into a list of urls for github searches
//> using scala 3
//> using toolkit latest
import sttp.client4.*
import scala.annotation.tailrec
@main def main(): Unit = {
val compromisedPackages =
"""
|@ahmedhfarag/ngx-perfect-scrollbar 20.0.20
@oscarduignan
oscarduignan / analytics.js
Created January 15, 2025 00:41
Logging events to server from javascript
const { timeOrigin } = window.performance
const unsentEvents = []
console.log("Analytics loaded") // shows that it is only run once, even though imported into multiple scripts
document.addEventListener("visibilitychange", function sendAnalytics() {
if (document.visibilityState === "hidden") {
const events = unsentEvents.splice(0)
@oscarduignan
oscarduignan / Metrics.scala
Last active November 25, 2024 10:39
What-if'ing what something that gathered info about a collection of repos locally could look like for generating adhoc reports on some metrics
//> using scala 3.3
//> using toolkit typelevel:0.1.29
//> using dep com.softwaremill.macwire::macros:2.6.4
//> using dep org.scalameta:scalameta_2.13:4.7.7
//> using dep com.lihaoyi::pprint:0.9.0
import com.softwaremill.macwire.*
import cats.effect.*
import cats.syntax.all.*
@oscarduignan
oscarduignan / FindUsages.scala
Last active November 25, 2024 10:40
Find usages of play-frontend-hmrc components in twirl templates, doesn't handle all cases- just a proof of concept approach
//> using scala 2.13
//> using dep "org.scalameta::scalameta:4.7.7"
//> using dep "com.lihaoyi::pprint:0.9.0"
//> using dep "org.eclipse.jgit:org.eclipse.jgit:6.10.0.202406032230-r"
//> using dep "org.eclipse.jgit:org.eclipse.jgit.ssh.apache.agent:6.10.0.202406032230-r"
//> using toolkit 0.5.0
import java.nio.file._
import scala.meta.internal.semanticdb.{Locator, MethodSignature, SymbolInformation, TypeRef, ValueSignature}
import scala.io.Source
@oscarduignan
oscarduignan / _autocomplete.js
Last active August 21, 2024 14:39 — forked from adamliptrot-oc/_autocomplete.js
Loads and polyfills the autocomplete
// Note - updated to work with the HMRC Frontend implementation
// https://github.com/hmrc/play-frontend-hmrc#adding-accessible-autocomplete-css-and-javascript
if (typeof HMRCAccessibleAutocomplete != 'undefined' && document.querySelector('[data-module="hmrc-accessible-autocomplete"]') != null) {
document.querySelectorAll('[data-module="hmrc-accessible-autocomplete"]').forEach(function (originalSelect) {
// load autocomplete - now handled by the HMRC component wrapper in Twirl
// accessibleAutocomplete.enhanceSelectElement({
// selectElement: originalSelect,
// showAllValues: true
@oscarduignan
oscarduignan / GlobalZapProxy.scala
Last active August 21, 2024 20:34
Embed / use Zap as a resource within a scala application
package uk.gov.hmrc.zap
import uk.gov.hmrc.zap.ZapRelease.ZapVersion
import java.io.File
import java.net.URI
import scala.sys.process._
import scala.concurrent.duration._
import cats.effect.{IO, Resource}
@oscarduignan
oscarduignan / GetZap.scala
Created August 9, 2024 10:08
proof of concept build a java assembly (fat jar) that contains a release of zap and can run it with the config we want
//> using dep com.lihaoyi::requests:0.9.0
//> using toolkit 0.5.0
//> using file RunZap.scala
//> using mainClass getZap
@main def getZap =
os.write.over(
os.pwd / "resources" / s"ZAP_${zapVersion}_Core.zip",
requests.get.stream(s"https://github.com/zaproxy/zaproxy/releases/download/v$zapVersion/ZAP_${zapVersion}_Core.zip"),
createFolders = true
@oscarduignan
oscarduignan / records.sc
Last active July 22, 2024 12:08
Thinking about ways to model records in scala that can give compile time errors where required fields are missing
//> using scala 3
trait Key { type Value; trait Provided }
case class Person[+T] private(underlying: Map[Key, Any]):
def apply(k: Key): Option[k.Value] =
underlying.get(k).map(_.asInstanceOf[k.Value])
def set(k: Key, v: k.Value): Person[T & k.Provided] =
Person[T & k.Provided](underlying + (k -> v))
@oscarduignan
oscarduignan / Caddyfile
Last active July 3, 2024 09:47
Example showing how default platform CSP is incompatible with some ways of loading scripts
http://127.0.0.1 {
vars {
platformCSP "script-src 'nonce-abc123' 'unsafe-inline' 'strict-dynamic' https: http: ; object-src 'none'; base-uri 'none';"
}
route / {
header Content-Type text/html
header Content-Security-Policy {vars.platformCSP}
respond <<HTML
<html>