Skip to content

Commit 363d932

Browse files
committed
Merge branch 'develop' into 1.2
2 parents 9e456ee + e539b71 commit 363d932

File tree

15 files changed

+201
-57
lines changed

15 files changed

+201
-57
lines changed

modules/backend/ServiceProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ protected function registerAssetBundles()
112112
}
113113
});
114114

115-
PackageManager::instance()->registerCallback(function ($mix) {
115+
PackageManager::registerCallback(function ($mix) {
116116
$mix->registerPackage('module-backend.formwidgets.codeeditor', '~/modules/backend/formwidgets/codeeditor/assets/winter.mix.js');
117117
});
118118
}

modules/backend/controllers/Users.php

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1-
<?php namespace Backend\Controllers;
2-
3-
use Mail;
4-
use Lang;
5-
use Flash;
6-
use Backend;
7-
use Redirect;
8-
use Response;
9-
use BackendMenu;
10-
use BackendAuth;
11-
use Backend\Models\UserGroup;
1+
<?php
2+
3+
namespace Backend\Controllers;
4+
5+
use Backend\Behaviors\FormController;
6+
use Backend\Behaviors\ListController;
7+
use Backend\Behaviors\RelationController;
128
use Backend\Classes\Controller;
9+
use Backend\Facades\Backend;
10+
use Backend\Facades\BackendAuth;
11+
use Backend\Facades\BackendMenu;
12+
use Backend\Models\UserGroup;
13+
use Illuminate\Support\Facades\Lang;
14+
use Illuminate\Support\Facades\Redirect;
15+
use Illuminate\Support\Facades\Response;
16+
use Illuminate\Support\Str;
1317
use System\Classes\SettingsManager;
18+
use Winter\Storm\Support\Facades\Flash;
19+
use Winter\Storm\Support\Facades\Mail;
1420

1521
/**
1622
* Backend user controller
@@ -25,8 +31,9 @@ class Users extends Controller
2531
* @var array Extensions implemented by this controller.
2632
*/
2733
public $implement = [
28-
\Backend\Behaviors\FormController::class,
29-
\Backend\Behaviors\ListController::class,
34+
FormController::class,
35+
ListController::class,
36+
RelationController::class,
3037
];
3138

3239
/**
@@ -99,6 +106,18 @@ public function formExtendQuery($query)
99106
$query->withTrashed();
100107
}
101108

109+
/**
110+
* Before creating a new user, generate password if auto-generate is enabled
111+
*/
112+
public function formBeforeCreate($model)
113+
{
114+
if (post('User._auto_generate_password')) {
115+
$password = Str::random(22);
116+
$model->password = $password;
117+
$model->password_confirmation = $password;
118+
}
119+
}
120+
102121
/**
103122
* Update controller
104123
*/
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# ===================================
2+
# Relation Behavior Config
3+
# ===================================
4+
5+
throttle:
6+
label: backend::lang.user.throttle_tab_label
7+
view:
8+
list:
9+
columns:
10+
ip_address:
11+
label: backend::lang.user.throttle_ip_address
12+
searchable: true
13+
attempts:
14+
label: backend::lang.user.throttle_attempts
15+
width: 100px
16+
align: center
17+
last_attempt_at:
18+
label: backend::lang.user.throttle_last_attempt
19+
type: datetime
20+
searchable: true
21+
suspended_at:
22+
label: backend::lang.user.throttle_suspended_at
23+
type: datetime
24+
searchable: true
25+
toolbarButtons: delete|refresh
26+
showSearch: true
27+
showSorting: true
28+
recordsPerPage: 10
29+
defaultSort:
30+
column: last_attempt_at
31+
direction: desc

modules/backend/formwidgets/codeeditor/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ modules/backend/formwidgets/codeeditor/
167167

168168
#### Build Command
169169
```bash
170-
php artisan mix:compile --package=module-backend.formwidgets.codeeditor -p
170+
php artisan mix:compile --package=module-backend.formwidgets.codeeditor -f
171171
```
172172

173173
#### Build Configuration

modules/backend/formwidgets/codeeditor/assets/js/build/codeeditor.bundle.js

Lines changed: 11 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/backend/formwidgets/codeeditor/assets/js/build/codeeditor.bundle/847.js

Lines changed: 0 additions & 8 deletions
This file was deleted.

modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ import constrainedEditor from 'constrained-editor-plugin';
4343
import { parse as parseXml } from 'fast-plist';
4444
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
4545

46+
// Fix: Twig tokenizer doesn't handle <script type="module"> (https://github.com/wintercms/winter/issues/1449)
47+
// Monaco's HTML tokenizer explicitly maps type="module" to text/javascript,
48+
// but the Twig tokenizer uses a generic capture that passes the raw type value
49+
// as a language ID. "module" isn't a valid language ID, causing a nullLanguage error.
50+
import { language as twigLanguage } from 'monaco-editor/esm/vs/basic-languages/twig/twig';
51+
twigLanguage.tokenizer.scriptAfterTypeEquals.unshift(
52+
[/"module"/, { token: 'attribute.value.html', switchTo: '@scriptWithCustomType.text/javascript' }],
53+
[/'module'/, { token: 'attribute.value.html', switchTo: '@scriptWithCustomType.text/javascript' }],
54+
);
55+
4656
((Snowboard) => {
4757
/**
4858
* Code editor widget.
@@ -81,6 +91,7 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
8191
this.fullscreen = false;
8292
this.cachedThemes = {};
8393
this.resizeThrottle = null;
94+
this.savedState = null;
8495
this.callbacks = {
8596
fullScreenChange: () => this.onFullScreenChange(),
8697
resize: () => {
@@ -183,7 +194,8 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
183194
this.visibilityListener = false;
184195
}
185196
if (this.clickListener) {
186-
document.removeEventListener('click', this.callbacks.click);
197+
document.removeEventListener('click', this.callbacks.click, { capture: true });
198+
this.clickListener = false;
187199
}
188200
}
189201

@@ -194,6 +206,11 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
194206
* and preventing slowdown of the browser.
195207
*/
196208
dispose() {
209+
if (this.editor) {
210+
this.savedState = {
211+
position: this.editor.getPosition(),
212+
};
213+
}
197214
if (this.disposables.length > 0) {
198215
this.disposables.forEach((disposable) => {
199216
disposable.dispose();
@@ -204,11 +221,15 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
204221
window.removeEventListener('resize', this.callbacks.resize);
205222
this.resizeListener = false;
206223
}
224+
if (this.model) {
225+
this.model.dispose();
226+
this.model = null;
227+
}
207228
if (this.editor) {
208229
this.editor.dispose();
209230
this.editor = null;
210231
}
211-
this.events.fire('dispose', this, this.editor);
232+
this.events.fire('dispose', this);
212233
}
213234

214235
/**
@@ -239,6 +260,11 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
239260
* Creates a Monaco editor instance in the given element.
240261
*/
241262
createEditor() {
263+
// Guard against creating a duplicate editor (both onObserve and onVisibilityChange
264+
// can trigger creation simultaneously)
265+
if (this.editor) {
266+
return;
267+
}
242268

243269
// Force a specific height on the container - stops Monaco from indefinitely trying
244270
// to resize if the container has a fluid height
@@ -259,6 +285,15 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
259285
this.enableStatusBarActions();
260286
this.registerKeyBindings();
261287

288+
// Restore cursor position and scroll state from before the editor was disposed
289+
if (this.savedState) {
290+
if (this.savedState.position) {
291+
this.editor.setPosition(this.savedState.position);
292+
this.editor.revealPositionInCenter(this.savedState.position);
293+
}
294+
this.savedState = null;
295+
}
296+
262297
this.events.fire('create', this, this.editor);
263298
}
264299

@@ -398,9 +433,12 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
398433
this.clickStartedInEditor = false;
399434
}, 20);
400435
}));
401-
document.addEventListener('click', this.callbacks.click, {
402-
capture: true,
403-
});
436+
if (!this.clickListener) {
437+
document.addEventListener('click', this.callbacks.click, {
438+
capture: true,
439+
});
440+
this.clickListener = true;
441+
}
404442

405443
window.addEventListener('resize', this.callbacks.resize);
406444
this.resizeListener = true;

modules/backend/lang/en/lang.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@
154154
'superuser_comment' => 'Grants this account unlimited access to all areas of the system. Super users can add and manage other users. ',
155155
'send_invite' => 'Send invitation by email',
156156
'send_invite_comment' => 'Sends a welcome message containing login and password information.',
157+
'auto_generate_password' => 'Auto-generate password',
158+
'auto_generate_password_comment' => 'Automatically create a secure random password. Uncheck to set a password manually.',
157159
'delete_confirm' => 'Delete this administrator?',
158160
'return' => 'Return to admin list',
159161
'allow' => 'Allow',
@@ -165,6 +167,13 @@
165167
'updated_at' => 'Updated at',
166168
'deleted_at' => 'Deleted at',
167169
'show_deleted' => 'Show deleted',
170+
'throttle_tab' => 'Failed Logins',
171+
'throttle_tab_label' => 'Failed Login Records',
172+
'throttle_comment' => 'View failed login attempts for this user. These records are automatically generated when login attempts fail. Users are suspended after exceeding the attempt limit.',
173+
'throttle_ip_address' => 'IP Address',
174+
'throttle_attempts' => 'Attempts',
175+
'throttle_last_attempt' => 'Last Attempt',
176+
'throttle_suspended_at' => 'Suspended At',
168177
'group' => [
169178
'name' => 'Group',
170179
'name_field' => 'Name',

modules/backend/models/User.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ class User extends UserBase
5757
'avatar' => \System\Models\File::class
5858
];
5959

60+
public $hasMany = [
61+
'throttle' => [UserThrottle::class, 'key' => 'user_id']
62+
];
63+
6064
/**
6165
* Purge attributes from data set.
6266
*/

modules/backend/models/user/fields.yaml

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,54 +3,64 @@
33
# ===================================
44

55
fields:
6-
is_superuser:
7-
context: [create, update]
8-
tab: backend::lang.user.permissions
9-
label: backend::lang.user.superuser
10-
type: switch
11-
comment: backend::lang.user.superuser_comment
6+
first_name:
7+
span: left
8+
label: backend::lang.user.first_name
9+
last_name:
10+
span: right
11+
label: backend::lang.user.last_name
12+
login:
13+
span: left
14+
label: backend::lang.user.login
15+
email:
16+
span: right
17+
type: email
18+
label: backend::lang.user.email
1219

1320
tabs:
1421
defaultTab: backend::lang.user.account
1522
icons:
1623
backend::lang.user.account: icon-user
1724
backend::lang.user.groups: icon-users
1825
backend::lang.user.permissions: icon-key
26+
backend::lang.user.throttle_tab: icon-ban
1927

2028
fields:
21-
login:
22-
span: left
23-
label: backend::lang.user.login
24-
25-
email:
26-
span: right
27-
type: email
28-
label: backend::lang.user.email
29-
3029
send_invite:
3130
context: create
3231
type: checkbox
3332
label: backend::lang.user.send_invite
3433
comment: backend::lang.user.send_invite_comment
3534
default: true
3635

37-
first_name:
38-
span: left
39-
label: backend::lang.user.first_name
40-
41-
last_name:
42-
span: right
43-
label: backend::lang.user.last_name
36+
_auto_generate_password:
37+
context: create
38+
type: checkbox
39+
label: backend::lang.user.auto_generate_password
40+
comment: backend::lang.user.auto_generate_password_comment
41+
default: true
42+
trigger:
43+
action: show
44+
field: send_invite
45+
condition: checked
4446

4547
password:
4648
type: password
4749
span: left
4850
label: backend::lang.user.password
51+
trigger:
52+
action: disable
53+
field: _auto_generate_password
54+
condition: checked
4955

5056
password_confirmation:
5157
type: password
5258
span: right
5359
label: backend::lang.user.password_confirmation
60+
trigger:
61+
action: disable
62+
field: _auto_generate_password
63+
condition: checked
5464

5565
role:
5666
context: [create, update]
@@ -65,6 +75,13 @@ tabs:
6575
type: checkboxlist
6676
tab: backend::lang.user.groups
6777

78+
throttle:
79+
label: backend::lang.user.throttle_tab_label
80+
type: relationmanager
81+
tab: backend::lang.user.throttle_tab
82+
context: [update]
83+
commentAbove: backend::lang.user.throttle_comment
84+
6885
secondaryTabs:
6986
fields:
7087
btn_impersonate:
@@ -85,3 +102,8 @@ secondaryTabs:
85102
mode: image
86103
imageHeight: 250
87104
imageWidth: 250
105+
is_superuser:
106+
context: [create, update]
107+
label: backend::lang.user.superuser
108+
type: switch
109+
comment: backend::lang.user.superuser_comment

0 commit comments

Comments
 (0)