UNPKG

@privacyportal.org/privacy-kit

Version:

Lightweight and FOSS browser library bringing Privacy Portal features to your website users

6 lines (5 loc) 13.2 kB
/* MIT License - Copyright (c) 2025 Privacy Portal. See full license at https://github.com/privacyportal/privacy-kit/LICENSE. */ "use strict";var W=Object.defineProperty;var K=(e,t,n)=>t in e?W(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var g=(e,t,n)=>K(e,typeof t!="symbol"?t+"":t,n);const G={VITE_AUTHORIZATION_URL:"https://app.privacyportal.org/oauth/authorize",VITE_TOKEN_URL:"https://api.privacyportal.org/oauth/token"},{VITE_AUTHORIZATION_URL:w,VITE_TOKEN_URL:J}=G,L={SCOPE:["openid","email"],RESPONSE_TYPE:"code",RESPONSE_MODE:"web_message"},Y="Please try again later.";class l extends Error{constructor({message:t}){super(t)}}function h(e){if(e instanceof l)switch(d.onError){case"ignore":break;case"alert":{alert(e.message);break}default:X(d.onError)&&d.onError.error(e.message)}}function X(e){return e!=null&&typeof e=="object"&&typeof e.error=="function"}class Q{constructor(){g(this,"_client_id");g(this,"_name_scope_required");g(this,"_onError")}get client_id(){return this._client_id}set client_id(t){this._client_id=t}get onError(){return this._onError}set onError(t){this._onError=t}get name_scope_required(){return this._name_scope_required||!1}set name_scope_required(t){this._name_scope_required=t}get redirect_uri(){return window.location.origin}get authorization_origin(){return new URL(w).origin}get authorization_url_placeholder(){return`${w}?loading`}getNameScopeRequired(t){return(t==null?void 0:t.name_scope_required)!==void 0?t==null?void 0:t.name_scope_required:this.name_scope_required}getScope(t){return[...L.SCOPE,...this.getNameScopeRequired(t)?["name"]:[]].join(" ")}createAuthorizationURL(t,n,i){if(!this.client_id)throw new l({message:"OAuth client_id not configured."});const r=new URLSearchParams;r.set("client_id",this.client_id),r.set("scope",this.getScope(i)),r.set("response_type",L.RESPONSE_TYPE),r.set("response_mode",L.RESPONSE_MODE),r.set("nonce",crypto.randomUUID().substring(4,18)),r.set("redirect_uri",this.redirect_uri),r.set("state",t),r.set("code_challenge",n),r.set("code_challenge_method","S256");const o=new URL(w);return o.search=r.toString(),o.toString()}}const d=new Q;function E(e,t){return n=>i=>{var o;const r=t!=null&&t.shadow?(o=i==null?void 0:i.composedPath())==null?void 0:o[0]:i==null?void 0:i.target;if(r)return r[t!=null&&t.closest?"closest":"matches"](e)&&n(r)}}function A(e,t){return e&&t?(e.value=t,e.dispatchEvent(new Event("paste",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),!0):!1}function S(e){return e.offsetWidth!==0||e.offsetHeight!==0}function R(e){return e.map(t=>`${t}:not(:disabled)`).join(", ")}function I(e,t){e.addEventListener("focusin",()=>{t.style.opacity="1"}),e.addEventListener("focusout",()=>{t.style.opacity="0"}),document.addEventListener("click",()=>{t.style.opacity=document.activeElement===e?"1":"0"},!0)}async function U(e){let t=e.parentElement,n;for(;t;){try{n=t.shadowRoot||t.attachShadow({mode:"open"});const i=document.createElement("style");i.textContent=":host{position:relative;display:block;box-sizing:border-box;margin:0;padding:0;}";const r=document.createElement("slot");n.append(i,r)}catch{}if(n)return{ancestor:t,shadowRoot:n};t=t.parentElement}throw new Error("Failed to attach HME DOM.")}function x(e,t,n){let i=0;const r=()=>{cancelAnimationFrame(i),i=requestAnimationFrame(n)},o=new ResizeObserver(r);o.observe(e),o.observe(t);const c=new FinalizationRegistry(s=>{s.unobserve(e),s.unobserve(t),s.disconnect()}),a=new WeakRef(e);c.register(a,o)}function f(e,t){return(t!=null&&t.toFixed?e.toFixed(t.toFixed):e)+"px"}function m(e){const t=window.open(d.authorization_url_placeholder,"PrivacyPortalSSO","top=0");t?e(t):h(new l({message:"Please allow popups in order to use Hide-my-Email."}))}function ee(e){const t=e.split(".",3)[1];return{...JSON.parse(atob(t))}}function te(e){const t=e instanceof Uint8Array?e:new Uint8Array(e);return btoa(String.fromCharCode(...t))}function j(e){return ne(te(e))}function ne(e){return e.replace(/\//g,"_").replace(/\+/g,"-").replace(/=+$/,"")}function P(e){return typeof e=="string"||e instanceof String}const q=["Authentication failed.",Y].join(" ");function ie(e=16){const t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,n=>n.toString(16).padStart(2,"0")).join("")}function re(e=32){const t=new Uint8Array(e);return crypto.getRandomValues(t),j(t)}async function oe(e){const n=new TextEncoder().encode(e),i=await crypto.subtle.digest("SHA-256",n);return j(i)}async function ae(e,t){try{if(!e)throw new l({message:"code missing."});if(!d.client_id)throw new l({message:"OAuth client_id not configured"});const n=new URLSearchParams;return n.set("client_id",d.client_id),n.set("grant_type","authorization_code"),n.set("code",e),n.set("redirect_uri",d.redirect_uri),n.set("code_verifier",t),(await fetch(J,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n})).json()}catch(n){throw n instanceof l?n:new l({message:q})}}async function ce({id_token:e,access_token:t}){if(!e||!t||!P(e)||!P(t))throw new l({message:q});return{id_token:e,access_token:t}}async function se(e,t){try{const n=ie(),i=re(),r=await oe(i);e.location.href=d.createAuthorizationURL(n,r,t);let o,c;return await Promise.race([new Promise((a,s)=>{window.addEventListener("message",async _=>{if(_.origin!==d.authorization_origin)return{};clearTimeout(o),clearInterval(c);const{code:V,state:Z}=_.data;if(n!==Z)return s(new l({message:"Authentication failed."}));const{id_token:O,access_token:T}=await ae(V,i).catch(s);await ce({id_token:O,access_token:T}).catch(s),a({id_token:O,access_token:T})},!1)}),new Promise(a=>{c=setInterval(()=>{e.closed&&(clearTimeout(o),clearInterval(c),a(void 0))},1e3)}),new Promise((a,s)=>{o=setTimeout(()=>{clearInterval(c),s(new l({message:"Authorization timed out."}))},18e4)})])}catch(n){h(n)}}async function z(e,t){const n=await se(e,t);if(n!=null&&n.id_token){const{email:i,name:r}=ee(n.id_token);return{email:i,name:r}}return{}}function de(e,t,n){const i=document.createElementNS("http://www.w3.org/2000/svg","svg");e!=null&&e.width&&i.setAttribute("width",e.width),e!=null&&e.height&&i.setAttribute("height",e.height),e!=null&&e.viewBox&&i.setAttribute("viewBox",e.viewBox),n!=null&&n.fillRule&&(i.style.fillRule=n.fillRule),n!=null&&n.clipRule&&(i.style.clipRule=n.clipRule),n!=null&&n.strokeLinejoin&&(i.style.strokeLinejoin=n.strokeLinejoin),n!=null&&n.strokeMiterlimit&&(i.style.strokeMiterlimit=n.strokeMiterlimit);for(const r of t)i.appendChild(r);return i}function N(e,t){const n=document.createElementNS("http://www.w3.org/2000/svg","path");return n.setAttribute("d",e),t!=null&&t.fill&&(n.style.fill=t.fill),n}function le(){return de({width:"100%",height:"100%",viewBox:"0 0 150 150"},[N("M150,22.5C150,10.082 139.918,0 127.5,0L22.5,0C10.082,0 0,10.082 0,22.5L0,127.5C0,139.918 10.082,150 22.5,150L127.5,150C139.918,150 150,139.918 150,127.5L150,22.5Z",{fill:"#333"}),N("M112.979,124.728C120.977,123.051 126.993,115.921 126.993,107.39C126.993,102.517 125.03,98.101 121.857,94.897L126.44,90.314L126.45,90.324C130.816,94.695 133.518,100.73 133.518,107.39C133.518,119.687 124.308,129.85 112.414,131.351L114.651,133.588L110.239,138L100.561,128.322L110.239,118.644L114.651,123.056L112.979,124.728ZM106.337,83.425L104.103,81.191L108.515,76.779L118.192,86.457L108.515,96.135L104.103,91.723L105.781,90.045C97.768,91.71 91.737,98.848 91.737,107.39C91.737,112.261 93.698,116.675 96.87,119.879L96.873,119.882L92.391,124.363L92.293,124.469L92.29,124.465C87.918,120.093 85.212,114.055 85.212,107.39C85.212,95.085 94.434,84.916 106.337,83.425ZM78.539,116.812L30.658,116.812C22.834,116.812 16.482,110.46 16.482,102.636L16.482,36.484C16.482,28.661 22.834,22.309 30.658,22.309L117.06,22.309C124.884,22.309 131.236,28.661 131.236,36.484L131.236,82.065C128.437,79.412 125.165,77.253 121.561,75.728L121.561,36.128C121.561,36.128 86.535,62.757 76.366,70.488C74.751,71.716 72.513,71.711 70.903,70.475C60.81,62.728 26.158,36.128 26.158,36.128L26.158,107.005L76.571,107.005C76.719,110.44 77.402,113.736 78.539,116.812ZM109.365,86.454L109.365,86.461L109.369,86.457L109.365,86.454ZM73.627,59.885L111.21,31.984L36.508,31.984L73.627,59.885Z",{fill:"#fff"})],{fillRule:"evenodd",clipRule:"evenodd",strokeLinejoin:"round",strokeMiterlimit:"2"})}const H="firefox",ue="android",fe="safari",he="chrome",_e="chromium",ge="criOS";function C(e,t){const n=e.userAgent.toLowerCase();for(const i of t)if(n.indexOf(i)===-1)return!1;return!0}function ye(e,t){const n=e.userAgent.toLowerCase();for(const i of t)if(n.indexOf(i)>-1)return!0;return!1}function me(e){return C(e,[H,ue])}function we(e){return C(e,[H])}function Le(e){return C(e,[fe])&&!ye(e,[he,_e,ge])}let F;const M="*****@pportal.io",y="Hide my Email",u="input[type=text]",$=["input[type=email]",`${u}[id*="email" i]`,`${u}[name*="email" i]`,`${u}[name*="username" i]`,`${u}[name*="login" i]`,`${u}[placeholder*="email" i]`,`${u}[placeholder*="e-mail" i]`],p=$.map(e=>`${e}:not([data-pp])`).join(", "),be=E(p),Ae=E(p,{shadow:!0});async function b(e,t){e.value="",F=e;const{email:n}=await z(t);A(F,n)}async function v(e){const t=`pp-${window.crypto.randomUUID().substring(0,8)}`;if(me(navigator)||Le(navigator)){const{ancestor:n,shadowRoot:i}=await U(e),r=document.createElement("li");r.innerText=y,r.style.padding="3px",r.style.cursor="pointer";const o=document.createElement("ul");o.id=t,o.style.display="block",o.style.position="absolute",o.style.maxHeight="300px",o.style.overflowY="auto",o.style.listStyle="none",o.style.backgroundColor="Canvas",o.style.color="CanvasText",o.style.colorScheme="light dark",o.style.boxShadow="0 2px 2px #999",o.style.fontSize="small",o.style.zIndex="1000",o.style.opacity="0",o.style.padding=o.style.margin="0px",o.appendChild(r);const c=document.createElement("style");c.textContent="li:hover{background-color:ButtonFace;color:ButtonText;}",i.append(c,o),x(e,n,()=>{const a=e.getBoundingClientRect(),s=n.getBoundingClientRect();o.style.width=f(a.width),o.style.top=f(a.bottom-s.top,{toFixed:2}),o.style.left=f(a.left-s.left,{toFixed:2})}),e.setAttribute("data-pp",""),r.onmousedown=a=>{a.preventDefault()},r.onclick=()=>{m(a=>{o.style.opacity="0",b(e,a).catch(h)})},I(e,o)}else{const n=document.createElement("option");n.setAttribute("id","new-privacy-addr"),n.setAttribute("value",M),n.textContent=y;let i;if(e.hasAttribute("list")){const r=e.getAttribute("list");r&&(i=document.getElementById(r))}if(i||(i=document.createElement("datalist"),i.setAttribute("id",t),e.setAttribute("list",t),e.insertAdjacentElement("afterend",i)),i.appendChild(n),e.setAttribute("data-pp",""),we(navigator)){const{ancestor:r,shadowRoot:o}=await U(e),c=document.createElement("button");c.title=y,c.ariaLabel=y,Object.assign(c.style,{position:"absolute",border:"none",borderRadius:"15px",cursor:"pointer",padding:"0",margin:"0",zIndex:"1000",pointerEvents:"auto",right:"8px",opacity:"0"}),c.appendChild(le()),o.append(c),x(e,r,()=>{const a=e.getBoundingClientRect(),s=r.getBoundingClientRect(),_=parseFloat(window.getComputedStyle(e).getPropertyValue("padding-right"))||0;c.style.height=c.style.width=f(a.height*.7,{toFixed:2}),c.style.top=f(a.top-s.top+a.height*.15,{toFixed:2}),c.style.right=f(s.right-a.right+Math.max(_,a.height*.15),{toFixed:2})}),c.onmousedown=a=>{a.preventDefault()},c.onclick=()=>{m(a=>{c.disabled=!0,b(e,a).catch(h).finally(()=>{c.disabled=!1})})},I(e,c)}}e.addEventListener("input",()=>{(e.value==="@"||e.value===M)&&m(n=>{b(e,n).catch(h)})})}function D(){for(const e of Array.from(document.querySelectorAll(p)))S(e)&&v(e).catch(console.error)}function Se(e){e!=null&&e.addEventListener&&e.addEventListener("focusin",be(t=>{v(t).catch(console.error)}),!0)}function k(){document.addEventListener("click",Ae(e=>{v(e).catch(console.error)}),!0)}function B(){[...Array.from(document.querySelectorAll("iframe"))].map(e=>{var t;try{const n=(e==null?void 0:e.contentDocument)||((t=e==null?void 0:e.contentWindow)==null?void 0:t.document);n!=null&&n.addEventListener&&Se(n)}catch{}})}function Ee(){window.addEventListener("load",()=>{D(),k(),B()}),document.readyState==="complete"&&(D(),k(),B())}const Re=["form button[data-pp-action=subscribe-anonymously]"],Ce=R(Re),pe=R($),ve=R([`${u}[id*="name" i]`,`${u}[name*="name" i]`]),Oe=E(Ce,{closest:!0});async function Te(e,t){try{const n=e.closest("form");if(!n)return;const i=[...Array.from(n.querySelectorAll(pe))].find(S);if(!i)return;const r=[...Array.from(n.querySelectorAll(ve))].find(S);let o;r!=null&&r.required&&(o={name_scope_required:!0});const{email:c,name:a}=await z(t,o);A(i,c)&&(!r||!a||A(r,a))&&n.dispatchEvent(new Event("submit",{cancelable:!0}))&&n.submit()}catch(n){h(n)}}function Ie(e){e!=null&&e.addEventListener&&e.addEventListener("click",Oe(t=>{m(n=>{Te(t,n)})}),!0)}function Ue(){window.addEventListener("load",()=>{Ie(document)})}function xe(e){return typeof e=="object"&&e!==null}const Pe={hide_my_email:!0,subscribe_anonymously:!0,on_error:"alert"};class Ne{static run(t){const{client_id:n,hide_my_email:i,subscribe_anonymously:r,on_error:o}={...Pe,...t};d.client_id=n,d.onError=o,i&&Ee(),r&&(xe(r)&&(d.name_scope_required=r.set_name_field),Ue())}}module.exports=Ne;