Restricted Site Access - Version 7.3.0

Version Description

  • Added: Ability to add, remove, and set IPs programatically (props @ivankruchkoff, @helen, @paulschreiber).
  • Added: Cloudflare IP detection compatibility (props @eightam, @dinhtungdu).
  • Added: WP-CLI option to modify and retrieve IP entry labels (props @Sidsector9, @dinhtungdu, @mikelking).
  • Added: Acceptance and end-to-end tests (props @dinhtungdu, @helen, @jeffpaul, @Sidsector9, @cadic).
  • Added: Issue management automation, JavaScript linting, and PHPUnit testing via GitHub Actions (props @jeffpaul, @Sidsector9, @dinhtungdu, @mitogh).
  • Changed: Update WP-CLI code to use new API for add/remove/set IPs (props @paulschreiber, @dinhtungdu).
  • Changed: Bump WordPress "tested up to" version 5.8 (props @dinhtungdu, @jeffpaul, @ankitguptaindia, @BBerg10up, @sudip-10up).
  • Changed: Improved Composer configuration and support (props @kopepasah, @dinhtungdu).
  • Changed: Improved documentation (props @jeffpaul, @dinhtungdu, @helen).
  • Changed: The default constant WP_TESTS_DOMAIN is replaced by a new constant PHP_UNIT_TESTS_ENV to allow testing correct redirections for restricted users by Cypress end-to-end tests (props @faisal-alvi, @Sidsector9, @dkotter).
  • Fixed: Issue with allowed IPs and associated comments being offset (props @adamsilverstein, @helen, @ivankruchkoff).
  • Fixed: Prevents new users from getting WordPress setup email, new user flow in multisite installations now work as expected (props @dinhtungdu, @wkw, @jeffpaul, @ivanlopez).
  • Fixed: Ensure assets are enqueued on correct screen only (props @kopepasah, @dinhtungdu, @paulschreiber, @n8dnx).
  • Fixed: Use correct variable for screen reader text (props @dinhtungdu, @lkraav).
  • Fixed: Set the correct filter option value to site_public if RSA_FORBID_RESTRICTION is defined (props @pabamato, @dinhtungdu).
  • Fixed: Prevent redirect loops when Redirect URL set on the same domain with or without Redirect to same path enabled (props @Sidsector9, @faisal-alvi, @cadic via #158).
  • Fixed: Undefined key "url" warning (props @Sidsector9).
  • Fixed: Redirect to same path setting screen-reader-text (props @pedro-mendonca).
  • Fixed: No loading of JS admin scripts on the network admin page (props @Sidsector9, @dinhtungdu).
  • Security: Bump websocket-extensions from 0.1.3 to 0.1.4 (props @dependabot).
  • Security: Bump lodash from 4.17.15 to 4.17.21 (props @dependabot).
  • Security: Bump rmccue/requests from 1.7.0 to 1.8.0 (props @dependabot).
  • Security: Bump grunt from 1.0.4 to 1.3.0 (props @dependabot).
  • Security: Bump path-parse from 1.0.6 to 1.0.7 (props @dependabot).
Download this release

Release Info

Developer 10up
Plugin Icon 128x128 Restricted Site Access
Version 7.3.0
Comparing to
See all releases

Code changes from version 7.2.0 to 7.3.0

.eslintrc.js ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ /**
3
+ * Internal dependencies
4
+ */
5
+
6
+ module.exports = {
7
+ extends: 'plugin:@wordpress/eslint-plugin/recommended-with-formatting',
8
+ globals: {
9
+ window: 'readonly',
10
+ $: 'readonly',
11
+ jQuery: 'readonly',
12
+ rsaAdmin: 'readonly',
13
+ rsaSettings: 'readonly',
14
+ ajaxurl: 'readonly',
15
+ },
16
+ };
assets/js/admin.min.js CHANGED
@@ -1 +1 @@
1
- !function(e,s){"use strict";s(".notice").on("click",".notice-dismiss",function(e){e.delegateTarget.getAttribute("data-rsa-notice")&&s.ajax({method:"post",data:{nonce:rsaAdmin.nonce,action:"rsa_notice_dismiss"},url:ajaxurl})})}(window,jQuery),function(s,i){"use strict";({els:{dialog:document.getElementById("rsa-disable-dialog"),userMessage:document.getElementById("rsa-user-message")},variables:{expectedAnswer:rsaAdmin.strings.message.toLowerCase(),disablingURL:null},openDialog:function(e){e.preventDefault(),i(this.els.dialog).dialog("open")},isExpectedAnswer:function(){return this.els.userMessage.value.toLowerCase()===this.variables.expectedAnswer},dialogSettings:function(){var e=this;e.close=function(){i(e.els.dialog).dialog("close"),e.els.userMessage.style.border="1px solid #ddd",e.els.userMessage.value=""},i(this.els.dialog).dialog({dialogClass:"wp-dialog",autoOpen:!1,draggable:!1,width:"auto",modal:!0,resizable:!1,buttons:[{text:rsaAdmin.strings.confirm,click:function(){e.isExpectedAnswer()?s.location.href=e.variables.disablingURL:e.els.userMessage.style.border="1px solid red"}},{text:rsaAdmin.strings.cancel,click:function(){e.close()},class:"button-primary"}],open:function(){i(".ui-widget-overlay").bind("click",function(){e.close()})},create:function(){i(".ui-dialog-titlebar-close").addClass("ui-button"),i(this).siblings(".ui-dialog-titlebar").hide()}}),this.els.buttons=i(this.els.dialog).dialog("option","buttons")},maybeSubmit:function(e){switch(e.key){case"Enter":this.els.buttons[0].click()}},bindEvents:function(){i('[data-slug="restricted-site-access"]').on("click",".deactivate a",this.openDialog.bind(this)),this.els.userMessage.addEventListener("keyup",this.maybeSubmit.bind(this))},init:function(){rsaAdmin.isNetworkWidePluginsPage&&(this.variables.disablingURL=document.getElementById("the-list").querySelector('[data-slug="restricted-site-access"] .deactivate a').href,this.bindEvents(),this.dialogSettings())}}).init()}(window,jQuery);
1
+ !function(e,s){"use strict";s(".notice").on("click",".notice-dismiss",function(e){e.delegateTarget.getAttribute("data-rsa-notice")&&s.ajax({method:"post",data:{nonce:rsaAdmin.nonce,action:"rsa_notice_dismiss"},url:ajaxurl})})}(window,jQuery),function(e,s){"use strict";({els:{dialog:document.getElementById("rsa-disable-dialog"),userMessage:document.getElementById("rsa-user-message")},variables:{expectedAnswer:rsaAdmin.strings.message.toLowerCase(),disablingURL:null},openDialog(e){e.preventDefault(),s(this.els.dialog).dialog("open")},isExpectedAnswer(){return this.els.userMessage.value.toLowerCase()===this.variables.expectedAnswer},dialogSettings(){const t=this;t.close=function(){s(t.els.dialog).dialog("close"),t.els.userMessage.style.border="1px solid #ddd",t.els.userMessage.value=""},s(this.els.dialog).dialog({dialogClass:"wp-dialog",autoOpen:!1,draggable:!1,width:"auto",modal:!0,resizable:!1,buttons:[{text:rsaAdmin.strings.confirm,click(){t.isExpectedAnswer()?e.location.href=t.variables.disablingURL:t.els.userMessage.style.border="1px solid red"}},{text:rsaAdmin.strings.cancel,click(){t.close()},class:"button-primary"}],open(){s(".ui-widget-overlay").bind("click",function(){t.close()})},create(){s(".ui-dialog-titlebar-close").addClass("ui-button"),s(this).siblings(".ui-dialog-titlebar").hide()}}),this.els.buttons=s(this.els.dialog).dialog("option","buttons")},maybeSubmit(e){switch(e.key){case"Enter":this.els.buttons[0].click()}},bindEvents(){s('[data-slug="restricted-site-access"]').on("click",".deactivate a",this.openDialog.bind(this)),this.els.userMessage.addEventListener("keyup",this.maybeSubmit.bind(this))},init(){const e=document.getElementById("the-list");e&&(this.variables.disablingURL=e.querySelector('[data-slug="restricted-site-access"] .deactivate a').href),this.bindEvents(),this.dialogSettings()}}).init()}(window,jQuery);
assets/js/settings.min.js CHANGED
@@ -1 +1 @@
1
- !function(e,c){"use strict";var r=e.document,n={add_btn:"",new_ip:"",ip_list_wrap:"",empty_ip:"",restrict_radio:"",table:"",redirect_choice:"",message_choice:"",page_choice:"",redirect_fields:"",message_field:"",page_field:""};!function(){n.add_btn=c(r.getElementById("addip")),n.new_ip=r.getElementById("newip"),n.new_ip_comment=r.getElementById("newipcomment"),n.ip_list_wrap=r.getElementById("ip_list"),n.empty_ip=c(r.getElementById("ip_list_empty")),n.restrict_radio=r.getElementById("blog-restricted"),n.table=c(r.getElementById("rsa-send-to-login")).closest("table"),n.redirect_choice=r.getElementById("rsa-redirect-visitor"),n.message_choice=r.getElementById("rsa-display-message"),n.page_choice=r.getElementById("rsa-unblocked-page"),n.redirect_fields=c(r.querySelectorAll(".rsa_redirect_field")).closest("tr"),n.message_field=c(r.getElementById("rsa_message")).closest("tr"),n.page_field=c(r.getElementById("rsa_page")).closest("tr"),n.restrict_radio&&!n.restrict_radio.checked&&n.table.hide(),n.redirect_choice&&!n.redirect_choice.checked&&n.redirect_fields.hide(),n.message_choice&&!n.message_choice.checked&&n.message_field.hide(),n.page_choice&&!n.page_choice.checked&&n.page_field.hide(),c(r.querySelectorAll("#rsa_handle_fields input")).on("change",function(){n.redirect_choice.checked?n.redirect_fields.show():n.redirect_fields.hide(),n.message_choice.checked?n.message_field.show():n.message_field.hide(),n.page_choice.checked?n.page_field.show():n.page_field.hide()}),c(r.querySelectorAll(".option-site-visibility input")).on("change",function(){n.restrict_radio.checked?n.table.show():n.table.hide()}),n.add_btn.on("click",function(){!function(t,d){if(""==c.trim(t))return;n.add_btn.attr("disabled","disabled");var e=c(r.querySelectorAll("#ip_list input")),i=0;for(e.length;i<e.length;i++)if(e[i].value==t)return c(e[i]).parent().effect("shake",600),n.add_btn.removeAttr("disabled");jQuery.post(ajaxurl,{action:"rsa_ip_check",ip_address:t,ip_address_comment:d,nonce:rsaAdmin.nonce},function(e){if(e)return c(n.new_ip.parentNode).effect("shake",600),n.add_btn.removeAttr("disabled"),!1;var i=n.empty_ip.clone().appendTo(n.ip_list_wrap);return i.children("input.ip").val(t),i.children("input.comment").val(d),i.removeAttr("id").slideDown(250),t==n.new_ip.value&&(c(n.new_ip).val(""),c(n.new_ip_comment).val("")),n.add_btn.removeAttr("disabled"),!0})}(n.new_ip.value,n.new_ip_comment.value)});var e=r.getElementById("rsa_myip");null!==e&&c(e).on("click",function(){c(n.new_ip).val(c(this).data("myip"))}),c(n.ip_list_wrap).on("click",".remove_btn",function(){c(this.parentNode).slideUp(250,function(){c(this).remove()})})}()}(window,jQuery);
1
+ !function(e,t){"use strict";const i=e.document,c={add_btn:"",new_ip:"",ip_list_wrap:"",empty_ip:"",restrict_radio:"",table:"",redirect_choice:"",message_choice:"",page_choice:"",redirect_fields:"",message_field:"",page_field:""};!function(){c.add_btn=t(i.getElementById("addip")),c.new_ip=i.getElementById("newip"),c.new_ip_comment=i.getElementById("newipcomment"),c.ip_list_wrap=i.getElementById("ip_list"),c.empty_ip=t(i.getElementById("ip_list_empty")),c.restrict_radio=i.getElementById("blog-restricted"),c.table=t(i.getElementById("rsa-send-to-login")).closest("table"),c.redirect_choice=i.getElementById("rsa-redirect-visitor"),c.message_choice=i.getElementById("rsa-display-message"),c.page_choice=i.getElementById("rsa-unblocked-page"),c.redirect_fields=t(i.querySelectorAll(".rsa_redirect_field")).closest("tr"),c.message_field=t(i.getElementById("rsa_message")).closest("tr"),c.page_field=t(i.getElementById("rsa_page")).closest("tr"),c.restrict_radio&&!c.restrict_radio.checked&&c.table.hide(),c.redirect_choice&&!c.redirect_choice.checked&&c.redirect_fields.hide(),c.message_choice&&!c.message_choice.checked&&c.message_field.hide(),c.page_choice&&!c.page_choice.checked&&c.page_field.hide(),t(i.querySelectorAll("#rsa_handle_fields input")).on("change",function(){c.redirect_choice.checked?c.redirect_fields.show():c.redirect_fields.hide(),c.message_choice.checked?c.message_field.show():c.message_field.hide(),c.page_choice.checked?c.page_field.show():c.page_field.hide()}),t(i.querySelectorAll(".option-site-visibility input")).on("change",function(){c.restrict_radio.checked?c.table.show():c.table.hide()}),c.add_btn.on("click",function(){!function(e,d){if(""===t.trim(e))return!1;c.add_btn.attr("disabled","disabled");const n=t(i.querySelectorAll("#ip_list input"));for(let i=0;i<n.length;i++)if(n[i].value===e)return t(n[i]).parent().effect("shake",600),c.add_btn.removeAttr("disabled"),!1;jQuery.post(ajaxurl,{action:"rsa_ip_check",ip_address:e,ip_address_comment:d,nonce:rsaSettings.nonce},function(i){if(i)return t(c.new_ip.parentNode).effect("shake",600),c.add_btn.removeAttr("disabled"),!1;const n=c.empty_ip.clone().appendTo(c.ip_list_wrap);return n.children("input.ip").val(e),n.children("input.comment").val(d),n.removeAttr("id").slideDown(250),e===c.new_ip.value&&(t(c.new_ip).val(""),t(c.new_ip_comment).val("")),c.add_btn.removeAttr("disabled"),!0})}(c.new_ip.value,c.new_ip_comment.value)});const e=i.getElementById("rsa_myip");null!==e&&t(e).on("click",function(){t(c.new_ip).val(t(this).data("myip"))}),t(c.ip_list_wrap).on("click",".remove_btn",function(){t(this.parentNode).slideUp(250,function(){t(this).remove()})})}()}(window,jQuery);
assets/js/src/admin.js CHANGED
@@ -4,13 +4,15 @@
4
  *
5
  * Copyright (c) 2013 10up, jakemgold
6
  * Licensed under the GPLv2+ license.
 
 
 
7
  */
8
  ( function( window, $ ) {
9
-
10
  'use strict';
11
 
12
  $( '.notice' ).on( 'click', '.notice-dismiss', function( event ) {
13
- var notice = event.delegateTarget.getAttribute( 'data-rsa-notice' );
14
 
15
  if ( ! notice ) {
16
  return;
@@ -20,35 +22,34 @@
20
  method: 'post',
21
  data: {
22
  nonce: rsaAdmin.nonce,
23
- action: 'rsa_notice_dismiss'
24
  },
25
- url: ajaxurl
26
  } );
27
  } );
28
- } )( window, jQuery );
29
 
30
  ( function( window, $ ) {
31
  'use strict';
32
 
33
- var RSADisablePlugin = {
34
-
35
  els: {
36
  dialog: document.getElementById( 'rsa-disable-dialog' ),
37
- userMessage: document.getElementById( 'rsa-user-message' )
38
  },
39
 
40
  variables: {
41
  expectedAnswer: rsaAdmin.strings.message.toLowerCase(),
42
- disablingURL: null
43
  },
44
 
45
- openDialog: function( event ) {
46
  event.preventDefault();
47
  $( this.els.dialog ).dialog( 'open' );
48
  },
49
 
50
- isExpectedAnswer: function() {
51
- var userMessage = this.els.userMessage.value.toLowerCase();
52
 
53
  if ( userMessage === this.variables.expectedAnswer ) {
54
  return true;
@@ -56,14 +57,14 @@
56
 
57
  return false;
58
  },
59
- dialogSettings: function() {
60
- var self = this;
61
 
62
  self.close = function() {
63
  $( self.els.dialog ).dialog( 'close' );
64
  self.els.userMessage.style.border = '1px solid #ddd';
65
  self.els.userMessage.value = '';
66
- }
67
 
68
  $( this.els.dialog ).dialog( {
69
  dialogClass: 'wp-dialog',
@@ -75,58 +76,73 @@
75
  buttons: [
76
  {
77
  text: rsaAdmin.strings.confirm,
78
- click: function() {
79
  if ( self.isExpectedAnswer() ) {
80
- window.location.href = self.variables.disablingURL;
 
81
  } else {
82
- self.els.userMessage.style.border = '1px solid red';
 
83
  }
84
- }
85
  },
86
  {
87
  text: rsaAdmin.strings.cancel,
88
- click: function() {
89
  self.close();
90
  },
91
- 'class': 'button-primary'
92
- }
93
  ],
94
- open: function() {
95
  $( '.ui-widget-overlay' ).bind( 'click', function() {
96
  self.close();
97
- });
98
  },
99
- create: function() {
100
  $( '.ui-dialog-titlebar-close' ).addClass( 'ui-button' );
101
  $( this ).siblings( '.ui-dialog-titlebar' ).hide();
102
- }
103
  } );
104
 
105
- this.els.buttons = $( this.els.dialog ).dialog( 'option', 'buttons' );
 
 
 
106
  },
107
 
108
- maybeSubmit: function( event ) {
109
  switch ( event.key ) {
110
  case 'Enter':
111
- this.els.buttons[0].click();
112
  break;
113
  }
114
  },
115
 
116
- bindEvents: function() {
117
- $( '[data-slug="restricted-site-access"]' ).on( 'click', '.deactivate a', this.openDialog.bind( this ) );
118
- this.els.userMessage.addEventListener( 'keyup', this.maybeSubmit.bind( this ) );
 
 
 
 
 
 
 
 
 
119
  },
120
 
121
- init: function() {
122
- if ( ! rsaAdmin.isNetworkWidePluginsPage ) {
123
- return;
 
 
 
124
  }
125
-
126
- this.variables.disablingURL = document.getElementById( 'the-list' ).querySelector( '[data-slug="restricted-site-access"] .deactivate a' ).href;
127
  this.bindEvents();
128
  this.dialogSettings();
129
- }
130
  };
131
 
132
  RSADisablePlugin.init();
4
  *
5
  * Copyright (c) 2013 10up, jakemgold
6
  * Licensed under the GPLv2+ license.
7
+ *
8
+ * @param {Object} window Global window object
9
+ * @param {Object} $ The jQuery object.
10
  */
11
  ( function( window, $ ) {
 
12
  'use strict';
13
 
14
  $( '.notice' ).on( 'click', '.notice-dismiss', function( event ) {
15
+ const notice = event.delegateTarget.getAttribute( 'data-rsa-notice' );
16
 
17
  if ( ! notice ) {
18
  return;
22
  method: 'post',
23
  data: {
24
  nonce: rsaAdmin.nonce,
25
+ action: 'rsa_notice_dismiss',
26
  },
27
+ url: ajaxurl,
28
  } );
29
  } );
30
+ }( window, jQuery ) );
31
 
32
  ( function( window, $ ) {
33
  'use strict';
34
 
35
+ const RSADisablePlugin = {
 
36
  els: {
37
  dialog: document.getElementById( 'rsa-disable-dialog' ),
38
+ userMessage: document.getElementById( 'rsa-user-message' ),
39
  },
40
 
41
  variables: {
42
  expectedAnswer: rsaAdmin.strings.message.toLowerCase(),
43
+ disablingURL: null,
44
  },
45
 
46
+ openDialog( event ) {
47
  event.preventDefault();
48
  $( this.els.dialog ).dialog( 'open' );
49
  },
50
 
51
+ isExpectedAnswer() {
52
+ const userMessage = this.els.userMessage.value.toLowerCase();
53
 
54
  if ( userMessage === this.variables.expectedAnswer ) {
55
  return true;
57
 
58
  return false;
59
  },
60
+ dialogSettings() {
61
+ const self = this;
62
 
63
  self.close = function() {
64
  $( self.els.dialog ).dialog( 'close' );
65
  self.els.userMessage.style.border = '1px solid #ddd';
66
  self.els.userMessage.value = '';
67
+ };
68
 
69
  $( this.els.dialog ).dialog( {
70
  dialogClass: 'wp-dialog',
76
  buttons: [
77
  {
78
  text: rsaAdmin.strings.confirm,
79
+ click() {
80
  if ( self.isExpectedAnswer() ) {
81
+ window.location.href =
82
+ self.variables.disablingURL;
83
  } else {
84
+ self.els.userMessage.style.border =
85
+ '1px solid red';
86
  }
87
+ },
88
  },
89
  {
90
  text: rsaAdmin.strings.cancel,
91
+ click() {
92
  self.close();
93
  },
94
+ class: 'button-primary',
95
+ },
96
  ],
97
+ open() {
98
  $( '.ui-widget-overlay' ).bind( 'click', function() {
99
  self.close();
100
+ } );
101
  },
102
+ create() {
103
  $( '.ui-dialog-titlebar-close' ).addClass( 'ui-button' );
104
  $( this ).siblings( '.ui-dialog-titlebar' ).hide();
105
+ },
106
  } );
107
 
108
+ this.els.buttons = $( this.els.dialog ).dialog(
109
+ 'option',
110
+ 'buttons'
111
+ );
112
  },
113
 
114
+ maybeSubmit( event ) {
115
  switch ( event.key ) {
116
  case 'Enter':
117
+ this.els.buttons[ 0 ].click();
118
  break;
119
  }
120
  },
121
 
122
+ bindEvents() {
123
+ $( '[data-slug="restricted-site-access"]' ).on(
124
+ 'click',
125
+ '.deactivate a',
126
+ this.openDialog.bind( this )
127
+ );
128
+ if ( this.els.userMessage ) {
129
+ this.els.userMessage.addEventListener(
130
+ 'keyup',
131
+ this.maybeSubmit.bind( this )
132
+ );
133
+ }
134
  },
135
 
136
+ init() {
137
+ const list = document.getElementById( 'the-list' );
138
+ if ( list ) {
139
+ this.variables.disablingURL = list.querySelector(
140
+ '[data-slug="restricted-site-access"] .deactivate a'
141
+ ).href;
142
  }
 
 
143
  this.bindEvents();
144
  this.dialogSettings();
145
+ },
146
  };
147
 
148
  RSADisablePlugin.init();
assets/js/src/settings.js CHANGED
@@ -4,42 +4,53 @@
4
  *
5
  * Copyright (c) 2013 10up, jakemgold
6
  * Licensed under the GPLv2+ license.
 
 
 
7
  */
8
- (function (window, $) {
9
-
10
  'use strict';
11
- var document = window.document;
12
-
13
- var Cache = {
14
- add_btn : '',
15
- new_ip : '',
16
- ip_list_wrap : '',
17
- empty_ip : '',
18
- restrict_radio : '',
19
- table : '',
20
- redirect_choice : '',
21
- message_choice : '',
22
- page_choice : '',
23
- redirect_fields : '',
24
- message_field : '',
25
- page_field : ''
26
  };
27
 
28
  function init() {
29
-
30
  Cache.add_btn = $( document.getElementById( 'addip' ) );
31
  Cache.new_ip = document.getElementById( 'newip' );
32
  Cache.new_ip_comment = document.getElementById( 'newipcomment' );
33
  Cache.ip_list_wrap = document.getElementById( 'ip_list' );
34
  Cache.empty_ip = $( document.getElementById( 'ip_list_empty' ) );
35
  Cache.restrict_radio = document.getElementById( 'blog-restricted' );
36
- Cache.table = $( document.getElementById( 'rsa-send-to-login' ) ).closest( 'table' );
37
- Cache.redirect_choice = document.getElementById( 'rsa-redirect-visitor' );
 
 
 
 
38
  Cache.message_choice = document.getElementById( 'rsa-display-message' );
39
  Cache.page_choice = document.getElementById( 'rsa-unblocked-page' );
40
- Cache.redirect_fields = $( document.querySelectorAll( '.rsa_redirect_field' ) ).closest( 'tr' );
41
- Cache.message_field = $( document.getElementById( 'rsa_message' ) ).closest( 'tr' );
42
- Cache.page_field = $( document.getElementById( 'rsa_page' ) ).closest( 'tr' );
 
 
 
 
 
 
43
 
44
  if ( Cache.restrict_radio && ! Cache.restrict_radio.checked ) {
45
  Cache.table.hide();
@@ -57,88 +68,98 @@
57
  Cache.page_field.hide();
58
  }
59
 
60
- $( document.querySelectorAll( '#rsa_handle_fields input' ) ).on('change',function(){
61
-
62
- if ( Cache.redirect_choice.checked ) {
63
- Cache.redirect_fields.show();
64
- } else {
65
- Cache.redirect_fields.hide();
66
- }
 
67
 
68
- if ( Cache.message_choice.checked ) {
69
- Cache.message_field.show();
70
- } else {
71
- Cache.message_field.hide();
72
- }
73
 
74
- if ( Cache.page_choice.checked ) {
75
- Cache.page_field.show();
76
- } else {
77
- Cache.page_field.hide();
 
78
  }
79
-
80
- });
81
-
82
- $( document.querySelectorAll( '.option-site-visibility input' ) ).on('change',function(){
83
- if ( Cache.restrict_radio.checked ) {
84
- Cache.table.show();
85
- } else {
86
- Cache.table.hide();
 
 
87
  }
88
- });
89
 
90
- Cache.add_btn.on('click',function(){
91
- add_ip( Cache.new_ip.value, Cache.new_ip_comment.value );
92
- });
93
 
94
- var myip_btn = document.getElementById( 'rsa_myip' );
95
- if ( null !== myip_btn ) {
96
- $( myip_btn ).on('click',function(){
97
  $( Cache.new_ip ).val( $( this ).data( 'myip' ) );
98
- });
99
  }
100
 
101
- $( Cache.ip_list_wrap ).on('click', '.remove_btn', function(){
102
- $( this.parentNode ).slideUp( 250, function(){ $( this ).remove(); } );
103
- });
104
-
 
105
  }
106
 
107
- function add_ip( ip, comment ) {
108
- if ( $.trim( ip ) == '' ) {
109
  return false;
110
  }
111
 
112
- var shake_speed = 600;
113
 
114
  Cache.add_btn.attr( 'disabled', 'disabled' );
115
- var ip_list = $( document.querySelectorAll( '#ip_list input' ) );
116
 
117
- for ( var i = 0, l = ip_list.length; i < ip_list.length; i++ ) {
118
- if ( ip_list[i].value == ip ) {
119
- $( ip_list[i] ).parent().effect( 'shake', shake_speed );
120
  Cache.add_btn.removeAttr( 'disabled' );
121
  return false;
122
  }
123
  }
124
 
125
- jQuery.post( ajaxurl, {
126
- action: 'rsa_ip_check',
127
- 'ip_address': ip,
128
- 'ip_address_comment': comment,
129
- nonce: rsaAdmin.nonce
130
- }, function(response) {
131
- if ( response ) {
132
- $( Cache.new_ip.parentNode ).effect( 'shake', shake_speed );
133
- Cache.add_btn.removeAttr( 'disabled' );
134
- return false;
135
- } else {
136
- var new_ip = Cache.empty_ip.clone().appendTo( Cache.ip_list_wrap );
137
- new_ip.children( 'input.ip' ).val( ip );
138
- new_ip.children( 'input.comment' ).val( comment );
139
- new_ip.removeAttr( 'id' ).slideDown( 250 );
140
-
141
- if ( ip == Cache.new_ip.value ) {
 
 
 
 
 
142
  $( Cache.new_ip ).val( '' );
143
  $( Cache.new_ip_comment ).val( '' );
144
  }
@@ -146,9 +167,8 @@
146
 
147
  return true;
148
  }
149
- } );
150
  }
151
 
152
  init();
153
-
154
- })(window,jQuery);
4
  *
5
  * Copyright (c) 2013 10up, jakemgold
6
  * Licensed under the GPLv2+ license.
7
+ *
8
+ * @param {Object} window Global window object
9
+ * @param {Object} $ The jQuery object.
10
  */
11
+ ( function( window, $ ) {
 
12
  'use strict';
13
+ const document = window.document;
14
+
15
+ const Cache = {
16
+ add_btn: '',
17
+ new_ip: '',
18
+ ip_list_wrap: '',
19
+ empty_ip: '',
20
+ restrict_radio: '',
21
+ table: '',
22
+ redirect_choice: '',
23
+ message_choice: '',
24
+ page_choice: '',
25
+ redirect_fields: '',
26
+ message_field: '',
27
+ page_field: '',
28
  };
29
 
30
  function init() {
 
31
  Cache.add_btn = $( document.getElementById( 'addip' ) );
32
  Cache.new_ip = document.getElementById( 'newip' );
33
  Cache.new_ip_comment = document.getElementById( 'newipcomment' );
34
  Cache.ip_list_wrap = document.getElementById( 'ip_list' );
35
  Cache.empty_ip = $( document.getElementById( 'ip_list_empty' ) );
36
  Cache.restrict_radio = document.getElementById( 'blog-restricted' );
37
+ Cache.table = $(
38
+ document.getElementById( 'rsa-send-to-login' )
39
+ ).closest( 'table' );
40
+ Cache.redirect_choice = document.getElementById(
41
+ 'rsa-redirect-visitor'
42
+ );
43
  Cache.message_choice = document.getElementById( 'rsa-display-message' );
44
  Cache.page_choice = document.getElementById( 'rsa-unblocked-page' );
45
+ Cache.redirect_fields = $(
46
+ document.querySelectorAll( '.rsa_redirect_field' )
47
+ ).closest( 'tr' );
48
+ Cache.message_field = $(
49
+ document.getElementById( 'rsa_message' )
50
+ ).closest( 'tr' );
51
+ Cache.page_field = $( document.getElementById( 'rsa_page' ) ).closest(
52
+ 'tr'
53
+ );
54
 
55
  if ( Cache.restrict_radio && ! Cache.restrict_radio.checked ) {
56
  Cache.table.hide();
68
  Cache.page_field.hide();
69
  }
70
 
71
+ $( document.querySelectorAll( '#rsa_handle_fields input' ) ).on(
72
+ 'change',
73
+ function() {
74
+ if ( Cache.redirect_choice.checked ) {
75
+ Cache.redirect_fields.show();
76
+ } else {
77
+ Cache.redirect_fields.hide();
78
+ }
79
 
80
+ if ( Cache.message_choice.checked ) {
81
+ Cache.message_field.show();
82
+ } else {
83
+ Cache.message_field.hide();
84
+ }
85
 
86
+ if ( Cache.page_choice.checked ) {
87
+ Cache.page_field.show();
88
+ } else {
89
+ Cache.page_field.hide();
90
+ }
91
  }
92
+ );
93
+
94
+ $( document.querySelectorAll( '.option-site-visibility input' ) ).on(
95
+ 'change',
96
+ function() {
97
+ if ( Cache.restrict_radio.checked ) {
98
+ Cache.table.show();
99
+ } else {
100
+ Cache.table.hide();
101
+ }
102
  }
103
+ );
104
 
105
+ Cache.add_btn.on( 'click', function() {
106
+ addIp( Cache.new_ip.value, Cache.new_ip_comment.value );
107
+ } );
108
 
109
+ const myipBtn = document.getElementById( 'rsa_myip' );
110
+ if ( null !== myipBtn ) {
111
+ $( myipBtn ).on( 'click', function() {
112
  $( Cache.new_ip ).val( $( this ).data( 'myip' ) );
113
+ } );
114
  }
115
 
116
+ $( Cache.ip_list_wrap ).on( 'click', '.remove_btn', function() {
117
+ $( this.parentNode ).slideUp( 250, function() {
118
+ $( this ).remove();
119
+ } );
120
+ } );
121
  }
122
 
123
+ function addIp( ip, comment ) {
124
+ if ( $.trim( ip ) === '' ) {
125
  return false;
126
  }
127
 
128
+ const shakeSpeed = 600;
129
 
130
  Cache.add_btn.attr( 'disabled', 'disabled' );
131
+ const ipList = $( document.querySelectorAll( '#ip_list input' ) );
132
 
133
+ for ( let i = 0; i < ipList.length; i++ ) {
134
+ if ( ipList[ i ].value === ip ) {
135
+ $( ipList[ i ] ).parent().effect( 'shake', shakeSpeed );
136
  Cache.add_btn.removeAttr( 'disabled' );
137
  return false;
138
  }
139
  }
140
 
141
+ jQuery.post(
142
+ ajaxurl,
143
+ {
144
+ action: 'rsa_ip_check',
145
+ ip_address: ip,
146
+ ip_address_comment: comment,
147
+ nonce: rsaSettings.nonce,
148
+ },
149
+ function( response ) {
150
+ if ( response ) {
151
+ $( Cache.new_ip.parentNode ).effect( 'shake', shakeSpeed );
152
+ Cache.add_btn.removeAttr( 'disabled' );
153
+ return false;
154
+ }
155
+ const newIp = Cache.empty_ip
156
+ .clone()
157
+ .appendTo( Cache.ip_list_wrap );
158
+ newIp.children( 'input.ip' ).val( ip );
159
+ newIp.children( 'input.comment' ).val( comment );
160
+ newIp.removeAttr( 'id' ).slideDown( 250 );
161
+
162
+ if ( ip === Cache.new_ip.value ) {
163
  $( Cache.new_ip ).val( '' );
164
  $( Cache.new_ip_comment ).val( '' );
165
  }
167
 
168
  return true;
169
  }
170
+ );
171
  }
172
 
173
  init();
174
+ }( window, jQuery ) );
 
readme.txt CHANGED
@@ -1,10 +1,13 @@
1
  === Restricted Site Access ===
2
- Contributors: jakemgold, rcbth, 10up, thinkoomph, tlovett1
3
- Donate link: https://10up.com/plugins/restricted-site-access-wordpress/
4
- Tags: privacy, restricted, restrict, privacy, limited, permissions, security, block
5
- Requires at least: 4.6
6
- Tested up to: 5.3
7
- Stable tag: 7.2.0
 
 
 
8
 
9
  Limit access to visitors who are logged in or allowed by IP addresses. Includes many options for handling blocked visitors.
10
 
@@ -14,18 +17,18 @@ Limit access your site to visitors who are logged in or accessing the site from
14
 
15
  Adds a number of new configuration options to the Reading settings panel as well as the Network Settings panel in multisite. From these panels you can:
16
 
17
- 1. Enable or disable site restriction
18
- 1. Change the restriction behavior: send to login, redirect, display a message, display a page
19
- 1. Add IP addresses to an unrestricted list, including ranges
20
- 1. Quickly add your current IP to the unrestricted list
21
- 1. Customize the redirect location, including an option to send them to the same requested path and set the HTTP status code for SEO friendliness
22
- 1. Define a simple message to show restricted visitors, or select a page to show them - great for "coming soon" teasers!
23
 
24
  == Installation ==
25
 
26
- 1. Install easily with the WordPress plugin control panel or manually download the plugin and upload the extracted folder to the `/wp-content/plugins/` directory
27
- 1. Activate the plugin through the 'Plugins' menu in WordPress
28
- 1. Configure the plugin by going to the "Reading" menu (WP3.5+) or "Privacy" (earlier versions) under "Settings"
29
 
30
  == Frequently Asked Questions ==
31
 
@@ -99,6 +102,48 @@ In your `wp-config.php` file, you can define the following:
99
  define( 'RSA_IP_WHITELIST', '192.0.0.1|192.0.0.10' );
100
  `
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
  == Screenshots ==
104
 
@@ -108,6 +153,32 @@ define( 'RSA_IP_WHITELIST', '192.0.0.1|192.0.0.10' );
108
 
109
  == Changelog ==
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  = 7.2.0 =
112
  * **Added:** Warn and confirm before network disabling the plugin (props [@pereirinha](profiles.wordpress.org/pereirinha), [@adamsilverstein](https://profiles.wordpress.org/adamsilverstein/))
113
  * **Fixed:** Ensure comments associated with IPs stay associated correctly (props [@adamsilverstein](https://profiles.wordpress.org/adamsilverstein/), [@ivankk](https://profiles.wordpress.org/ivankk/), [@helen](https://profiles.wordpress.org/helen/))
1
  === Restricted Site Access ===
2
+ Contributors: jakemgold, rcbth, 10up, thinkoomph, tlovett1
3
+ Donate link: https://10up.com/plugins/restricted-site-access-wordpress/
4
+ Tags: privacy, restricted, restrict, privacy, limited, permissions, security, block
5
+ Requires at least: 5.0
6
+ Tested up to: 6.0
7
+ Stable tag: 7.3.0
8
+ Requires PHP: 5.6
9
+ License: GPLv2 or later
10
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
12
  Limit access to visitors who are logged in or allowed by IP addresses. Includes many options for handling blocked visitors.
13
 
17
 
18
  Adds a number of new configuration options to the Reading settings panel as well as the Network Settings panel in multisite. From these panels you can:
19
 
20
+ * Enable or disable site restriction
21
+ * Change the restriction behavior: send to login, redirect, display a message, display a page
22
+ * Add IP addresses to an unrestricted list, including ranges
23
+ * Quickly add your current IP to the unrestricted list
24
+ * Customize the redirect location, including an option to send them to the same requested path and set the HTTP status code for SEO friendliness
25
+ * Define a simple message to show restricted visitors, or select a page to show them - great for "coming soon" teasers!
26
 
27
  == Installation ==
28
 
29
+ 1. Install easily with the WordPress plugin control panel or manually download the plugin and upload the extracted folder to the `/wp-content/plugins/` directory.
30
+ 1. Activate the plugin through the 'Plugins' menu in WordPress.
31
+ 1. Configure the plugin by going to the "Reading" menu (WP3.5+) or "Privacy" (earlier versions) under "Settings".
32
 
33
  == Frequently Asked Questions ==
34
 
102
  define( 'RSA_IP_WHITELIST', '192.0.0.1|192.0.0.10' );
103
  `
104
 
105
+ In 7.1.1, the capacity to programmatically add / remove / set access IPs programmatically was introduced.
106
+
107
+ The following are valid statements:
108
+
109
+ Set IPs, ignoring all stored values (but not the constant defined values), if you're going to use the approach with array indices rather than mixing the two.
110
+
111
+ `
112
+ Restricted_Site_Access::set_ips( array( '192.168.0.1', '192.168.0.2', '192.168.0.3' ) );
113
+ Restricted_Site_Access::set_ips( array( 'labelfoo' => '192.168.0.1', 'labelbar' => 192.168.0.2', 'labelbaz' => 192.168.0.3' ) );
114
+ `
115
+
116
+ Add IPs, if they're not already added.
117
+
118
+ `
119
+ Restricted_Site_Access::add_ips( array( 'five' => '192.168.1.5', 'six' => '192.168.1.6') );
120
+ `
121
+
122
+ Remove IPs, if they are in the list.
123
+
124
+ `
125
+ Restricted_Site_Access::remove_ips( array( '192.168.1.2','192.168.1.5','192.168.1.6', ) );
126
+ `
127
+
128
+ = Is there a constant I can set to ensure my site is (or is not) restricted? =
129
+
130
+ As of version 7.1.0, two constants were introduced that give you the ability to specify if the site should be in restricted mode.
131
+
132
+ You can force the plugin to be in restricted mode by adding the following to your `wp-config.php` file:
133
+
134
+ `
135
+ define( 'RSA_FORCE_RESTRICTION', true );
136
+ `
137
+
138
+ Or to ensure your site won't be in restricted mode:
139
+
140
+ `
141
+ define( 'RSA_FORBID_RESTRICTION', true );
142
+ `
143
+
144
+ Make sure you add it before the `/* That's all, stop editing! Happy blogging. */` line.
145
+
146
+ Please note that setting `RSA_FORCE_RESTRICTION` will override `RSA_FORBID_RESTRICTION` if both are set.
147
 
148
  == Screenshots ==
149
 
153
 
154
  == Changelog ==
155
 
156
+ = 7.3.0 =
157
+ * **Added:** Ability to add, remove, and set IPs programatically (props [@ivankruchkoff](https://github.com/ivankruchkoff), [@helen](https://github.com/helen), [@paulschreiber](https://github.com/paulschreiber)).
158
+ * **Added:** Cloudflare IP detection compatibility (props [@eightam](https://github.com/eightam), [@dinhtungdu](https://github.com/dinhtungdu)).
159
+ * **Added:** WP-CLI option to modify and retrieve IP entry labels (props [@Sidsector9](https://github.com/Sidsector9), [@dinhtungdu](https://github.com/dinhtungdu), [@mikelking](https://github.com/mikelking)).
160
+ * **Added:** Acceptance and end-to-end tests (props [@dinhtungdu](https://github.com/dinhtungdu), [@helen](https://github.com/helen), [@jeffpaul](https://github.com/jeffpaul), [@Sidsector9](https://github.com/Sidsector9), [@cadic](https://github.com/cadic)).
161
+ * **Added:** Issue management automation, JavaScript linting, and PHPUnit testing via GitHub Actions (props [@jeffpaul](https://github.com/jeffpaul), [@Sidsector9](https://github.com/Sidsector9), [@dinhtungdu](https://github.com/dinhtungdu), [@mitogh](https://github.com/mitogh)).
162
+ * **Changed:** Update WP-CLI code to use new API for add/remove/set IPs (props [@paulschreiber](https://github.com/paulschreiber), [@dinhtungdu](https://github.com/dinhtungdu)).
163
+ * **Changed:** Bump WordPress "tested up to" version 5.8 (props [@dinhtungdu](https://github.com/dinhtungdu), [@jeffpaul](https://github.com/jeffpaul), [@ankitguptaindia](https://github.com/ankitguptaindia), [@BBerg10up](https://github.com/BBerg10up), [@sudip-10up](https://github.com/sudip-10up)).
164
+ * **Changed:** Improved Composer configuration and support (props [@kopepasah](https://github.com/kopepasah), [@dinhtungdu](https://github.com/dinhtungdu)).
165
+ * **Changed:** Improved documentation (props [@jeffpaul](https://github.com/jeffpaul), [@dinhtungdu](https://github.com/dinhtungdu), [@helen](https://github.com/helen)).
166
+ * **Changed:** The default constant `WP_TESTS_DOMAIN` is replaced by a new constant `PHP_UNIT_TESTS_ENV` to allow testing correct redirections for restricted users by Cypress end-to-end tests (props [@faisal-alvi](https://github.com/faisal-alvi), [@Sidsector9](https://github.com/Sidsector9), [@dkotter](https://github.com/dkotter)).
167
+ * **Fixed:** Issue with allowed IPs and associated comments being offset (props [@adamsilverstein](https://github.com/adamsilverstein), [@helen](https://github.com/helen), [@ivankruchkoff](https://github.com/ivankruchkoff)).
168
+ * **Fixed:** Prevents new users from getting WordPress setup email, new user flow in multisite installations now work as expected (props [@dinhtungdu](https://github.com/dinhtungdu), [@wkw](https://github.com/wkw), [@jeffpaul](https://github.com/jeffpaul), [@ivanlopez](https://github.com/ivanlopez)).
169
+ * **Fixed:** Ensure assets are enqueued on correct screen only (props [@kopepasah](https://github.com/kopepasah), [@dinhtungdu](https://github.com/dinhtungdu), [@paulschreiber](https://github.com/paulschreiber), [@n8dnx](https://github.com/n8dnx)).
170
+ * **Fixed:** Use correct variable for screen reader text (props [@dinhtungdu](https://github.com/dinhtungdu), [@lkraav](https://github.com/lkraav)).
171
+ * **Fixed:** Set the correct filter option value to `site_public` if `RSA_FORBID_RESTRICTION` is defined (props [@pabamato](https://github.com/pabamato), [@dinhtungdu](https://github.com/dinhtungdu)).
172
+ * **Fixed:** Prevent redirect loops when Redirect URL set on the same domain with or without Redirect to same path enabled (props [@Sidsector9](https://github.com/Sidsector9), [@faisal-alvi](https://github.com/faisal-alvi), [@cadic](https://github.com/cadic) via [#158](https://github.com/10up/restricted-site-access/pull/158)).
173
+ * **Fixed:** Undefined key "url" warning (props [@Sidsector9](https://github.com/Sidsector9)).
174
+ * **Fixed:** `Redirect to same path` setting screen-reader-text (props [@pedro-mendonca](https://github.com/pedro-mendonca)).
175
+ * **Fixed:** No loading of JS admin scripts on the network admin page (props [@Sidsector9](https://github.com/Sidsector9), [@dinhtungdu](https://github.com/dinhtungdu)).
176
+ * **Security:** Bump `websocket-extensions` from 0.1.3 to 0.1.4 (props [@dependabot](https://github.com/apps/dependabot)).
177
+ * **Security:** Bump `lodash` from 4.17.15 to 4.17.21 (props [@dependabot](https://github.com/apps/dependabot)).
178
+ * **Security:** Bump `rmccue/requests` from 1.7.0 to 1.8.0 (props [@dependabot](https://github.com/apps/dependabot)).
179
+ * **Security:** Bump `grunt` from 1.0.4 to 1.3.0 (props [@dependabot](https://github.com/apps/dependabot)).
180
+ * **Security:** Bump `path-parse` from 1.0.6 to 1.0.7 (props [@dependabot](https://github.com/apps/dependabot)).
181
+
182
  = 7.2.0 =
183
  * **Added:** Warn and confirm before network disabling the plugin (props [@pereirinha](profiles.wordpress.org/pereirinha), [@adamsilverstein](https://profiles.wordpress.org/adamsilverstein/))
184
  * **Fixed:** Ensure comments associated with IPs stay associated correctly (props [@adamsilverstein](https://profiles.wordpress.org/adamsilverstein/), [@ivankk](https://profiles.wordpress.org/ivankk/), [@helen](https://profiles.wordpress.org/helen/))
restricted_site_access.php CHANGED
@@ -1,13 +1,16 @@
1
  <?php // phpcs:disable WordPress.Files.FileName
2
  /**
3
- * Plugin Name: Restricted Site Access
4
- * Plugin URI: https://10up.com/plugins/restricted-site-access-wordpress/
5
- * Description: <strong>Limit access your site</strong> to visitors who are logged in or accessing the site from a set of specific IP addresses. Send restricted visitors to the log in page, redirect them, or display a message or page. <strong>Powerful control over redirection</strong>, including <strong>SEO friendly redirect headers</strong>. Great solution for Extranets, publicly hosted Intranets, or parallel development sites.
6
- * Version: 7.2.0
7
- * Author: Jake Goldman, 10up, Oomph
8
- * Author URI: https://10up.com
9
- * License: GPLv2 or later
10
- * Text Domain: restricted-site-access
 
 
 
11
  */
12
 
13
  define( 'RSA_VERSION', '7.2.0' );
@@ -100,7 +103,7 @@ class Restricted_Site_Access {
100
  public static function ajax_notice_dismiss() {
101
 
102
  // @codeCoverageIgnoreStart
103
- if ( ! defined( 'WP_TESTS_DOMAIN' ) ) {
104
  if ( ! check_ajax_referer( 'rsa_admin_nonce', 'nonce', false ) ) {
105
  wp_send_json_error();
106
  exit;
@@ -126,7 +129,7 @@ class Restricted_Site_Access {
126
  }
127
 
128
  // @codeCoverageIgnoreStart
129
- if ( ! defined( 'WP_TESTS_DOMAIN' ) ) {
130
  wp_send_json_success();
131
  }
132
  // @codeCoverageIgnoreEnd
@@ -215,7 +218,7 @@ class Restricted_Site_Access {
215
  /**
216
  * Populate the option with defaults.
217
  *
218
- * @param boolean $network Whther this is a network install. Default false.
219
  */
220
  public static function get_options( $network = false ) {
221
  $options = array();
@@ -308,15 +311,28 @@ class Restricted_Site_Access {
308
  $results = self::restrict_access_check( $wp );
309
 
310
  if ( is_array( $results ) && ! empty( $results ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
311
 
312
  // Don't redirect during unit tests.
313
- if ( ! empty( $results['url'] ) && ! defined( 'WP_TESTS_DOMAIN' ) ) {
314
  wp_redirect( $results['url'], $results['code'] ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
315
  die();
316
  }
317
 
318
  // Don't die during unit tests.
319
- if ( ! empty( $results['die_message'] ) && ! defined( 'WP_TESTS_DOMAIN' ) ) {
320
  wp_die( wp_kses_post( $results['die_message'] ), esc_html( $results['die_title'] ), array( 'response' => esc_html( $results['die_code'] ) ) );
321
  }
322
  }
@@ -332,6 +348,11 @@ class Restricted_Site_Access {
332
  self::$rsa_options = self::get_options();
333
  $is_restricted = self::is_restricted();
334
 
 
 
 
 
 
335
  // Check to see if it's _not_ restricted.
336
  if ( apply_filters( 'restricted_site_access_is_restricted', $is_restricted, $wp ) === false ) {
337
  return;
@@ -427,7 +448,16 @@ class Restricted_Site_Access {
427
  case 2:
428
  if ( ! empty( self::$rsa_options['redirect_url'] ) ) {
429
  if ( ! empty( self::$rsa_options['redirect_path'] ) ) {
430
- self::$rsa_options['redirect_url'] = untrailingslashit( self::$rsa_options['redirect_url'] ) . sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
 
 
 
 
 
 
 
 
 
431
  }
432
  break;
433
  }
@@ -712,6 +742,12 @@ class Restricted_Site_Access {
712
  * Enqueue Settings page scripts.
713
  */
714
  public static function enqueue_settings_script() {
 
 
 
 
 
 
715
  $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
716
  $folder = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'src/' : '';
717
 
@@ -722,6 +758,14 @@ class Restricted_Site_Access {
722
  RSA_VERSION,
723
  true
724
  );
 
 
 
 
 
 
 
 
725
  }
726
 
727
  /**
@@ -730,6 +774,10 @@ class Restricted_Site_Access {
730
  public static function enqueue_admin_script() {
731
  $current_screen = get_current_screen();
732
 
 
 
 
 
733
  $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
734
  $folder = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'src/' : '';
735
 
@@ -745,9 +793,8 @@ class Restricted_Site_Access {
745
  'rsa-admin',
746
  'rsaAdmin',
747
  array(
748
- 'nonce' => wp_create_nonce( 'rsa_admin_nonce' ),
749
- 'isNetworkWidePluginsPage' => $current_screen && 'plugins-network' === $current_screen->id,
750
- 'strings' => array(
751
  'confirm' => esc_html__( 'Network Disable Plugin', 'restricted-site-access' ),
752
  'cancel' => esc_html__( 'Cancel', 'restricted-site-access' ),
753
  'message' => esc_html__( 'I understand', 'restricted-site-access' ),
@@ -1167,7 +1214,8 @@ class Restricted_Site_Access {
1167
  // @codeCoverageIgnoreEnd
1168
  }
1169
  ?>
1170
- <fieldset><legend class="screen-reader-text"><span><?php esc_html( self::$rsa_options['redirect_path']['label'] ); ?></span></legend>
 
1171
  <label for="redirect_path">
1172
  <input type="checkbox" name="rsa_options[redirect_path]" value="1" id="redirect_path" class="rsa_redirect_field" <?php checked( self::$rsa_options['redirect_path'] ); ?> />
1173
  <?php esc_html_e( 'Send restricted visitor to same path (relative URL) at the new web address', 'restricted-site-access' ); ?></label>
@@ -1317,7 +1365,7 @@ class Restricted_Site_Access {
1317
 
1318
  // Check if constant disallowing restriction is defined.
1319
  if ( defined( 'RSA_FORBID_RESTRICTION' ) && RSA_FORBID_RESTRICTION === true ) {
1320
- $value = 1;
1321
  }
1322
 
1323
  // Check if constant forcing restriction is defined.
@@ -1464,6 +1512,7 @@ class Restricted_Site_Access {
1464
  public static function get_client_ip_address() {
1465
  $ip = '';
1466
  $headers = array(
 
1467
  'HTTP_CLIENT_IP',
1468
  'HTTP_X_FORWARDED_FOR',
1469
  'HTTP_X_FORWARDED',
@@ -1492,6 +1541,215 @@ class Restricted_Site_Access {
1492
 
1493
  return $ip;
1494
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1495
  }
1496
 
1497
  if ( ! defined( 'RSA_IS_NETWORK' ) ) {
1
  <?php // phpcs:disable WordPress.Files.FileName
2
  /**
3
+ * Plugin Name: Restricted Site Access
4
+ * Plugin URI: https://10up.com/plugins/restricted-site-access-wordpress/
5
+ * Description: <strong>Limit access your site</strong> to visitors who are logged in or accessing the site from a set of specific IP addresses. Send restricted visitors to the log in page, redirect them, or display a message or page. <strong>Powerful control over redirection</strong>, including <strong>SEO friendly redirect headers</strong>. Great solution for Extranets, publicly hosted Intranets, or parallel development sites.
6
+ * Version: 7.3.0
7
+ * Requires at least: 4.6
8
+ * Requires PHP:
9
+ * Author: Jake Goldman, 10up, Oomph
10
+ * Author URI: https://10up.com
11
+ * License: GPL v2 or later
12
+ * License URI: https://www.gnu.org/licenses/gpl-2.0.html
13
+ * Text Domain: restricted-site-access
14
  */
15
 
16
  define( 'RSA_VERSION', '7.2.0' );
103
  public static function ajax_notice_dismiss() {
104
 
105
  // @codeCoverageIgnoreStart
106
+ if ( ! defined( 'PHP_UNIT_TESTS_ENV' ) ) {
107
  if ( ! check_ajax_referer( 'rsa_admin_nonce', 'nonce', false ) ) {
108
  wp_send_json_error();
109
  exit;
129
  }
130
 
131
  // @codeCoverageIgnoreStart
132
+ if ( ! defined( 'PHP_UNIT_TESTS_ENV' ) ) {
133
  wp_send_json_success();
134
  }
135
  // @codeCoverageIgnoreEnd
218
  /**
219
  * Populate the option with defaults.
220
  *
221
+ * @param boolean $network Whether this is a network install. Default false.
222
  */
223
  public static function get_options( $network = false ) {
224
  $options = array();
311
  $results = self::restrict_access_check( $wp );
312
 
313
  if ( is_array( $results ) && ! empty( $results ) ) {
314
+ /**
315
+ * This conditional prevents a redirect loop if the redirect URL
316
+ * belongs to the same domain.
317
+ */
318
+ if ( 2 === self::$rsa_options['approach'] ) {
319
+ $redirect_url_without_scheme = trailingslashit( preg_replace( '(^https?://)', '', $results['url'] ) );
320
+ $current_url_without_scheme = trailingslashit( preg_replace( '(^https?://)', '', home_url( $wp->request ) ) );
321
+ $current_url_path = trailingslashit( wp_parse_url( home_url( $wp->request ), PHP_URL_PATH ) );
322
+
323
+ if ( ( $current_url_path === $redirect_url_without_scheme ) || ( $redirect_url_without_scheme === $current_url_without_scheme ) ) {
324
+ return;
325
+ }
326
+ }
327
 
328
  // Don't redirect during unit tests.
329
+ if ( ! empty( $results['url'] ) && ! defined( 'PHP_UNIT_TESTS_ENV' ) ) {
330
  wp_redirect( $results['url'], $results['code'] ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
331
  die();
332
  }
333
 
334
  // Don't die during unit tests.
335
+ if ( ! empty( $results['die_message'] ) && ! defined( 'PHP_UNIT_TESTS_ENV' ) ) {
336
  wp_die( wp_kses_post( $results['die_message'] ), esc_html( $results['die_title'] ), array( 'response' => esc_html( $results['die_code'] ) ) );
337
  }
338
  }
348
  self::$rsa_options = self::get_options();
349
  $is_restricted = self::is_restricted();
350
 
351
+ // Check to see if we're activating new user.
352
+ if ( 'wp-activate.php' === $wp->request ) {
353
+ return;
354
+ }
355
+
356
  // Check to see if it's _not_ restricted.
357
  if ( apply_filters( 'restricted_site_access_is_restricted', $is_restricted, $wp ) === false ) {
358
  return;
448
  case 2:
449
  if ( ! empty( self::$rsa_options['redirect_url'] ) ) {
450
  if ( ! empty( self::$rsa_options['redirect_path'] ) ) {
451
+ $redirect_url_domain = wp_parse_url( self::$rsa_options['redirect_url'], PHP_URL_HOST );
452
+ $current_url_domain = wp_parse_url( home_url( $wp->request ), PHP_URL_HOST );
453
+
454
+ /**
455
+ * This conditional prevents a redirect loop if the redirect URL
456
+ * belongs to the same domain.
457
+ */
458
+ if ( ! empty( $redirect_url_domain ) && $redirect_url_domain !== $current_url_domain ) {
459
+ self::$rsa_options['redirect_url'] = untrailingslashit( self::$rsa_options['redirect_url'] ) . sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
460
+ }
461
  }
462
  break;
463
  }
742
  * Enqueue Settings page scripts.
743
  */
744
  public static function enqueue_settings_script() {
745
+ $current_screen = get_current_screen();
746
+
747
+ if ( ! empty( $current_screen ) && ( 'options-reading' !== $current_screen->id && 'settings-network' !== $current_screen->id ) ) {
748
+ return;
749
+ }
750
+
751
  $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
752
  $folder = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'src/' : '';
753
 
758
  RSA_VERSION,
759
  true
760
  );
761
+
762
+ wp_localize_script(
763
+ 'rsa-settings',
764
+ 'rsaSettings',
765
+ array(
766
+ 'nonce' => wp_create_nonce( 'rsa_admin_nonce' ),
767
+ )
768
+ );
769
  }
770
 
771
  /**
774
  public static function enqueue_admin_script() {
775
  $current_screen = get_current_screen();
776
 
777
+ if ( ! empty( $current_screen ) && ! in_array( $current_screen->id, array( 'plugins-network', 'options-reading' ), true ) ) {
778
+ return;
779
+ }
780
+
781
  $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
782
  $folder = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'src/' : '';
783
 
793
  'rsa-admin',
794
  'rsaAdmin',
795
  array(
796
+ 'nonce' => wp_create_nonce( 'rsa_admin_nonce' ),
797
+ 'strings' => array(
 
798
  'confirm' => esc_html__( 'Network Disable Plugin', 'restricted-site-access' ),
799
  'cancel' => esc_html__( 'Cancel', 'restricted-site-access' ),
800
  'message' => esc_html__( 'I understand', 'restricted-site-access' ),
1214
  // @codeCoverageIgnoreEnd
1215
  }
1216
  ?>
1217
+ <fieldset>
1218
+ <legend class="screen-reader-text"><span><?php esc_html_e( 'Redirect to same path', 'restricted-site-access' ); ?></span></legend>
1219
  <label for="redirect_path">
1220
  <input type="checkbox" name="rsa_options[redirect_path]" value="1" id="redirect_path" class="rsa_redirect_field" <?php checked( self::$rsa_options['redirect_path'] ); ?> />
1221
  <?php esc_html_e( 'Send restricted visitor to same path (relative URL) at the new web address', 'restricted-site-access' ); ?></label>
1365
 
1366
  // Check if constant disallowing restriction is defined.
1367
  if ( defined( 'RSA_FORBID_RESTRICTION' ) && RSA_FORBID_RESTRICTION === true ) {
1368
+ $value = 0;
1369
  }
1370
 
1371
  // Check if constant forcing restriction is defined.
1512
  public static function get_client_ip_address() {
1513
  $ip = '';
1514
  $headers = array(
1515
+ 'HTTP_CF_CONNECTING_IP',
1516
  'HTTP_CLIENT_IP',
1517
  'HTTP_X_FORWARDED_FOR',
1518
  'HTTP_X_FORWARDED',
1541
 
1542
  return $ip;
1543
  }
1544
+
1545
+ /**
1546
+ * Get IPs programmatically
1547
+ *
1548
+ * @param bool $include_config Whether to include the config file IPs. Default true.
1549
+ * @param bool $include_labels Whether to include the comments. Default false.
1550
+ * @return array
1551
+ */
1552
+ public static function get_ips( $include_config = true, $include_labels = false ) {
1553
+ self::$rsa_options = self::get_options();
1554
+ $current_ips = (array) self::$rsa_options['allowed'];
1555
+ $config_ips = array();
1556
+
1557
+ if ( $include_labels ) {
1558
+ $labels = (array) self::$rsa_options['comment'];
1559
+ $current_ips = array_combine( $labels, $current_ips );
1560
+ }
1561
+
1562
+ if ( $include_config ) {
1563
+ $config_ips = self::get_config_ips();
1564
+ }
1565
+
1566
+ $result = array_unique( array_merge( $current_ips, $config_ips ) );
1567
+
1568
+ return $result;
1569
+ }
1570
+
1571
+ /**
1572
+ * Add IPs programmatically
1573
+ *
1574
+ * The $ip_list can either contain a single IP via string, IP addresses in an array, e.g.
1575
+ * '192.168.0.1'
1576
+ * array( '192.168.0.1', '192.168.0.2' )
1577
+ * or labels can be used as array indices
1578
+ * array( 'labelone' => '192.168.0.1', 'labeltwo' => '192.168.0.2' )
1579
+ *
1580
+ * @param string|array $ips list of IPs to add.
1581
+ */
1582
+ public static function add_ips( $ips ) {
1583
+ if ( is_null( self::$rsa_options ) ) {
1584
+ if ( is_null( self::$fields ) ) {
1585
+ self::populate_fields_array();
1586
+ }
1587
+ self::$rsa_options = self::get_options();
1588
+ }
1589
+ $ips = (array) $ips;
1590
+ $allowed_ips = isset( self::$rsa_options['allowed'] ) ? (array) self::$rsa_options['allowed'] : array();
1591
+ $comments = isset( self::$rsa_options['comment'] ) ? (array) self::$rsa_options['comment'] : array();
1592
+ $i = 0;
1593
+ foreach ( $ips as $label => $ip ) {
1594
+ if ( ! in_array( $ip, $allowed_ips, true ) && self::is_ip( $ip ) ) {
1595
+ $allowed_ips[] = $ip;
1596
+ $comments[] = $i !== $label ? sanitize_text_field( $label ) : '';
1597
+ }
1598
+ $i++;
1599
+ }
1600
+
1601
+ if ( self::$rsa_options['allowed'] !== $allowed_ips ) {
1602
+ self::$rsa_options['allowed'] = $allowed_ips;
1603
+ self::$rsa_options['comment'] = $comments;
1604
+ update_option( 'rsa_options', self::sanitize_options( self::$rsa_options ) );
1605
+ }
1606
+ }
1607
+
1608
+ /**
1609
+ * Update an existing IP address or label.
1610
+ *
1611
+ * @param boolean|string $ip The IP address that needs to be updated.
1612
+ * @param boolean|string $new_ip The new IP address that will replace $ip.
1613
+ * @param boolean|string $new_label The new label that will replace the label of $ip.
1614
+ *
1615
+ * @return integer
1616
+ */
1617
+ public static function update_ip_or_label( $ip = false, $new_ip = false, $new_label = false ) {
1618
+ if ( is_null( self::$rsa_options ) ) {
1619
+ if ( is_null( self::$fields ) ) {
1620
+ self::populate_fields_array();
1621
+ }
1622
+ self::$rsa_options = self::get_options();
1623
+ }
1624
+
1625
+ if ( false === $ip ) {
1626
+ return new WP_Error( 'ip_argument_not_found', __( 'IP argument not found.', 'restricted-site-access' ) );
1627
+ }
1628
+
1629
+ $allowed_ips = (array) self::$rsa_options['allowed'];
1630
+ $comments = (array) self::$rsa_options['comment'];
1631
+ $ip_index = -1;
1632
+
1633
+ /**
1634
+ * Get the index of the ip address that needs
1635
+ * to be updated.
1636
+ */
1637
+ foreach ( $allowed_ips as $index => $current_ip ) {
1638
+ if ( $current_ip === $ip ) {
1639
+ $ip_index = $index;
1640
+ break;
1641
+ }
1642
+ }
1643
+
1644
+ /**
1645
+ * Return if `$ip` not found.
1646
+ */
1647
+ if ( -1 === $ip_index ) {
1648
+ return new WP_Error( 'ip_address_does_not_exist', __( "The IP address doesn't exist.", 'restricted-site-access' ) );
1649
+ }
1650
+
1651
+ /**
1652
+ * Return if the format of `$new_ip` is invalid.
1653
+ */
1654
+ if ( false !== $new_ip && ! self::is_ip( $new_ip ) ) {
1655
+ return new WP_Error( 'ip_address_is_invalid', __( 'The new IP address format is incorrect.', 'restricted-site-access' ) );
1656
+ }
1657
+
1658
+ /**
1659
+ * Return status code 2 if `$ip` doesn't exist in
1660
+ * `$allowed_ips` array.
1661
+ */
1662
+ if ( in_array( $new_ip, $allowed_ips, true ) ) {
1663
+ return new WP_Error( 'ip_address_already_exists', __( 'The IP address already exists.', 'restricted-site-access' ) );
1664
+ }
1665
+
1666
+ /**
1667
+ * Add `$new_ip` to the `$allowed_ips` array.
1668
+ */
1669
+ if ( false !== $new_ip ) {
1670
+ $allowed_ips[ $ip_index ] = $new_ip;
1671
+ }
1672
+
1673
+ /**
1674
+ * Add `$new_label` to the `$comments` array.
1675
+ */
1676
+ if ( false !== $new_label ) {
1677
+ $comments[ $ip_index ] = $new_label;
1678
+ }
1679
+
1680
+ self::$rsa_options['allowed'] = $allowed_ips;
1681
+ self::$rsa_options['comment'] = $comments;
1682
+ update_option( 'rsa_options', self::sanitize_options( self::$rsa_options ) );
1683
+
1684
+ return true;
1685
+ }
1686
+
1687
+ /**
1688
+ * Remove IPs programmatically
1689
+ *
1690
+ * The $ip_list can either contain a single IP via string, IP addresses in an array, e.g.
1691
+ * '192.168.0.1'
1692
+ * array( '192.168.0.1', '192.168.0.2' )
1693
+ *
1694
+ * @param string|array $ips list of IPs to remove.
1695
+ */
1696
+ public static function remove_ips( $ips ) {
1697
+ if ( is_null( self::$rsa_options ) ) {
1698
+ if ( is_null( self::$fields ) ) {
1699
+ self::populate_fields_array();
1700
+ }
1701
+ }
1702
+ self::$rsa_options = self::get_options();
1703
+
1704
+ $ips = (array) $ips;
1705
+ $allowed_ips = (array) self::$rsa_options['allowed'];
1706
+ $comments = (array) self::$rsa_options['comment'];
1707
+ $found_ips = array_intersect( $allowed_ips, $ips );
1708
+ foreach ( array_keys( $found_ips ) as $found_ip_key ) {
1709
+ unset( $comments[ $found_ip_key ] );
1710
+ unset( $allowed_ips[ $found_ip_key ] );
1711
+ }
1712
+ $comments = array_values( $comments );
1713
+ $allowed_ips = array_values( $allowed_ips );
1714
+
1715
+ if ( self::$rsa_options['allowed'] !== $allowed_ips || self::$rsa_options['comment'] !== $comments ) {
1716
+ self::$rsa_options['allowed'] = $allowed_ips;
1717
+ self::$rsa_options['comment'] = $comments;
1718
+ update_option( 'rsa_options', self::sanitize_options( self::$rsa_options ) );
1719
+ }
1720
+ }
1721
+
1722
+ /**
1723
+ * Set IPs programmatically
1724
+ * Same syntax as add_ips(), but this replaces existing IPs and comments.
1725
+ *
1726
+ * @param string|array $ips list of IPs to set as default IPs.
1727
+ */
1728
+ public static function set_ips( $ips ) {
1729
+ if ( is_null( self::$rsa_options ) ) {
1730
+ if ( is_null( self::$fields ) ) {
1731
+ self::populate_fields_array();
1732
+ }
1733
+ self::$rsa_options = self::get_options();
1734
+ }
1735
+ $ips = (array) $ips;
1736
+ $allowed_ips = array();
1737
+ $comments = array();
1738
+ $i = 0;
1739
+ foreach ( $ips as $label => $ip ) {
1740
+ if ( ! in_array( $ip, $allowed_ips, true ) && self::is_ip( $ip ) ) {
1741
+ $allowed_ips[] = $ip;
1742
+ $comments[] = $i !== $label ? sanitize_text_field( $label ) : '';
1743
+ }
1744
+ $i++;
1745
+ }
1746
+
1747
+ if ( self::$rsa_options['allowed'] !== $allowed_ips ) {
1748
+ self::$rsa_options['allowed'] = $allowed_ips;
1749
+ self::$rsa_options['comment'] = $comments;
1750
+ update_option( 'rsa_options', self::sanitize_options( self::$rsa_options ) );
1751
+ }
1752
+ }
1753
  }
1754
 
1755
  if ( ! defined( 'RSA_IS_NETWORK' ) ) {
wp-cli.php CHANGED
@@ -137,9 +137,9 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
137
  WP_CLI::success(
138
  sprintf(
139
  /* translators: %s: What the user is updating: "Site" or "Network". */
140
- __( '%s restrictions disabled.', 'restricted-site-access' )
141
- ),
142
- $this->update_text()
143
  );
144
  return; // Exit.
145
  }
@@ -306,6 +306,9 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
306
  * [--exclude-config]
307
  * : Don't include IPs from the configuration file.
308
  *
 
 
 
309
  * [--format=<format>]
310
  * : Render output in a particular format.
311
  * ---
@@ -334,21 +337,29 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
334
  public function ip_list( $args, $assoc_args ) {
335
  $this->setup( $args, $assoc_args );
336
 
337
- $no_config = WP_CLI\Utils\get_flag_value( $assoc_args, 'exclude-config', false );
338
- $ips = $this->get_current_ips( ! $no_config );
339
- $items = array();
 
 
340
 
341
  if ( 0 === count( $ips ) ) {
342
  WP_CLI::line( __( 'No IP addresses configured.', 'restricted-site-access' ) );
343
  return;
344
  }
345
 
346
- foreach ( $ips as $ip ) {
347
- $items[] = compact( 'ip' );
 
 
 
 
 
 
348
  }
349
 
350
  $format = WP_CLI\Utils\get_flag_value( $assoc_args, 'format', 'table' );
351
- WP_CLI\Utils\format_items( $format, $items, array( 'ip' ) );
352
  }
353
 
354
  /**
@@ -368,6 +379,10 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
368
  * $ wp rsa ip-add 192.0.0.1
369
  * Success: Added 192.0.0.1 to site whitelist.
370
  *
 
 
 
 
371
  * @subcommand ip-add
372
  *
373
  * @param array $args List of IPs to whitelist.
@@ -376,16 +391,89 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
376
  public function ip_add( $args, $assoc_args ) {
377
  $this->setup( $args, $assoc_args );
378
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  // Validate the IP addresses.
380
- $valid_ips = array_filter( $args, [ 'Restricted_Site_Access', 'is_ip' ] );
381
  if ( 0 === count( $valid_ips ) ) {
382
  WP_CLI::error( __( 'No valid IP addresses provided.', 'restricted-site-access' ) );
383
  }
384
 
385
- // Get the new IPs.
386
- $current_ips = $this->get_current_ips();
387
- $new_ips = array_diff( $valid_ips, $current_ips );
388
-
389
  if ( 0 === count( $new_ips ) ) {
390
  // Only show a warning as this may be an automated process.
391
  WP_CLI::warning(
@@ -398,9 +486,19 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
398
  return;
399
  }
400
 
 
 
 
 
 
 
 
 
 
 
 
401
  // Updates the option.
402
- $options['allowed'] = array_merge( $this->get_current_ips( false ), $new_ips );
403
- $new_options = $this->update_options( $options );
404
 
405
  WP_CLI::success(
406
  sprintf(
@@ -415,7 +513,7 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
415
  sprintf(
416
  /* translators: %2$s: IP addresses. %1$s: Context: "Site" or "Network". */
417
  __( 'Current %2$s whitelisted IPs are: %1$s', 'restricted-site-access' ),
418
- implode( ', ', $new_options['allowed'] ),
419
  $this->update_text( false )
420
  )
421
  );
@@ -447,7 +545,7 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
447
  $this->setup( $args, $assoc_args );
448
 
449
  // Validate the IP addresses.
450
- $valid_ips = array_filter( $args, [ 'Restricted_Site_Access', 'is_ip' ] );
451
  if ( 0 === count( $valid_ips ) ) {
452
  WP_CLI::error( __( 'No valid IP addresses provided.', 'restricted-site-access' ) );
453
  }
@@ -469,8 +567,7 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
469
  }
470
 
471
  // Updates the option.
472
- $options['allowed'] = array_diff( $current_ips, $removed_ips );
473
- $new_options = $this->update_options( $options );
474
 
475
  WP_CLI::success(
476
  sprintf(
@@ -485,12 +582,76 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
485
  sprintf(
486
  /* translators: %2$s: IP addresses. %1$s: Context: "Site" or "Network". */
487
  __( 'Current %2$s whitelisted IPs are: %1$s', 'restricted-site-access' ),
488
- implode( ', ', $new_options['allowed'] ),
489
  $this->update_text( false )
490
  )
491
  );
492
  }
493
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
  /**
495
  * Sets list of IPs to whitelist. Overwrites current settings.
496
  *
@@ -517,20 +678,19 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
517
  $this->setup( $args, $assoc_args );
518
 
519
  // Validate the IP addresses.
520
- $valid_ips = array_filter( $args, [ 'Restricted_Site_Access', 'is_ip' ] );
521
  if ( 0 === count( $valid_ips ) ) {
522
  WP_CLI::error( __( 'No valid IP addresses provided.', 'restricted-site-access' ) );
523
  }
524
 
525
  // Updates the option.
526
- $options['allowed'] = $valid_ips;
527
- $new_options = $this->update_options( $options );
528
 
529
  WP_CLI::success(
530
  sprintf(
531
  /* translators: %2$s: IPs to whitelist, %1$s: Context: "Site" or "Network". */
532
  __( 'Set %2$s IP whitelist to %1$s.', 'restricted-site-access' ),
533
- implode( ', ', $new_options['allowed'] ),
534
  $this->update_text( false )
535
  )
536
  );
@@ -543,7 +703,7 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
543
  * @param array $assoc_args Array with associative arguments.
544
  * @return void
545
  */
546
- private function setup( $args = [], $assoc_args = [] ) {
547
  $this->args = $args;
548
  $this->assoc_args = $assoc_args;
549
 
@@ -568,18 +728,11 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
568
  * Gets all current IPs, optionally including config IPs.
569
  *
570
  * @param bool $include_config Whether to include the config file IPs. Default true.
 
571
  * @return array
572
  */
573
- private function get_current_ips( $include_config = true ) {
574
- $options = $this->get_options();
575
- $current_ips = empty( $options['allowed'] ) ? array() : $options['allowed'];
576
- $config_ips = array();
577
-
578
- if ( $include_config ) {
579
- $config_ips = Restricted_Site_Access::get_config_ips();
580
- }
581
-
582
- return array_unique( array_merge( $current_ips, $config_ips ) );
583
  }
584
 
585
  /**
137
  WP_CLI::success(
138
  sprintf(
139
  /* translators: %s: What the user is updating: "Site" or "Network". */
140
+ __( '%s restrictions disabled.', 'restricted-site-access' ),
141
+ $this->update_text()
142
+ )
143
  );
144
  return; // Exit.
145
  }
306
  * [--exclude-config]
307
  * : Don't include IPs from the configuration file.
308
  *
309
+ * [--include-labels]
310
+ * : Include labels.
311
+ *
312
  * [--format=<format>]
313
  * : Render output in a particular format.
314
  * ---
337
  public function ip_list( $args, $assoc_args ) {
338
  $this->setup( $args, $assoc_args );
339
 
340
+ $show_labels = WP_CLI\Utils\get_flag_value( $assoc_args, 'include-labels', false );
341
+ $no_config = WP_CLI\Utils\get_flag_value( $assoc_args, 'exclude-config', false );
342
+ $ips = $this->get_current_ips( ! $no_config, $show_labels );
343
+ $items = array();
344
+ $fields = $show_labels ? array( 'ip', 'label' ) : array( 'ip' );
345
 
346
  if ( 0 === count( $ips ) ) {
347
  WP_CLI::line( __( 'No IP addresses configured.', 'restricted-site-access' ) );
348
  return;
349
  }
350
 
351
+ if ( $show_labels ) {
352
+ foreach ( $ips as $label => $ip ) {
353
+ $items[] = compact( 'ip', 'label' );
354
+ }
355
+ } else {
356
+ foreach ( $ips as $ip ) {
357
+ $items[] = compact( 'ip' );
358
+ }
359
  }
360
 
361
  $format = WP_CLI\Utils\get_flag_value( $assoc_args, 'format', 'table' );
362
+ WP_CLI\Utils\format_items( $format, $items, $fields );
363
  }
364
 
365
  /**
379
  * $ wp rsa ip-add 192.0.0.1
380
  * Success: Added 192.0.0.1 to site whitelist.
381
  *
382
+ * # Adds 8.8.8.8 1.1.1.1 with labels Google and Cloudflare.
383
+ * $ wp rsa ip-add 8.8.8.8=Google 1.1.1.1=Cloudflare
384
+ * Success: Added 8.8.8.8, 1.1.1.1 to site whitelist.
385
+ *
386
  * @subcommand ip-add
387
  *
388
  * @param array $args List of IPs to whitelist.
391
  public function ip_add( $args, $assoc_args ) {
392
  $this->setup( $args, $assoc_args );
393
 
394
+ /**
395
+ * The input arguments can be of the form:
396
+ * wp rsa ip-add 8.8.8.8=Google 9.9.9.9 1.1.1.1=Cloudflare.
397
+ *
398
+ * Some input IP addresses may be provided with a label while
399
+ * other might not.
400
+ *
401
+ * We will normalise the input as:
402
+ * array(
403
+ * array(
404
+ * 'key' => '8.8.8.8',
405
+ * 'label' => 'Google'
406
+ * ),
407
+ * array(
408
+ * 'key' => '9.9.9.9',
409
+ * 'label' => ''
410
+ * ),
411
+ * array(
412
+ * 'key' => '1.1.1.1',
413
+ * 'label' => 'Cloudflare'
414
+ * ),
415
+ * )
416
+ */
417
+ $ips_and_labels_array = array();
418
+ foreach ( $args as $index => $item ) {
419
+ $fragments = explode( '=', $item );
420
+ /**
421
+ * If the IP doesn't have a corressponding label,
422
+ * then set label to '[null]:x', where 'x' is an
423
+ * integer.
424
+ */
425
+ if ( ! isset( $fragments[1] ) ) {
426
+ $fragments[1] = '';
427
+ }
428
+
429
+ $structure_ip_label_array = array(
430
+ 'ip' => $fragments[0],
431
+ 'label' => $fragments[1],
432
+ );
433
+
434
+ $ips_and_labels_array[] = $structure_ip_label_array;
435
+ }
436
+
437
+ /**
438
+ * Get all whitelisted IPs saved in DB.
439
+ */
440
+ $current_ips = $this->get_current_ips();
441
+
442
+ /**
443
+ * This will only hold those input IP addresses
444
+ * which are not already whitelisted.
445
+ */
446
+ $filtered_ips_and_labels = array();
447
+
448
+ /**
449
+ * A simple for loop to filter the input IP addresses.
450
+ */
451
+ foreach ( $ips_and_labels_array as $ip_label_pair ) {
452
+ if ( ! in_array( $ip_label_pair['ip'], $current_ips, true ) ) {
453
+ $filtered_ips_and_labels[] = array(
454
+ 'ip' => $ip_label_pair['ip'],
455
+ 'label' => $ip_label_pair['label'],
456
+ );
457
+ }
458
+ }
459
+
460
+ /**
461
+ * Extract all IP address from the filtered array
462
+ * as an indexed array.
463
+ */
464
+ $new_ips = array_map(
465
+ function( $ip_label_pair ) {
466
+ return $ip_label_pair['ip'];
467
+ },
468
+ $filtered_ips_and_labels
469
+ );
470
+
471
  // Validate the IP addresses.
472
+ $valid_ips = array_filter( $new_ips, array( 'Restricted_Site_Access', 'is_ip' ) );
473
  if ( 0 === count( $valid_ips ) ) {
474
  WP_CLI::error( __( 'No valid IP addresses provided.', 'restricted-site-access' ) );
475
  }
476
 
 
 
 
 
477
  if ( 0 === count( $new_ips ) ) {
478
  // Only show a warning as this may be an automated process.
479
  WP_CLI::warning(
486
  return;
487
  }
488
 
489
+ $ips_with_label = array();
490
+ $ips_without_label = array();
491
+
492
+ foreach ( $filtered_ips_and_labels as $ip_label_pair ) {
493
+ if ( empty( $ip_label_pair['label'] ) ) {
494
+ $ips_without_label[] = $ip_label_pair['ip'];
495
+ } else {
496
+ $ips_with_label[ $ip_label_pair['label'] ] = $ip_label_pair['ip'];
497
+ }
498
+ }
499
+
500
  // Updates the option.
501
+ Restricted_Site_Access::add_ips( array_merge( $ips_without_label, $ips_with_label ) );
 
502
 
503
  WP_CLI::success(
504
  sprintf(
513
  sprintf(
514
  /* translators: %2$s: IP addresses. %1$s: Context: "Site" or "Network". */
515
  __( 'Current %2$s whitelisted IPs are: %1$s', 'restricted-site-access' ),
516
+ implode( ', ', Restricted_Site_Access::get_ips() ),
517
  $this->update_text( false )
518
  )
519
  );
545
  $this->setup( $args, $assoc_args );
546
 
547
  // Validate the IP addresses.
548
+ $valid_ips = array_filter( $args, array( 'Restricted_Site_Access', 'is_ip' ) );
549
  if ( 0 === count( $valid_ips ) ) {
550
  WP_CLI::error( __( 'No valid IP addresses provided.', 'restricted-site-access' ) );
551
  }
567
  }
568
 
569
  // Updates the option.
570
+ Restricted_Site_Access::remove_ips( $removed_ips );
 
571
 
572
  WP_CLI::success(
573
  sprintf(
582
  sprintf(
583
  /* translators: %2$s: IP addresses. %1$s: Context: "Site" or "Network". */
584
  __( 'Current %2$s whitelisted IPs are: %1$s', 'restricted-site-access' ),
585
+ implode( ', ', Restricted_Site_Access::get_ips() ),
586
  $this->update_text( false )
587
  )
588
  );
589
  }
590
 
591
+ /**
592
+ * Used to update an existing IP address or to
593
+ * update the label of an existing IP address.
594
+ *
595
+ * ## OPTIONS
596
+ *
597
+ * <ip>
598
+ * : IP address to update.
599
+ *
600
+ * [--new-ip]
601
+ * : The IP address to replace with.
602
+ *
603
+ * [--new-label]
604
+ * : The new label for the IP address.
605
+ *
606
+ * [--network]
607
+ * : Multisite only. Sets configuration for the network as a whole.
608
+ *
609
+ * ## EXAMPLES
610
+ *
611
+ * # Update the label of IP 192.0.0.1 to "New label"
612
+ * $ wp rsa ip-update 192.0.0.1 --new-label="New label"
613
+ * Success: Fields correctly updated.
614
+ *
615
+ * # Replace the IP IP 192.0.0.1 to 200.1.2.3
616
+ * $ wp rsa ip-update 192.0.0.1 --new-ip=200.1.2.3
617
+ * Success: Fields correctly updated.
618
+ *
619
+ * @subcommand ip-update
620
+ *
621
+ * @param array $args IP to update.
622
+ * @param array $assoc_args Optional flags.
623
+ */
624
+ public function ip_update( $args, $assoc_args ) {
625
+ $this->setup( $args, $assoc_args );
626
+
627
+ if ( 0 === count( $assoc_args ) ) {
628
+ \WP_CLI::error( __( 'Provide the arguments to update.', 'restricted-site-access' ) );
629
+ }
630
+
631
+ $valid_ips = array_filter( $args, array( 'Restricted_Site_Access', 'is_ip' ) );
632
+
633
+ if ( 0 === count( $valid_ips ) ) {
634
+ WP_CLI::error( __( 'No valid IP addresses provided.', 'restricted-site-access' ) );
635
+ }
636
+
637
+ $new_ip = \WP_CLI\Utils\get_flag_value( $assoc_args, 'new-ip', false );
638
+ $new_label = \WP_CLI\Utils\get_flag_value( $assoc_args, 'new-label', false );
639
+
640
+ $update_status = Restricted_Site_Access::update_ip_or_label( $valid_ips[0], $new_ip, $new_label );
641
+
642
+ if ( is_wp_error( $update_status ) ) {
643
+ WP_CLI::error(
644
+ sprintf(
645
+ '%s (%s)',
646
+ $update_status->get_error_message(),
647
+ $update_status->get_error_code()
648
+ )
649
+ );
650
+ }
651
+
652
+ WP_CLI::success( __( 'IP updated.', 'restricted-site-access' ) );
653
+ }
654
+
655
  /**
656
  * Sets list of IPs to whitelist. Overwrites current settings.
657
  *
678
  $this->setup( $args, $assoc_args );
679
 
680
  // Validate the IP addresses.
681
+ $valid_ips = array_filter( $args, array( 'Restricted_Site_Access', 'is_ip' ) );
682
  if ( 0 === count( $valid_ips ) ) {
683
  WP_CLI::error( __( 'No valid IP addresses provided.', 'restricted-site-access' ) );
684
  }
685
 
686
  // Updates the option.
687
+ Restricted_Site_Access::set_ips( $valid_ips );
 
688
 
689
  WP_CLI::success(
690
  sprintf(
691
  /* translators: %2$s: IPs to whitelist, %1$s: Context: "Site" or "Network". */
692
  __( 'Set %2$s IP whitelist to %1$s.', 'restricted-site-access' ),
693
+ implode( ', ', Restricted_Site_Access::get_ips() ),
694
  $this->update_text( false )
695
  )
696
  );
703
  * @param array $assoc_args Array with associative arguments.
704
  * @return void
705
  */
706
+ private function setup( $args = array(), $assoc_args = array() ) {
707
  $this->args = $args;
708
  $this->assoc_args = $assoc_args;
709
 
728
  * Gets all current IPs, optionally including config IPs.
729
  *
730
  * @param bool $include_config Whether to include the config file IPs. Default true.
731
+ * @param bool $include_labels Whether to include the comments. Default false.
732
  * @return array
733
  */
734
+ private function get_current_ips( $include_config = true, $include_labels = false ) {
735
+ return Restricted_Site_Access::get_ips( $include_config, $include_labels );
 
 
 
 
 
 
 
 
736
  }
737
 
738
  /**