Skip to content

Commit 8f8691c

Browse files
committed
Merge remote-tracking branch 'origin/2.x' into 2.x
# Conflicts: # README.md
2 parents 8968a17 + e4a78f3 commit 8f8691c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2549
-28
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Twilio 1.2.0
2+
===============
3+
- Add Time-based One Time Password (TOTP)
4+
- Updated examples
5+
16
Twilio 1.1.0
27
===============
38
- Add TwilioValidatePhone snippet to validate phone number

README.md

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
# Twilio
1+
# Twilio Verify
22

3-
## Sample Registration page
3+
Twilio is a verification service that allows you to send a code to a user's phone or use a time-based one time password to verify their identity. You can find more information on Twilio at [https://www.twilio.com/](https://www.twilio.com/). This is not a free service, so you will need to sign up for a Twilio account. Each successful verification will cost you $0.05, so this is something to consider before implementing.
4+
5+
## Phone Verification
6+
7+
### Sample Registration page
48

59
```html
610
<link
@@ -66,7 +70,7 @@
6670
</script>
6771
```
6872

69-
## Sample Activation Page (&twilioActivationResourceId)
73+
### Sample Activation Page (&twilioActivationResourceId)
7074

7175
```html
7276
[[!TwilioGetPhone]]
@@ -108,3 +112,67 @@ Phone: [[!+twilio.phone]]
108112
</div>
109113
</form>
110114
```
115+
116+
## Time-based One Time Password
117+
118+
### Sample Challenge Page
119+
120+
Create a challenge page and set the system setting `twilio.totp_challenge_page` to the page ID.
121+
122+
```html
123+
[[!FormIt?
124+
&hooks=`TwilioTOTPChallenge,TwilioVerify`
125+
&twilioRedirect=`4` // ID of the page to redirect to after verification
126+
&twilioFactorType=`totp`
127+
&validate=`code:required`
128+
]]
129+
<form method="post">
130+
<label>
131+
Enter 2FA Code
132+
<input name="code" value="" />
133+
</label>
134+
<button type="submit">Submit</button>
135+
</form>
136+
```
137+
138+
### Sample Create/Reset Token Page
139+
140+
Create a page with the following content:
141+
142+
```html
143+
[[TwilioTOTPCreate?twilioRedirect=`4`]]
144+
```
145+
146+
### Sample Profile Page
147+
148+
```html
149+
[[!TwilioTOTPqr]]
150+
151+
[[!+twilio.qr:ne=``:then=`
152+
<img src="[[!+twilio.qr]]" />
153+
<p>Secret [[!+twilio.secret]]</p>
154+
[[!+twilio.status:is=`unverified`:then=`
155+
<p><a href="[[~5]]"><strong>Verify 2FA Code Before Next Login</strong></a></p> <!-- link to challenge page -->
156+
`:else=``]]
157+
<p><a href="[[~6]]">Refresh 2FA</a><br /> <!-- link to create / refresh page -->
158+
<a href="[[~6?status=`disable_totp`]]">Disable 2FA</a></p>
159+
`:else=`
160+
<a href="[[~6]]">Enable 2FA</a>
161+
`]]
162+
```
163+
164+
## System Settings
165+
166+
| key | description |
167+
| --- |------------------------------------------------------------------------------------------------------------|
168+
| twilio.account_sid | Twilio Account SID - Found under Account Info here https://console.twilio.com/ |
169+
| twilio.account_token | Twilio Auth Token - Found under Account Info here https://console.twilio.com/ |
170+
| twilio.service_id | Twilio Service ID - Found under Services Page here https://console.twilio.com/us1/develop/verify/services |
171+
| twilio.totp_enforce | Enforce 2FA for all users |
172+
| twilio.totp_email_on_login | Email a code to the user when they login |
173+
| twilio.totp_challenge_page | Page ID of the challenge page |
174+
175+
## Manager Page
176+
177+
Twilio 2FA Verification can be enabled in the manager login as well. You can view the status of Twilio 2FA for each user in the menu under
178+
"Extras -> User Authentication"

_build/config.json

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@
33
"lowCaseName": "twilio",
44
"description": "Twilio for MODX Revolution 2.x",
55
"author": "John Peca",
6-
"version": "1.1.0",
6+
"version": "1.2.0",
77
"package": {
8+
"menus": [
9+
{
10+
"text": "twilio.users",
11+
"description": "twilio.users.desc",
12+
"action": "users",
13+
"permissions": "twilio_manage_auth"
14+
}
15+
],
816
"elements": {
917
"snippets": [
1018
{
@@ -26,6 +34,28 @@
2634
{
2735
"name": "TwilioValidatePhone",
2836
"file": "TwilioValidatePhone.php"
37+
},
38+
{
39+
"name": "TwilioTOTPChallenge",
40+
"file": "TwilioTOTPChallenge.php"
41+
},
42+
{
43+
"name": "TwilioTOTPCreate",
44+
"file": "TwilioTOTPCreate.php"
45+
},
46+
{
47+
"name": "TwilioTOTPqr",
48+
"file": "TwilioTOTPqr.php"
49+
}
50+
],
51+
"plugins": [
52+
{
53+
"name": "Twilio",
54+
"file": "Twilio.php",
55+
"events": [
56+
"OnBeforeManagerPageInit",
57+
"OnManagerPageInit"
58+
]
2959
}
3060
]
3161
},
@@ -42,9 +72,30 @@
4272
{
4373
"key": "service_id",
4474
"value": ""
75+
},
76+
{
77+
"key": "totp_enforce",
78+
"value": "0",
79+
"type": "combo-boolean"
80+
},
81+
{
82+
"key": "totp_email_on_login",
83+
"value": "0",
84+
"type": "combo-boolean"
85+
},
86+
{
87+
"key": "totp_challenge_page",
88+
"value": ""
4589
}
4690
]
4791
},
92+
"build" : {
93+
"resolver" : {
94+
"after" : [
95+
"acls.php"
96+
]
97+
}
98+
},
4899
"dependencies": [
49100
{
50101
"name": "formit",

_build/resolvers/acls.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
if ($object->xpdo) {
3+
switch ($options[xPDOTransport::PACKAGE_ACTION]) {
4+
case xPDOTransport::ACTION_INSTALL:
5+
case xPDOTransport::ACTION_UPGRADE:
6+
/** @var modX $modx */
7+
$modx =& $object->xpdo;
8+
9+
$permissions = array('twilio_manage_auth');
10+
11+
foreach ($permissions as $permission) {
12+
$accessPermission = $modx->getObject('modAccessPermission', array(
13+
'template' => 1,
14+
'name' => $permission
15+
));
16+
17+
if (!$accessPermission) {
18+
$accessPermission = $modx->newObject('modAccessPermission');
19+
$accessPermission->set('template', 1);
20+
$accessPermission->set('name', $permission);
21+
$accessPermission->set('value', 1);
22+
$accessPermission->save();
23+
}
24+
}
25+
26+
break;
27+
}
28+
}
29+
return true;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
require_once dirname(dirname(dirname(dirname(__FILE__)))).'/config.core.php';
3+
require_once MODX_CORE_PATH . 'config/' . MODX_CONFIG_KEY . '.inc.php';
4+
require_once MODX_CONNECTORS_PATH . 'index.php';
5+
6+
$corePath = $modx->getOption('twilio.core_path', null, $modx->getOption('core_path', null, MODX_CORE_PATH) . 'components/twilio/');
7+
$twilio = $modx->getService(
8+
'twilio',
9+
'Twilio',
10+
$corePath . 'model/twilio/',
11+
array(
12+
'core_path' => $corePath
13+
)
14+
);
15+
16+
/* handle request */
17+
$modx->request->handleRequest(
18+
array(
19+
'processors_path' => $twilio->getOption('processorsPath', null, $corePath . 'processors/'),
20+
'location' => '',
21+
)
22+
);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#modx-leftbar, .x-layout-cmini-west {
2+
display: none !important;
3+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Ext.onReady(function() {
2+
var div = document.getElementById('modx-panel-profile-update');
3+
div.innerHTML = div.innerHTML + '<div class="x-form-item x-tab-item x-form-element">'
4+
+ '<label for="qrcode" style="width:auto;" class="x-form-item-label">'+
5+
twilio.qrText
6+
+':\n\</label></div>'
7+
+ '<div id="qrcode"><img id="qrimg" src=""></div>';
8+
MODx.Ajax.request({
9+
url: twilio.config.connector_url,
10+
params:{action:'totp/qr', user: twilio.config.user.user},
11+
listeners:{
12+
'success':{fn:function(r){ document.getElementById("qrimg").src = r.object.qr;},scope:this },
13+
'failure':{fn:function(){ },scope:this}}});
14+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
twilio.page.Totp = function(config) {
2+
config = config || {};
3+
Ext.applyIf(config,{
4+
components: [{
5+
xtype: 'twilio-panel-totp',
6+
renderTo: 'twilio-panel-totp-div'
7+
}]
8+
});
9+
twilio.page.Totp.superclass.constructor.call(this,config);
10+
}
11+
Ext.extend(twilio.page.Totp,MODx.Component);
12+
Ext.reg('twilio-page-totp',twilio.page.Totp);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
twilio.page.Users = function(config) {
2+
config = config || {};
3+
Ext.applyIf(config,{
4+
components: [{
5+
xtype: 'twilio-panel-users',
6+
renderTo: 'twilio-panel-users-div'
7+
}]
8+
});
9+
twilio.page.Users.superclass.constructor.call(this,config);
10+
}
11+
Ext.extend(twilio.page.Users,MODx.Component);
12+
Ext.reg('twilio-page-users',twilio.page.Users);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
var Twilio = function (config) {
2+
config = config || {};
3+
Twilio.superclass.constructor.call(this,config);
4+
};
5+
Ext.extend(Twilio, Ext.Component, {
6+
page:{},window:{},grid:{},tree:{},panel:{},combo:{},config: {}
7+
});
8+
Ext.reg('twilio',Twilio);
9+
twilio = new Twilio();

0 commit comments

Comments
 (0)