1*ef5bb1f3SLORTET====== Extranet Plugin ====== 2*ef5bb1f3SLORTET 3*ef5bb1f3SLORTET---- plugin ---- 4*ef5bb1f3SLORTETdescription: Restrict pages, media and actions for extranet visitors 5*ef5bb1f3SLORTETauthor : Valentin LORTET 6*ef5bb1f3SLORTETemail : contact@valentinlortet.fr 7*ef5bb1f3SLORTETtype : Action, Syntax, Helper 8*ef5bb1f3SLORTETlastupdate : 2026-03-13 9*ef5bb1f3SLORTETcompatible : Librarian 10*ef5bb1f3SLORTETdepends : prosemirror 11*ef5bb1f3SLORTETconflicts : 12*ef5bb1f3SLORTETsimilar : 13*ef5bb1f3SLORTETtags : Access, Extranet, Intranet, Proxy, Security, Helper 14*ef5bb1f3SLORTET 15*ef5bb1f3SLORTETdownloadurl: https://github.com/Lortet/dokuwiki-plugin-extranet/zipball/master 16*ef5bb1f3SLORTETbugtracker : https://github.com/Lortet/dokuwiki-plugin-extranet/issues 17*ef5bb1f3SLORTETsourcerepo : https://github.com/Lortet/dokuwiki-plugin-extranet/ 18*ef5bb1f3SLORTETdonationurl: 19*ef5bb1f3SLORTETscreenshot_img : 20*ef5bb1f3SLORTET---- 21*ef5bb1f3SLORTET 22*ef5bb1f3SLORTET[[fr:plugin:extranet| Français]] | **English** | [[de:plugin:extranet| Deutsch]] | [[es:plugin:extranet| Español]] 23*ef5bb1f3SLORTET 24*ef5bb1f3SLORTET===== Installation ===== 25*ef5bb1f3SLORTET 26*ef5bb1f3SLORTETInstall the plugin from the [[plugin:extension|Extension Manager]] using the URL above, or copy it into ''lib/plugins/extranet''. 27*ef5bb1f3SLORTET 28*ef5bb1f3SLORTET===== Description ===== 29*ef5bb1f3SLORTET 30*ef5bb1f3SLORTETThe **extranet** plugin can: 31*ef5bb1f3SLORTET * detect whether a request comes from the extranet from a configurable ''$_SERVER'' value; 32*ef5bb1f3SLORTET * restrict the display of pages and media files; 33*ef5bb1f3SLORTET * disable selected DokuWiki actions for extranet visitors; 34*ef5bb1f3SLORTET * apply global rules through filters; 35*ef5bb1f3SLORTET * add per-page exceptions with ''~~NOEXTRANET~~'' and ''~~EXTRANET~~''; 36*ef5bb1f3SLORTET * integrate with ProseMirror so these macros are preserved in WYSIWYG editing. 37*ef5bb1f3SLORTET 38*ef5bb1f3SLORTETThe plugin is suited to intranet/extranet segmentation. It complements ACLs, but does not replace real access control. 39*ef5bb1f3SLORTET 40*ef5bb1f3SLORTET===== Settings ===== 41*ef5bb1f3SLORTET 42*ef5bb1f3SLORTET^ Name ^ Description ^ Default value ^ 43*ef5bb1f3SLORTET| request_match_key | ''$_SERVER'' key used to determine whether the request comes from the extranet. Can be ''REMOTE_ADDR'' or an ''HTTP_*'' key. | '''' | 44*ef5bb1f3SLORTET| extranet_match_list | Comma-separated list of values treated as extranet. | '''' | 45*ef5bb1f3SLORTET| extranet_match_regex | Regex used to detect an extranet request from the configured value. | '''' | 46*ef5bb1f3SLORTET| default_policy | Default policy: ''allow'', ''block'', ''force_allow'' or ''force_block''. | ''allow'' | 47*ef5bb1f3SLORTET| filter_list | List of page or media IDs targeted by the policy. Supports exact IDs, namespace prefixes ending with '':'', and wildcards ''*''. | '''' | 48*ef5bb1f3SLORTET| filter_regex | Additional regex used to target pages or media files. | '''' | 49*ef5bb1f3SLORTET| hide_files | How restricted media files are handled: ''all'', ''except_pageicons'' or ''none''. | ''none'' | 50*ef5bb1f3SLORTET| disable_actions | DokuWiki actions disabled for extranet visitors. | ''admin,edit,preview,save,revisions,diff,export_raw,export_xhtml,export_xhtmlbody,permalink,register'' | 51*ef5bb1f3SLORTET| restricted_disable_actions | Additional actions disabled only when the current page is restricted. | '''' | 52*ef5bb1f3SLORTET| preserve_first_title | Keep the first heading when a page is hidden. | ''true'' | 53*ef5bb1f3SLORTET| message_prefix | Prefix inserted before the restriction message. | '''' | 54*ef5bb1f3SLORTET| message_suffix | Suffix inserted after the restriction message. | '''' | 55*ef5bb1f3SLORTET 56*ef5bb1f3SLORTET===== Compatibility ===== 57*ef5bb1f3SLORTET 58*ef5bb1f3SLORTETThe following legacy configuration keys are still accepted: 59*ef5bb1f3SLORTET * ''server_ip_key'' 60*ef5bb1f3SLORTET * ''extranet_ip_list'' 61*ef5bb1f3SLORTET * ''extranet_ip_regex'' 62*ef5bb1f3SLORTET 63*ef5bb1f3SLORTETThe new names should be preferred: 64*ef5bb1f3SLORTET * ''request_match_key'' 65*ef5bb1f3SLORTET * ''extranet_match_list'' 66*ef5bb1f3SLORTET * ''extranet_match_regex'' 67*ef5bb1f3SLORTET 68*ef5bb1f3SLORTET===== Usage ===== 69*ef5bb1f3SLORTET 70*ef5bb1f3SLORTETTwo macros are available: 71*ef5bb1f3SLORTET * ''~~NOEXTRANET~~'' : blocks the page from the extranet when the policy allows it; 72*ef5bb1f3SLORTET * ''~~EXTRANET~~'' : allows the page from the extranet when the policy allows it. 73*ef5bb1f3SLORTET 74*ef5bb1f3SLORTETBehavior depending on ''default_policy'': 75*ef5bb1f3SLORTET * ''allow'' : everything is allowed except filtered pages or pages marked ''~~NOEXTRANET~~''; 76*ef5bb1f3SLORTET * ''block'' : everything is blocked except filtered pages or pages marked ''~~EXTRANET~~''; 77*ef5bb1f3SLORTET * ''force_allow'' : only filter rules apply, ''~~NOEXTRANET~~'' is ignored; 78*ef5bb1f3SLORTET * ''force_block'' : only filter rules apply, ''~~EXTRANET~~'' is ignored. 79*ef5bb1f3SLORTET 80*ef5bb1f3SLORTET===== Examples ===== 81*ef5bb1f3SLORTET 82*ef5bb1f3SLORTETDetection by direct IP: 83*ef5bb1f3SLORTET * ''request_match_key = REMOTE_ADDR'' 84*ef5bb1f3SLORTET * ''extranet_match_regex = /^10\.100\./'' 85*ef5bb1f3SLORTET 86*ef5bb1f3SLORTETDetection by proxy header: 87*ef5bb1f3SLORTET * ''request_match_key = HTTP_X_NETWORK_ZONE'' 88*ef5bb1f3SLORTET * ''extranet_match_list = extranet'' 89*ef5bb1f3SLORTET 90*ef5bb1f3SLORTETDetection by upstream host name: 91*ef5bb1f3SLORTET * ''request_match_key = HTTP_X_UPSTREAM_HOST'' 92*ef5bb1f3SLORTET * ''extranet_match_regex = /^frontend-ext-/'' 93*ef5bb1f3SLORTET 94*ef5bb1f3SLORTET===== Helper API ===== 95*ef5bb1f3SLORTET 96*ef5bb1f3SLORTETLoad helper: 97*ef5bb1f3SLORTET''$extranet = plugin_load('helper', 'extranet');'' 98*ef5bb1f3SLORTET 99*ef5bb1f3SLORTET==== Main methods ==== 100*ef5bb1f3SLORTET 101*ef5bb1f3SLORTET^ Method ^ Since ^ Description ^ 102*ef5bb1f3SLORTET| ''getDefaultPolicy()'' | ''2026-03-13'' | Returns the effective default policy. | 103*ef5bb1f3SLORTET| ''getRequestMatchKey()'' | ''2026-03-13'' | Returns the ''$_SERVER'' key used for detection. | 104*ef5bb1f3SLORTET| ''getExtranetMatchList()'' | ''2026-03-13'' | Returns the list of values treated as extranet. | 105*ef5bb1f3SLORTET| ''getExtranetMatchRegex()'' | ''2026-03-13'' | Returns the extranet detection regex. | 106*ef5bb1f3SLORTET| ''isExtranetRequest()'' | ''2026-03-13'' | Tells whether the current request is treated as extranet. | 107*ef5bb1f3SLORTET| ''isPageVisibleFromExtranet($id, $content = null)'' | ''2026-03-13'' | Tells whether a page is visible from the extranet. | 108*ef5bb1f3SLORTET| ''isMediaVisibleFromExtranet($mediaID)'' | ''2026-03-13'' | Tells whether a media file is visible from the extranet. | 109*ef5bb1f3SLORTET| ''isPageAllowed($id, $content = null)'' | ''2026-03-13'' | Tells whether a page is allowed in the current context. | 110*ef5bb1f3SLORTET| ''isMediaAllowed($mediaID)'' | ''2026-03-13'' | Tells whether a media file is allowed in the current context. | 111*ef5bb1f3SLORTET| ''parseRuleList($raw)'' | ''2026-03-13'' | Converts a rules configuration into a usable array. | 112*ef5bb1f3SLORTET| ''idMatchesRule($id, $rule)'' | ''2026-03-13'' | Tests an ID against an exact rule, namespace, wildcard or regex. | 113*ef5bb1f3SLORTET 114*ef5bb1f3SLORTET===== How it works ===== 115*ef5bb1f3SLORTET 116*ef5bb1f3SLORTETExtranet detection is based on a value read from ''$_SERVER'': 117*ef5bb1f3SLORTET * the full raw value is tested; 118*ef5bb1f3SLORTET * if it contains commas, each separated item is also tested. 119*ef5bb1f3SLORTET 120*ef5bb1f3SLORTETThis covers: 121*ef5bb1f3SLORTET * a direct IP; 122*ef5bb1f3SLORTET * an ''X-Forwarded-For''-style header; 123*ef5bb1f3SLORTET * a network marker injected by a proxy; 124*ef5bb1f3SLORTET * an upstream or frontend host name. 125*ef5bb1f3SLORTET 126*ef5bb1f3SLORTETWhen a page is restricted: 127*ef5bb1f3SLORTET * the cache is separated between intranet and extranet; 128*ef5bb1f3SLORTET * the wiki content is replaced with a configurable message; 129*ef5bb1f3SLORTET * the first heading can be kept if ''preserve_first_title'' is enabled. 130*ef5bb1f3SLORTET 131*ef5bb1f3SLORTETWhen a media file is restricted and ''hide_files'' is not ''none'', the plugin serves a dedicated image instead of the real file. 132*ef5bb1f3SLORTET 133*ef5bb1f3SLORTET===== Notes ===== 134*ef5bb1f3SLORTET 135*ef5bb1f3SLORTET * The plugin should not be seen as a replacement for ACLs. 136*ef5bb1f3SLORTET * Reliability depends on the request marker provided by the web infrastructure. An untrusted or forgeable header makes the detection unsafe. 137