package sihl
The modular functional web framework
Install
Dune Dependency
Authors
Maintainers
Sources
sihl-queue-0.1.9.tbz
sha256=77f0813d75a88edd14b3396e8b848d94c31c28803299b4b1bd4b78b1de4a2e80
sha512=a8907bc35ea14b7c3a7d638979a2a274860202b2de58b84b5621a4908db001ace493d8aa2e5383f4c8b1847efd256938592f63ef75a41521284b3640d3a7442a
doc/src/sihl.utils/sihl_utils.ml.html
Source file sihl_utils.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
module Core = Sihl_core module Time = struct type duration = | OneSecond | OneMinute | TenMinutes | OneHour | OneDay | OneWeek | OneMonth | OneYear [@@deriving yojson, show, eq] let duration_to_span duration = let duration_s = match duration with | OneSecond -> 1. | OneMinute -> 60. | TenMinutes -> 60. *. 10. | OneHour -> 60. *. 60. | OneDay -> 60. *. 60. *. 24. | OneWeek -> 60. *. 60. *. 24. *. 7. | OneMonth -> 60. *. 60. *. 24. *. 30. | OneYear -> 60. *. 60. *. 24. *. 365. in Option.get (Ptime.of_float_s duration_s) |> Ptime.to_span ;; let ptime_to_yojson ptime = `String (Ptime.to_rfc3339 ptime) let ptime_of_yojson yojson = match yojson |> Yojson.Safe.to_string |> Ptime.of_rfc3339 |> Ptime.rfc3339_error_to_msg with | Ok (ptime, _, _) -> Ok ptime | Error (`Msg msg) -> Error msg ;; let ptime_of_date_string date = let date = date |> String.split_on_char '-' |> List.map int_of_string_opt |> List.map (Option.to_result ~none: "Invalid date string provided, make sure that year, month and date are \ ints") |> List.fold_left (fun result item -> match item with | Ok item -> Result.map (List.cons item) result | Error msg -> Error msg) (Ok []) |> Result.map List.rev in match date with | Ok [ year; month; day ] -> Ptime.of_date (year, month, day) |> Option.to_result ~none:"Invalid date provided, only format 1990-12-01 is accepted" | Ok _ -> Error "Invalid date provided, only format 1990-12-01 is accepted" | Error msg -> Error msg ;; let ptime_to_date_string ptime = let year, month, day = Ptime.to_date ptime in let month = if month < 10 then Printf.sprintf "0%d" month else Printf.sprintf "%d" month in let day = if day < 10 then Printf.sprintf "0%d" day else Printf.sprintf "%d" day in Printf.sprintf "%d-%s-%s" year month day ;; end module Jwt = struct type algorithm = Jwto.algorithm = | HS256 | HS512 | Unknown type t = Jwto.t type payload = (string * string) list let empty = [] let add_claim ~key ~value payload = Base.List.cons (key, value) payload let set_expires_in ~now duration payload = let span = Time.duration_to_span duration in let epoch_s = Ptime.add_span now span |> Option.map Ptime.to_float_s |> Option.map Float.to_string in match epoch_s with | Some epoch_s -> add_claim ~key:"exp" ~value:epoch_s payload | None -> payload ;; let encode algorithm ~secret payload = Jwto.encode algorithm secret payload let decode ~secret token = Jwto.decode_and_verify secret token let get_claim ~key token = token |> Jwto.get_payload |> Jwto.get_claim key let is_expired ~now ?(claim = "exp") token = let is_ealier = let ( let* ) = Option.bind in let* claim = get_claim ~key:claim token in let* exp = Float.of_string_opt claim in let* exp = Ptime.of_float_s exp in Option.some (Ptime.is_earlier exp ~than:now) in Option.value is_ealier ~default:false ;; let pp = Jwto.pp let eq = Jwto.eq module Jwto = Jwto end module Json = struct type t = Yojson.Safe.t let parse str = try Ok (str |> Yojson.Safe.from_string) with | _ -> Error "failed to parse json" ;; let parse_opt str = try Some (str |> Yojson.Safe.from_string) with | _ -> None ;; let parse_exn str = str |> Yojson.Safe.from_string let to_string = Yojson.Safe.to_string module Yojson = Yojson.Safe end module Regex = struct type t = Re.Pcre.regexp let of_string string = Re.Pcre.regexp string let test regexp string = Re.Pcre.pmatch ~rex:regexp string let extract_last regexp text = let ( let* ) = Option.bind in let extracts = Array.to_list (Re.Pcre.extract ~rex:regexp text) in let* extracts = try Some (List.tl extracts) with | _ -> None in try Some (List.hd extracts) with | _ -> None ;; module Re = Re end module Hashing = struct let hash ?count plain = match count, Core.Configuration.is_testing () with | _, true -> Ok (Bcrypt.hash ~count:4 plain |> Bcrypt.string_of_hash) | Some count, false -> if count < 4 || count > 31 then Error "Password hashing count has to be between 4 and 31" else Ok (Bcrypt.hash ~count plain |> Bcrypt.string_of_hash) | None, false -> Ok (Bcrypt.hash ~count:10 plain |> Bcrypt.string_of_hash) ;; let matches ~hash ~plain = Bcrypt.verify plain (Bcrypt.hash_of_string hash) module Bcrypt = Bcrypt end module String = struct let strip_chars s cs = let len = Caml.String.length s in let res = Bytes.create len in let rec aux i j = if i >= len then Bytes.to_string (Bytes.sub res 0 j) else if Caml.String.contains cs s.[i] then aux (succ i) j else ( Bytes.set res j s.[i]; aux (succ i) (succ j)) in aux 0 0 ;; end module Encryption = struct let xor c1 c2 = try Some (List.map2 (fun chr1 chr2 -> Char.chr (Char.code chr1 lxor Char.code chr2)) c1 c2) with | exn -> Logs.err (fun m -> m "XOR: Failed to XOR %s and %s. %s" (c1 |> List.to_seq |> Caml.String.of_seq) (c2 |> List.to_seq |> Caml.String.of_seq) (Printexc.to_string exn)); None ;; let decrypt_with_salt ~salted_cipher ~salt_length = if List.length salted_cipher - salt_length != salt_length then ( Logs.err (fun m -> m "ENCRYPT: Failed to decrypt cipher %s. Salt length does not match cipher \ length." (salted_cipher |> List.to_seq |> Caml.String.of_seq)); None) else ( try let salt = CCList.take salt_length salted_cipher in let encrypted_value = CCList.drop salt_length salted_cipher in xor salt encrypted_value with | exn -> Logs.err (fun m -> m "ENCRYPT: Failed to decrypt cipher %s. %s" (salted_cipher |> List.to_seq |> Caml.String.of_seq) (Printexc.to_string exn)); None) ;; end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>