import { Dictionary } from "fastly:dictionary";
const backendName = "origin_0";

function handler(event) {
  // Get the request from the client.
  let req = event.request

  // Each entry in the dictionary has the base64-encoded value of username:password as its key.
  // To generate a key from username:password pairs, on a bash shell you should be able to do:
  // echo -n "alice:secretpassword" | base64
  const dict = new Dictionary("username_password");
  const credential = getCredential(req.headers.get("Authorization"));

  if(keyExists(dict, credential)) {
    // Decode the credential and extract the username.
    const username = getUserName(credential);
    if(username) {
      req.headers.delete("Authorization");
      req.headers.set("Authorized-User", username);
      console.log(`Access granted for user ${username}`);
      return fetch(req, {
        backend: backendName,
      });
    }
  }

  console.log("Access denied");
  // Catch all other requests and return a 401.
  const body = `
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
    <head>
        <title>Error</title>
        <meta HTTP-EQUIV='Content-Type' CONTENT='text/html;'>
    </head>
    <body><h1>401 Unauthorized (Fastly)</h1></body>
</html>`;
  
  const headers = new Headers({
    "Content-Type": "text/html; charset=UTF-8",
    "WWW-Authenticate": "Basic realm=MYREALM",
  });
   
  return new Response(body, {
    status: 401,
    headers,
  });
}

function keyExists(dict, key) {
  try { dict.get(key); return true; } catch (e) { return false; }
}

function getCredential(input) {
  let re = /Basic (?<credential>.+)/;
  return re.test(input) ? re.exec(input).groups.credential : "";
}

function getUserName(input) {
  let decodedInput = atob(input);
  const re = /^(?<username>.+?):.*$/;
  const m = decodedInput.match(re);
  return m ? m.groups.username : "";
}

addEventListener("fetch", event => event.respondWith(handler(event)));