허용목록이 플러그인 코드 상수라, 새 확장이 저장 키를 도입할 때마다 이 플러그인을 고쳐야 했다. 고치지 않으면 그 키는 방문마다 파기되는데 예외도 로그도 남지 않아 운영자에게는 "설정이 저장되지 않는다" 는 증상만 보인다. 허용목록을 운영자 설정(necessary_storage_allowlist)으로 옮기고, 관리자 환경설정에 브라우저 저장소·세션 저장소·쿠키 세 카드를 두어 직접 편집하게 했다. 확장은 GDPR 을 알 필요가 없고 GDPR 도 확장을 알 필요가 없다 — 연결은 운영자가 화면에서 한다. 저장 키를 플러그인이 관측·수집하지 않는 것도 같은 이유다: 관측 자체가 추적이다. 판정은 서버(미들웨어)와 클라이언트 셋(인터셉터 둘 + 정리기)이 같은 설정을 같은 매칭 규칙으로 읽는다. 잠금 항목(로그인 토큰·CSRF·세션 쿠키·동의 기록)만 설정 밖에 두고 판정 시점에 합집합으로 얹는다 — 설정에 담기면 저장 요청 한 번으로 지워져 잠금이 아니게 된다. 기설치본은 업그레이드 스텝이 현재 카탈로그를 설정 파일에 못박되, 운영자가 이미 편집했으면 그대로 둔다. 함께 고친 선재 결함 셋: - 차단 도메인 추천 목록이 응답에 실리지 않아 자동완성이 동작하지 않던 문제 - 세션 쿠키 이름을 기본값에서 바꾼 사이트에서 브라우저 측 목록의 그 항목이 죽던 문제 - 쿠키 목록에만 앞부분 매칭(`이름_*`)이 적용되지 않던 문제
2 lines
9.6 KiB
JavaScript
2 lines
9.6 KiB
JavaScript
var SirsoftGdpr=(function(g){"use strict";function ie(e,t){const n=e.toLowerCase(),r=t.toLowerCase();if(r.startsWith("*.")){const o=r.slice(1);return n.endsWith(o)&&n!==o.slice(1)}return n===r}function H(e,t){if(typeof window>"u"||typeof URL>"u")return null;let n,r;try{const o=new URL(e,window.location.href);r=o.protocol,n=o.hostname}catch{return null}if(r!=="http:"&&r!=="https:"||n===""||n===window.location.hostname)return null;for(const[o,i]of Object.entries(t))if(o!=="necessary"){for(const s of i)if(ie(n,s))return o}return null}const A="data-gdpr-category",k="gdpr-blocked-embed",M="data-gdpr-original",_=[`script[${A}]`,`iframe[${A}]`,"script[src]","iframe[src]","img[src]","link[href]"].join(", ");let u=null,p={categories:{},needs_renewal:!1},G={};function $(e){if(e&&typeof e=="object"&&"categories"in e){const t=e;return{categories:{...t.categories},needs_renewal:t.needs_renewal===!0}}return{categories:{...e},needs_renewal:!1}}function U(e){p=$(e),u!==null&&w()}function se(e){G={...e},u!==null&&w()}function ce(){typeof document>"u"||u!==null||(w(),u=new MutationObserver(e=>{for(const t of e)t.addedNodes.forEach(n=>{n instanceof HTMLElement&&ae(n)})}),u.observe(document.documentElement,{childList:!0,subtree:!0}),window.addEventListener("gdpr:consent-changed",le))}function le(e){const t=e.detail;t!==null&&typeof t=="object"&&(p=$(t)),w()}function ae(e){fe(e)&&E(e),e.querySelectorAll(_).forEach(t=>E(t))}function w(){typeof document>"u"||(document.querySelectorAll(`.${k}`).forEach(e=>{const t=e.dataset.gdprBlockedCategory;t&&S(t)&&de(e)}),document.querySelectorAll(_).forEach(e=>E(e)))}function E(e){if(e.classList.contains(k)||e.hasAttribute("data-gdpr-blocked-category"))return;const t=e.getAttribute(A);if(t!==null&&t!==""){if(S(t))return;K(e,t);return}const n=ue(e);if(n===null)return;const r=H(n,G);r!==null&&(S(r)||K(e,r))}function ue(e){return e instanceof HTMLScriptElement||e instanceof HTMLIFrameElement||e instanceof HTMLImageElement?e.getAttribute("src"):e instanceof HTMLLinkElement?e.getAttribute("href"):null}function fe(e){if(typeof e.matches!="function")return!1;try{return e.matches(_)}catch{return!1}}function K(e,t){const n=document.createElement("div");n.className=k,n.dataset.gdprBlockedCategory=t,n.dataset.gdprOriginalTag=e.tagName.toLowerCase(),n.setAttribute(M,e.outerHTML),n.setAttribute("aria-hidden","true"),n.style.display="none",e.replaceWith(n)}function de(e){const t=e.getAttribute(M);if(!t){e.remove();return}const n=document.createElement("div");n.innerHTML=t;const r=n.firstElementChild;r!==null?e.replaceWith(r):e.remove()}function S(e){return e==="necessary"?!0:p.needs_renewal?!1:p.categories[e]===!0}const L=["localStorage","sessionStorage","cookie"],f={localStorage:["auth_token"],sessionStorage:[],cookie:["XSRF-TOKEN","gdpr_session"]};function W(){return{localStorage:[],sessionStorage:[],cookie:[]}}function x(e){const t=W();if(e===null||typeof e!="object")return t;const n=e;for(const r of L){const o=n[r];Array.isArray(o)&&(t[r]=o.filter(i=>typeof i=="string"&&i!==""))}return t}function ge(e,t){const n=W();for(const r of L)n[r]=[...new Set([...e[r],...t[r]])];return n}function pe(e){return L.every(t=>e[t].length===0)}function we(e,t){if(t.endsWith("*")){const n=t.slice(0,-1);return n!==""&&e.startsWith(n)}return t===e}function m(e,t,n){return n[t].some(r=>we(e,r))}const me=500,ye=["click","keydown","change","submit","pointerdown","touchstart"];let q=!1,T=0;function be(e){e.isTrusted&&(T=Date.now())}function he(){if(!q){q=!0;for(const e of ye){const t=be;window.addEventListener(e,t,{capture:!0,passive:!0})}}}function F(){const e=window.event;return e&&e.isTrusted?!0:T===0?!1:Date.now()-T<=me}let D=!1,c=null,y={functionalConsented:!1,necessaryAllowlist:f};function Ce(e){const t=e.indexOf("=");return t<=0?null:e.substring(0,t).trim()}function Ae(e){return m(e,"cookie",y.necessaryAllowlist)}function ke(e){const t=Ce(e);return t===null?!1:!!(_e(e)||Ae(t)||y.functionalConsented||F())}function _e(e){const t=e.toLowerCase(),n=t.match(/max-age\s*=\s*(-?\d+)/);return!!(n&&parseInt(n[1],10)<=0||t.includes("expires=thu, 01 jan 1970")||t.includes("expires=thu, 01-jan-1970"))}function Ee(e){if(D)return;if(D=!0,y=e,c=Object.getOwnPropertyDescriptor(Document.prototype,"cookie")??null,!c||!c.set||!c.get){D=!1;return}const t=c.set,n=c.get;Object.defineProperty(Document.prototype,"cookie",{configurable:!0,get(){return n.call(this)},set(r){ke(r)&&t.call(this,r)}})}function z(e){y=e}function Y(e,t,n){const r=[];for(let o=0;o<e.length;o++){const i=e.key(o);i!==null&&r.push(i)}for(const o of r)if(!m(o,t,n))try{e.removeItem(o)}catch{}}function Se(e){const t=document.cookie;if(!t)return;const n=t.split(";");for(const r of n){const o=r.indexOf("="),i=(o>-1?r.substring(0,o):r).trim();if(i&&!m(i,"cookie",e))try{document.cookie=`${i}=; Max-Age=0; Path=/`}catch{}}}function J(e={}){const t=e.allowlist??f;Y(window.localStorage,"localStorage",t),Y(window.sessionStorage,"sessionStorage",t),Se(t)}let I=null;function Le(){if(typeof window>"u")return null;const t=window.G7Core?.api;return t&&typeof t.get=="function"?t:null}async function X(e){const t=Le();if(t)try{return await t.get(e)}catch{return null}try{const n=await fetch("/api"+e,{method:"GET",headers:{Accept:"application/json"},credentials:"same-origin"});return n.ok?await n.json():null}catch{return null}}async function Te(){if(I)return I;const t=(await X("/plugins/sirsoft-gdpr/settings"))?.data;return t?(I=t,t):null}async function Q(){const e=await X("/plugins/sirsoft-gdpr/consent/cookie/status"),t=e?.data?.consents;return t==null?null:{categories:t,needs_renewal:e?.data?.needs_renewal===!0,current_policy_version:String(e?.data?.current_policy_version??"")}}const O="data-gdpr-blocked-src",v="data-gdpr-blocked-category",De="data-gdpr-category";let V=!1,d={blockedDomains:{},consent:{necessary:!0},needs_renewal:!1};function j(e){return e==="necessary"?!0:d.needs_renewal===!0?!1:d.consent?.[e]===!0}function Ie(e,t){const n=e.getAttribute(De);if(n!==null&&n!=="")return j(n)?null:n;const r=H(t,d.blockedDomains);return r===null||j(r)?null:r}function Oe(e){if(d={blockedDomains:e.blockedDomains??{},consent:e.consent??{necessary:!0},needs_renewal:e.needs_renewal===!0},V||typeof HTMLScriptElement>"u")return;const t=Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype,"src");t===void 0||typeof t.set!="function"||(Object.defineProperty(HTMLScriptElement.prototype,"src",{configurable:!0,enumerable:t.enumerable??!0,get(){return t.get?.call(this)??""},set(n){const r=Ie(this,n);if(r!==null){this.setAttribute(O,n),this.setAttribute(v,r);return}t.set.call(this,n)}}),V=!0)}function P(e){d={blockedDomains:e.blockedDomains??{},consent:e.consent??{necessary:!0},needs_renewal:e.needs_renewal===!0}}function Z(e){if(!j(e)||typeof document>"u")return;document.querySelectorAll(`script[${v}="${e}"]`).forEach(n=>{const r=n.getAttribute(O);if(r===null||r==="")return;const o=document.createElement("script");for(const s of Array.from(n.attributes))s.name===O||s.name===v||s.name==="src"||o.setAttribute(s.name,s.value);const i=n.parentNode;i!==null&&(i.replaceChild(o,n),o.src=r)})}let ee=!1,R=null,b={functionalConsented:!1,necessaryAllowlist:f};function ve(e,t){return!!(m(e,t,b.necessaryAllowlist)||b.functionalConsented||F())}function je(e){if(ee)return;ee=!0,b=e;const t=Storage.prototype;R=t.setItem,t.setItem=function(n,r){const o=this===window.sessionStorage?"sessionStorage":"localStorage";ve(n,o)&&R&&R.call(this,n,r)}}function te(e){b=e}const l="sirsoft-gdpr";function ne(){if(typeof window>"u")return{};const n=window.G7Config?.plugins?.[l]?.blocked_domains;if(n==null||typeof n!="object")return{};const r={};for(const[o,i]of Object.entries(n)){if(!Array.isArray(i))continue;const s=i.filter(a=>typeof a=="string"&&a!=="");s.length>0&&(r[o]=s)}return r}function N(){if(typeof window>"u")return f;const t=window.G7Config?.plugins?.[l],n=x(t?.necessary_storage_allowlist),r=x(t?.necessary_storage_locked);return ge(n,pe(r)?f:r)}function Pe(){return typeof window>"u"?!1:window.G7Config?.plugins?.[l]?.banner_enabled===!0}function B(){const e=window.G7Core?.getActionDispatcher?.();if(!e){setTimeout(B,100);return}e.registerHandler(`${l}.syncConsent`,async()=>{const t=await Q();if(t===null)return;const n=!t.needs_renewal&&t.categories.functional===!0;U({categories:t.categories,needs_renewal:t.needs_renewal});const r=ne();P({blockedDomains:r,consent:t.categories,needs_renewal:t.needs_renewal});const o=N();if(te({functionalConsented:n,necessaryAllowlist:o}),z({functionalConsented:n,necessaryAllowlist:o}),n||J({allowlist:o}),!t.needs_renewal)for(const[i,s]of Object.entries(t.categories))s===!0&&i!=="necessary"&&Z(i)})}async function re(){if(typeof window>"u")return;if(B(),Pe()){const h=ne();Oe({blockedDomains:h,consent:{necessary:!0}}),he();const C=N();je({functionalConsented:!1,necessaryAllowlist:C}),Ee({functionalConsented:!1,necessaryAllowlist:C})}const t=await Te();if(!t||!(t.banner_enabled===!0))return;const r=t.blocked_domains??{};se(r),P({blockedDomains:r,consent:{necessary:!0}}),ce();const i=await Q(),s=i!==null&&!i.needs_renewal&&i.categories.functional===!0,a=N();if(te({functionalConsented:s,necessaryAllowlist:a}),z({functionalConsented:s,necessaryAllowlist:a}),s||J({allowlist:a}),i!==null&&(U({categories:i.categories,needs_renewal:i.needs_renewal}),P({blockedDomains:r,consent:i.categories,needs_renewal:i.needs_renewal}),!i.needs_renewal))for(const[h,C]of Object.entries(i.categories))C===!0&&h!=="necessary"&&Z(h)}function oe(){B()}return typeof window<"u"&&(window.__SirsoftGdpr={identifier:l,initPlugin:oe}),typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{re()}):re()),g.PLUGIN_IDENTIFIER=l,g.initPlugin=oe,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"}),g})({});
|