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