admin-lte 4.0.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ACCESSIBILITY-COMPLIANCE.md +60 -339
- package/CHANGELOG.md +66 -0
- package/README.md +15 -2
- package/dist/css/adminlte-docs.css +878 -0
- package/dist/css/adminlte-docs.css.map +1 -0
- package/dist/css/adminlte-docs.min.css +7 -0
- package/dist/css/adminlte-docs.min.css.map +1 -0
- package/dist/css/adminlte-docs.rtl.css +877 -0
- package/dist/css/adminlte-docs.rtl.css.map +1 -0
- package/dist/css/adminlte-docs.rtl.min.css +7 -0
- package/dist/css/adminlte-docs.rtl.min.css.map +1 -0
- package/dist/css/adminlte.css +1176 -2718
- package/dist/css/adminlte.css.map +1 -1
- package/dist/css/adminlte.min.css +2 -2
- package/dist/css/adminlte.min.css.map +1 -1
- package/dist/css/adminlte.rtl.css +1176 -2718
- package/dist/css/adminlte.rtl.css.map +1 -1
- package/dist/css/adminlte.rtl.min.css +2 -2
- package/dist/css/adminlte.rtl.min.css.map +1 -1
- package/dist/js/adminlte.esm.js +1365 -0
- package/dist/js/adminlte.esm.js.map +1 -0
- package/dist/js/adminlte.esm.min.js +7 -0
- package/dist/js/adminlte.esm.min.js.map +1 -0
- package/dist/js/adminlte.js +606 -310
- package/dist/js/adminlte.js.map +1 -1
- package/dist/js/adminlte.min.js +2 -2
- package/dist/js/adminlte.min.js.map +1 -1
- package/dist/js/types/accessibility.d.ts +46 -0
- package/dist/js/types/adminlte.d.ts +9 -0
- package/dist/js/types/base-component.d.ts +36 -0
- package/dist/js/types/card-widget.d.ts +30 -0
- package/dist/js/types/color-mode.d.ts +56 -0
- package/dist/js/types/direct-chat.d.ts +19 -0
- package/dist/js/types/fullscreen.d.ts +21 -0
- package/dist/js/types/layout.d.ts +19 -0
- package/dist/js/types/push-menu.d.ts +102 -0
- package/dist/js/types/treeview.d.ts +27 -0
- package/dist/js/types/util/index.d.ts +42 -0
- package/package.json +60 -21
- package/src/scss/_app-header.scss +3 -1
- package/src/scss/_app-main.scss +4 -0
- package/src/scss/_app-sidebar.scss +3 -1
- package/src/scss/_bootstrap-overrides.scss +60 -0
- package/src/scss/_callouts.scss +13 -3
- package/src/scss/_dropdown.scss +3 -1
- package/src/scss/_info-box.scss +3 -1
- package/src/scss/_progress-bars.scss +3 -1
- package/src/scss/_table.scss +4 -2
- package/src/scss/adminlte-docs.scss +25 -0
- package/src/scss/adminlte.scss +5 -4
- package/src/scss/pages/_login_and_register.scss +3 -1
- package/src/scss/parts/_core.scss +0 -1
- package/src/ts/accessibility.ts +129 -69
- package/src/ts/adminlte.ts +3 -1
- package/src/ts/base-component.ts +84 -0
- package/src/ts/card-widget.ts +134 -85
- package/src/ts/color-mode.ts +174 -0
- package/src/ts/direct-chat.ts +38 -32
- package/src/ts/fullscreen.ts +78 -63
- package/src/ts/layout.ts +2 -1
- package/src/ts/push-menu.ts +93 -44
- package/src/ts/treeview.ts +107 -47
- package/src/ts/util/index.ts +114 -29
- package/.browserslistrc +0 -17
- package/.prettierrc +0 -6
- package/CODE_OF_CONDUCT.md +0 -43
- package/SECURITY.md +0 -99
- package/dist/UI/general.html +0 -2317
- package/dist/UI/icons.html +0 -1126
- package/dist/UI/timeline.html +0 -1212
- package/dist/docs/browser-support.html +0 -826
- package/dist/docs/color-mode.html +0 -1142
- package/dist/docs/components/main-header.html +0 -1209
- package/dist/docs/components/main-sidebar.html +0 -924
- package/dist/docs/customization.html +0 -1080
- package/dist/docs/deployment.html +0 -1145
- package/dist/docs/faq.html +0 -1392
- package/dist/docs/getting-started.html +0 -991
- package/dist/docs/how-to-contribute.html +0 -890
- package/dist/docs/index.html +0 -16
- package/dist/docs/integrations.html +0 -1231
- package/dist/docs/introduction.html +0 -1008
- package/dist/docs/javascript/accessibility.html +0 -949
- package/dist/docs/javascript/card-widget.html +0 -1019
- package/dist/docs/javascript/direct-chat.html +0 -896
- package/dist/docs/javascript/fullscreen.html +0 -905
- package/dist/docs/javascript/layout.html +0 -908
- package/dist/docs/javascript/plugins-overview.html +0 -1144
- package/dist/docs/javascript/pushmenu.html +0 -1045
- package/dist/docs/javascript/treeview.html +0 -1024
- package/dist/docs/layout-blueprint.html +0 -1087
- package/dist/docs/layout.html +0 -842
- package/dist/docs/license.html +0 -807
- package/dist/docs/migration.html +0 -1149
- package/dist/docs/recipes.html +0 -1185
- package/dist/docs/rtl.html +0 -957
- package/dist/examples/lockscreen.html +0 -249
- package/dist/examples/login-v2.html +0 -282
- package/dist/examples/login.html +0 -272
- package/dist/examples/register-v2.html +0 -291
- package/dist/examples/register.html +0 -277
- package/dist/forms/elements.html +0 -1405
- package/dist/forms/layout.html +0 -1267
- package/dist/forms/validation.html +0 -1275
- package/dist/forms/wizard.html +0 -1410
- package/dist/generate/theme.html +0 -1082
- package/dist/index.html +0 -1745
- package/dist/index2.html +0 -2277
- package/dist/index3.html +0 -1532
- package/dist/layout/collapsed-sidebar-without-hover.html +0 -1144
- package/dist/layout/collapsed-sidebar.html +0 -1137
- package/dist/layout/fixed-complete.html +0 -1138
- package/dist/layout/fixed-footer.html +0 -1136
- package/dist/layout/fixed-header.html +0 -1136
- package/dist/layout/fixed-sidebar.html +0 -1138
- package/dist/layout/layout-custom-area.html +0 -1177
- package/dist/layout/layout-rtl.html +0 -1137
- package/dist/layout/logo-switch.html +0 -683
- package/dist/layout/sidebar-mini.html +0 -1137
- package/dist/layout/unfixed-sidebar.html +0 -1136
- package/dist/mailbox/compose.html +0 -1151
- package/dist/mailbox/inbox.html +0 -1509
- package/dist/mailbox/read.html +0 -1202
- package/dist/pages/404.html +0 -239
- package/dist/pages/500.html +0 -227
- package/dist/pages/calendar.html +0 -1266
- package/dist/pages/chat.html +0 -1427
- package/dist/pages/faq.html +0 -1383
- package/dist/pages/file-manager.html +0 -1835
- package/dist/pages/invoice.html +0 -1199
- package/dist/pages/kanban.html +0 -1439
- package/dist/pages/maintenance.html +0 -230
- package/dist/pages/pricing.html +0 -1279
- package/dist/pages/profile.html +0 -1382
- package/dist/pages/projects.html +0 -1644
- package/dist/pages/settings.html +0 -1387
- package/dist/tables/data.html +0 -1319
- package/dist/tables/simple.html +0 -1435
- package/dist/widgets/cards.html +0 -1356
- package/dist/widgets/info-box.html +0 -1429
- package/dist/widgets/small-box.html +0 -1225
- package/eslint.config.js +0 -82
- package/github-issue-response.md +0 -40
- package/index.html +0 -12
- package/netlify.toml +0 -16
- package/src/scss/_bootstrap-variables.scss +0 -1766
package/src/ts/util/index.ts
CHANGED
|
@@ -1,22 +1,80 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle management
|
|
3
|
+
* ============================================================================
|
|
4
|
+
*
|
|
5
|
+
* Plugins register their initialisation through `onDOMContentLoaded`. Besides
|
|
6
|
+
* the initial page load, every registered callback is re-run on Hotwired Turbo
|
|
7
|
+
* navigations (`turbo:load`): Turbo Drive swaps the <body> without a full page
|
|
8
|
+
* reload, so without re-initialisation plugins such as PushMenu and TreeView
|
|
9
|
+
* stop working after the first in-app link click (#563, #5890).
|
|
10
|
+
*
|
|
11
|
+
* Re-running init would normally leak listeners, because callbacks also bind to
|
|
12
|
+
* `window`/`document`, which survive Turbo's <body> swap. To prevent that, each
|
|
13
|
+
* cycle has its own `AbortController`: callbacks should attach their
|
|
14
|
+
* window/document-level listeners with the signal from `getLifecycleSignal()`.
|
|
15
|
+
* The signal is aborted on `turbo:before-render`, tearing down the previous
|
|
16
|
+
* cycle's listeners before the callbacks run again. Listeners bound to elements
|
|
17
|
+
* inside <body> don't need the signal — Turbo discards the old <body>, so they
|
|
18
|
+
* are cleaned up automatically.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const lifecycleCallbacks: Array<() => void> = []
|
|
22
|
+
|
|
23
|
+
// Mutable state is held on an object so the lifecycle hooks below can update it
|
|
24
|
+
// without reassigning top-level bindings.
|
|
25
|
+
const lifecycleState = {
|
|
26
|
+
controller: new AbortController(),
|
|
27
|
+
hasInitialized: false
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The AbortSignal for the current lifecycle. Pass it as the
|
|
32
|
+
* `{ signal }` option to window/document `addEventListener` calls made during
|
|
33
|
+
* initialisation so they are removed automatically on the next Turbo render.
|
|
34
|
+
*/
|
|
35
|
+
const getLifecycleSignal = (): AbortSignal => lifecycleState.controller.signal
|
|
36
|
+
|
|
37
|
+
const runLifecycleCallbacks = (): void => {
|
|
38
|
+
if (lifecycleState.hasInitialized) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
lifecycleState.hasInitialized = true
|
|
43
|
+
|
|
44
|
+
for (const callback of lifecycleCallbacks) {
|
|
45
|
+
callback()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
2
48
|
|
|
3
49
|
const onDOMContentLoaded = (callback: () => void): void => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
})
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
domContentLoadedCallbacks.push(callback)
|
|
15
|
-
} else {
|
|
50
|
+
lifecycleCallbacks.push(callback)
|
|
51
|
+
|
|
52
|
+
// Late registration: the batch for the current cycle has already run (the
|
|
53
|
+
// script loaded after DOMContentLoaded, or a callback was registered after a
|
|
54
|
+
// Turbo visit), so run the newcomer immediately rather than stranding it
|
|
55
|
+
// until the next navigation. Preserves the original non-loading behaviour.
|
|
56
|
+
if (lifecycleState.hasInitialized) {
|
|
16
57
|
callback()
|
|
17
58
|
}
|
|
18
59
|
}
|
|
19
60
|
|
|
61
|
+
// Initial page load.
|
|
62
|
+
if (document.readyState === 'loading') {
|
|
63
|
+
document.addEventListener('DOMContentLoaded', runLifecycleCallbacks, { once: true })
|
|
64
|
+
} else {
|
|
65
|
+
runLifecycleCallbacks()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Hotwired Turbo: drop the previous cycle's window/document listeners, then
|
|
69
|
+
// re-run initialisation against the freshly rendered <body>.
|
|
70
|
+
document.addEventListener('turbo:before-render', () => {
|
|
71
|
+
lifecycleState.controller.abort()
|
|
72
|
+
lifecycleState.controller = new AbortController()
|
|
73
|
+
lifecycleState.hasInitialized = false
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
document.addEventListener('turbo:load', runLifecycleCallbacks)
|
|
77
|
+
|
|
20
78
|
/* ES2022 UTILITY FUNCTIONS */
|
|
21
79
|
|
|
22
80
|
/**
|
|
@@ -46,10 +104,35 @@ const safePropertyAccess = (obj: Record<string, unknown>, property: string): unk
|
|
|
46
104
|
}
|
|
47
105
|
}
|
|
48
106
|
|
|
107
|
+
/* SLIDE ANIMATION BOOKKEEPING
|
|
108
|
+
* Pending timers are tracked per element so that starting a new slide cancels
|
|
109
|
+
* the previous animation's steps: without this, rapidly toggling a treeview or
|
|
110
|
+
* card leaves a stale cleanup timer that strips height/transition mid-animation
|
|
111
|
+
* and desyncs the element's display state from its component's classes. */
|
|
112
|
+
const slideTimers = new WeakMap<HTMLElement, Array<ReturnType<typeof globalThis.setTimeout>>>()
|
|
113
|
+
|
|
114
|
+
const cancelSlide = (target: HTMLElement): void => {
|
|
115
|
+
const timers = slideTimers.get(target) ?? []
|
|
116
|
+
for (const timer of timers) {
|
|
117
|
+
globalThis.clearTimeout(timer)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
slideTimers.delete(target)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const clearSlideStyles = (target: HTMLElement): void => {
|
|
124
|
+
for (const property of ['height', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom', 'overflow', 'transition-duration', 'transition-property']) {
|
|
125
|
+
target.style.removeProperty(property)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
49
129
|
/* SLIDE UP */
|
|
50
130
|
const slideUp = (target: HTMLElement, duration = 500) => {
|
|
131
|
+
cancelSlide(target)
|
|
132
|
+
|
|
51
133
|
if (duration <= 1) {
|
|
52
134
|
target.style.display = 'none'
|
|
135
|
+
clearSlideStyles(target)
|
|
53
136
|
return
|
|
54
137
|
}
|
|
55
138
|
|
|
@@ -59,7 +142,7 @@ const slideUp = (target: HTMLElement, duration = 500) => {
|
|
|
59
142
|
target.style.height = `${target.offsetHeight}px`
|
|
60
143
|
target.style.overflow = 'hidden'
|
|
61
144
|
|
|
62
|
-
globalThis.setTimeout(() => {
|
|
145
|
+
const stepTimer = globalThis.setTimeout(() => {
|
|
63
146
|
target.style.height = '0'
|
|
64
147
|
target.style.paddingTop = '0'
|
|
65
148
|
target.style.paddingBottom = '0'
|
|
@@ -67,21 +150,22 @@ const slideUp = (target: HTMLElement, duration = 500) => {
|
|
|
67
150
|
target.style.marginBottom = '0'
|
|
68
151
|
}, 1)
|
|
69
152
|
|
|
70
|
-
globalThis.setTimeout(() => {
|
|
153
|
+
const cleanupTimer = globalThis.setTimeout(() => {
|
|
71
154
|
target.style.display = 'none'
|
|
72
|
-
target
|
|
73
|
-
|
|
74
|
-
target.style.removeProperty('padding-bottom')
|
|
75
|
-
target.style.removeProperty('margin-top')
|
|
76
|
-
target.style.removeProperty('margin-bottom')
|
|
77
|
-
target.style.removeProperty('overflow')
|
|
78
|
-
target.style.removeProperty('transition-duration')
|
|
79
|
-
target.style.removeProperty('transition-property')
|
|
155
|
+
clearSlideStyles(target)
|
|
156
|
+
slideTimers.delete(target)
|
|
80
157
|
}, duration)
|
|
158
|
+
|
|
159
|
+
slideTimers.set(target, [stepTimer, cleanupTimer])
|
|
81
160
|
}
|
|
82
161
|
|
|
83
162
|
/* SLIDE DOWN */
|
|
84
163
|
const slideDown = (target: HTMLElement, duration = 500) => {
|
|
164
|
+
cancelSlide(target)
|
|
165
|
+
// Drop inline styles a cancelled slideUp may have left behind (height: 0,
|
|
166
|
+
// overflow: hidden, …) before measuring, or the natural height reads as 0.
|
|
167
|
+
clearSlideStyles(target)
|
|
168
|
+
|
|
85
169
|
target.style.removeProperty('display')
|
|
86
170
|
let { display } = globalThis.getComputedStyle(target)
|
|
87
171
|
|
|
@@ -103,7 +187,7 @@ const slideDown = (target: HTMLElement, duration = 500) => {
|
|
|
103
187
|
target.style.marginTop = '0'
|
|
104
188
|
target.style.marginBottom = '0'
|
|
105
189
|
|
|
106
|
-
globalThis.setTimeout(() => {
|
|
190
|
+
const stepTimer = globalThis.setTimeout(() => {
|
|
107
191
|
target.style.boxSizing = 'border-box'
|
|
108
192
|
target.style.transitionProperty = 'height, margin, padding'
|
|
109
193
|
target.style.transitionDuration = `${duration}ms`
|
|
@@ -114,12 +198,12 @@ const slideDown = (target: HTMLElement, duration = 500) => {
|
|
|
114
198
|
target.style.removeProperty('margin-bottom')
|
|
115
199
|
}, 1)
|
|
116
200
|
|
|
117
|
-
globalThis.setTimeout(() => {
|
|
118
|
-
target
|
|
119
|
-
|
|
120
|
-
target.style.removeProperty('transition-duration')
|
|
121
|
-
target.style.removeProperty('transition-property')
|
|
201
|
+
const cleanupTimer = globalThis.setTimeout(() => {
|
|
202
|
+
clearSlideStyles(target)
|
|
203
|
+
slideTimers.delete(target)
|
|
122
204
|
}, duration)
|
|
205
|
+
|
|
206
|
+
slideTimers.set(target, [stepTimer, cleanupTimer])
|
|
123
207
|
}
|
|
124
208
|
|
|
125
209
|
/* TOGGLE */
|
|
@@ -134,6 +218,7 @@ const slideToggle = (target: HTMLElement, duration = 500) => {
|
|
|
134
218
|
|
|
135
219
|
export {
|
|
136
220
|
onDOMContentLoaded,
|
|
221
|
+
getLifecycleSignal,
|
|
137
222
|
slideUp,
|
|
138
223
|
slideDown,
|
|
139
224
|
slideToggle,
|
package/.browserslistrc
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# https://github.com/browserslist/browserslist#readme
|
|
2
|
-
# Updated for ES2022 compatibility
|
|
3
|
-
|
|
4
|
-
>= 0.5%
|
|
5
|
-
last 2 major versions
|
|
6
|
-
not dead
|
|
7
|
-
Chrome >= 97
|
|
8
|
-
Firefox >= 104
|
|
9
|
-
Firefox ESR
|
|
10
|
-
iOS >= 15.4
|
|
11
|
-
Safari >= 15.4
|
|
12
|
-
Edge >= 97
|
|
13
|
-
not Explorer <= 11
|
|
14
|
-
not ie 11
|
|
15
|
-
not android 4.4.3
|
|
16
|
-
not ios_saf < 15.4
|
|
17
|
-
not kaios <= 2.5 # fix floating label issues in Firefox (see https://github.com/postcss/autoprefixer/issues/1533)
|
package/.prettierrc
DELETED
package/CODE_OF_CONDUCT.md
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# Contributor Covenant Code of Conduct
|
|
2
|
-
|
|
3
|
-
## Our Pledge
|
|
4
|
-
|
|
5
|
-
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
|
6
|
-
|
|
7
|
-
## Our Standards
|
|
8
|
-
|
|
9
|
-
Examples of behavior that contributes to creating a positive environment include:
|
|
10
|
-
|
|
11
|
-
- Using welcoming and inclusive language
|
|
12
|
-
- Being respectful of differing viewpoints and experiences
|
|
13
|
-
- Gracefully accepting constructive criticism
|
|
14
|
-
- Focusing on what is best for the community
|
|
15
|
-
- Showing empathy towards other community members
|
|
16
|
-
|
|
17
|
-
Examples of unacceptable behavior by participants include:
|
|
18
|
-
|
|
19
|
-
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
|
20
|
-
- Trolling, insulting/derogatory comments, and personal or political attacks
|
|
21
|
-
- Public or private harassment
|
|
22
|
-
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
|
23
|
-
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
24
|
-
|
|
25
|
-
## Our Responsibilities
|
|
26
|
-
|
|
27
|
-
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
|
28
|
-
|
|
29
|
-
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
|
30
|
-
|
|
31
|
-
## Scope
|
|
32
|
-
|
|
33
|
-
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
|
34
|
-
|
|
35
|
-
## Enforcement
|
|
36
|
-
|
|
37
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at https://colorlib.com/wp/contact-us/. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
|
38
|
-
|
|
39
|
-
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
|
40
|
-
|
|
41
|
-
## Attribution
|
|
42
|
-
|
|
43
|
-
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 1.4, available at <https://www.contributor-covenant.org/version/1/4/code-of-conduct/>
|
package/SECURITY.md
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
# Security Policy
|
|
2
|
-
|
|
3
|
-
## Reporting Security Issues
|
|
4
|
-
|
|
5
|
-
If you discover a security vulnerability in AdminLTE, please report it by emailing the maintainers or opening a private security advisory on GitHub. We take security seriously and will respond promptly.
|
|
6
|
-
|
|
7
|
-
## Supported Versions
|
|
8
|
-
|
|
9
|
-
| Version | Supported |
|
|
10
|
-
| ------- | ------------------ |
|
|
11
|
-
| 4.x | :white_check_mark: |
|
|
12
|
-
| 3.x | :x: |
|
|
13
|
-
| < 3.0 | :x: |
|
|
14
|
-
|
|
15
|
-
## Security Best Practices
|
|
16
|
-
|
|
17
|
-
AdminLTE is a frontend admin dashboard template. When deploying applications built with AdminLTE, follow these security best practices:
|
|
18
|
-
|
|
19
|
-
### 1. Production Deployment
|
|
20
|
-
|
|
21
|
-
- **Never expose `node_modules` directory** in production environments
|
|
22
|
-
- **Remove demo/example files** (like `index2.html`, `index3.html`) from production builds
|
|
23
|
-
- **Use a proper build process** that only includes necessary production assets
|
|
24
|
-
- **Configure web server properly** to prevent directory traversal attacks
|
|
25
|
-
|
|
26
|
-
### 2. Build Process
|
|
27
|
-
|
|
28
|
-
When deploying to production:
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
# Build only production assets
|
|
32
|
-
npm run production
|
|
33
|
-
|
|
34
|
-
# Deploy only the dist/ directory contents you need
|
|
35
|
-
# Typically: dist/js/adminlte.min.js and dist/css/adminlte.min.css
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### 3. What NOT to Deploy
|
|
39
|
-
|
|
40
|
-
Do not deploy these to production:
|
|
41
|
-
- `node_modules/` directory
|
|
42
|
-
- Example/demo HTML files (`index.html`, `index2.html`, `index3.html`, etc.)
|
|
43
|
-
- Source files (`src/` directory)
|
|
44
|
-
- Development configuration files
|
|
45
|
-
- Documentation files
|
|
46
|
-
|
|
47
|
-
## Known CVE Issues
|
|
48
|
-
|
|
49
|
-
### CVE-2021-36471 (Disputed)
|
|
50
|
-
|
|
51
|
-
**Status**: This CVE is **disputed** and does not represent a vulnerability in AdminLTE itself.
|
|
52
|
-
|
|
53
|
-
**Issue**: CVE-2021-36471 claims AdminLTE 3.1.0 has a "Directory Traversal vulnerability" that allows remote attackers to view demo pages via `/admin/index2.html` and `/admin/index3.html`.
|
|
54
|
-
|
|
55
|
-
**Clarification**:
|
|
56
|
-
- The `index2.html` and `index3.html` files are **example/demo pages** intended for developer reference during development
|
|
57
|
-
- This is **not a vulnerability in AdminLTE** - it is a **deployment misconfiguration** by website developers
|
|
58
|
-
- The issue occurs when developers incorrectly deploy:
|
|
59
|
-
- Their entire `node_modules` folder publicly
|
|
60
|
-
- Demo/example files in production environments
|
|
61
|
-
- Without proper web server configuration
|
|
62
|
-
|
|
63
|
-
**Resolution**:
|
|
64
|
-
- AdminLTE 4.x has restructured the project architecture with clear separation between development demos and production assets
|
|
65
|
-
- Follow the production deployment best practices above
|
|
66
|
-
- Only deploy the compiled production assets from `dist/js/` and `dist/css/`
|
|
67
|
-
- The original CVE researcher acknowledged this should be classified as low/info severity, not critical
|
|
68
|
-
|
|
69
|
-
**For More Information**:
|
|
70
|
-
- [GitHub Issue #4948](https://github.com/ColorlibHQ/AdminLTE/issues/4948)
|
|
71
|
-
- [CVE Record](https://www.cve.org/CVERecord?id=CVE-2021-36471) (marked as disputed)
|
|
72
|
-
|
|
73
|
-
## Secure Development
|
|
74
|
-
|
|
75
|
-
### Content Security Policy (CSP)
|
|
76
|
-
|
|
77
|
-
When implementing AdminLTE in your application, consider adding appropriate Content Security Policy headers to prevent XSS attacks.
|
|
78
|
-
|
|
79
|
-
### Authentication & Authorization
|
|
80
|
-
|
|
81
|
-
AdminLTE is a **UI template only** and does not include authentication or authorization. You must:
|
|
82
|
-
- Implement proper authentication in your backend
|
|
83
|
-
- Secure all API endpoints
|
|
84
|
-
- Use HTTPS in production
|
|
85
|
-
- Implement proper session management
|
|
86
|
-
- Follow OWASP security guidelines
|
|
87
|
-
|
|
88
|
-
### Dependencies
|
|
89
|
-
|
|
90
|
-
- Keep AdminLTE and its dependencies up to date
|
|
91
|
-
- Regularly run `npm audit` to check for vulnerabilities
|
|
92
|
-
- Review security advisories for Bootstrap and other dependencies
|
|
93
|
-
|
|
94
|
-
## Contact
|
|
95
|
-
|
|
96
|
-
For security concerns, please contact the maintainers through:
|
|
97
|
-
- GitHub Issues (for general questions)
|
|
98
|
-
- GitHub Security Advisories (for sensitive security issues)
|
|
99
|
-
- Project maintainer email (check package.json)
|