@fdm-monster/client-next 0.0.1

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.
Files changed (205) hide show
  1. package/.all-contributorsrc +57 -0
  2. package/.browserslistrc +4 -0
  3. package/.editorconfig +5 -0
  4. package/.env +1 -0
  5. package/.eslintrc-auto-import.json +73 -0
  6. package/.eslintrc.js +126 -0
  7. package/.github/FUNDING.yml +3 -0
  8. package/.github/workflows/release-client.yml +94 -0
  9. package/.github/workflows/vue-publish.yml +26 -0
  10. package/.prettierignore +15 -0
  11. package/.prettierrc.cjs +7 -0
  12. package/.whitesource +12 -0
  13. package/.yarn/releases/yarn-4.5.1.cjs +934 -0
  14. package/.yarnrc.yml +3 -0
  15. package/CODE_OF_CONDUCT.md +46 -0
  16. package/README.md +93 -0
  17. package/RELEASE_NOTES.MD +11 -0
  18. package/index.html +16 -0
  19. package/package.default.json +42 -0
  20. package/package.json +26 -0
  21. package/public/favicon.ico +0 -0
  22. package/public/img/DavidZwart.jpg +0 -0
  23. package/public/img/OIG.JYDC2RaWdz7g9.jpg +0 -0
  24. package/public/img/OIG.jpg +0 -0
  25. package/public/img/icons/android-chrome-192x192.png +0 -0
  26. package/public/img/icons/android-chrome-256x256.png +0 -0
  27. package/public/img/icons/android-chrome-384x384.png +0 -0
  28. package/public/img/icons/android-chrome-512x512.png +0 -0
  29. package/public/img/icons/favicon.svg +1 -0
  30. package/public/img/logo.png +0 -0
  31. package/public/img/logo.svg +1 -0
  32. package/public/img/manifest.webmanifest +33 -0
  33. package/public/img/octoprint-tentacle.svg +144 -0
  34. package/public/img/thumbail_unknown.jpg +0 -0
  35. package/public/img/vbanner.jpg +0 -0
  36. package/public/index.html +17 -0
  37. package/public/robots.txt +2 -0
  38. package/renovate.json +30 -0
  39. package/src/App.vue +60 -0
  40. package/src/AppLoader.vue +383 -0
  41. package/src/assets/adjectives.json +1468 -0
  42. package/src/assets/android-chrome-192x192.png +0 -0
  43. package/src/assets/logo.png +0 -0
  44. package/src/assets/logo.svg +6 -0
  45. package/src/assets/nouns.json +4309 -0
  46. package/src/auto-imports.d.ts +139 -0
  47. package/src/backend/app.service.ts +39 -0
  48. package/src/backend/auth.service.ts +56 -0
  49. package/src/backend/base.service.ts +57 -0
  50. package/src/backend/batch.service.ts +37 -0
  51. package/src/backend/camera-stream.service.ts +33 -0
  52. package/src/backend/custom-gcode.service.ts +11 -0
  53. package/src/backend/dto/octoprint-settings.dto.ts +168 -0
  54. package/src/backend/first-time-setup.service.ts +17 -0
  55. package/src/backend/floor.service.ts +84 -0
  56. package/src/backend/index.ts +4 -0
  57. package/src/backend/print-completions.service.ts +11 -0
  58. package/src/backend/printer-file.service.ts +91 -0
  59. package/src/backend/printer-group.service.ts +62 -0
  60. package/src/backend/printer-job.service.ts +20 -0
  61. package/src/backend/printer-settings.service.ts +28 -0
  62. package/src/backend/printers.service.ts +136 -0
  63. package/src/backend/server-private.service.ts +55 -0
  64. package/src/backend/server.api.ts +132 -0
  65. package/src/backend/settings.service.ts +85 -0
  66. package/src/backend/user.service.ts +51 -0
  67. package/src/components/AboutHelp/AboutView.vue +164 -0
  68. package/src/components/CameraGrid/CameraGridView.vue +111 -0
  69. package/src/components/FirstTimeSetup/FirstTimeSetupView.vue +354 -0
  70. package/src/components/Generic/Actions/PrinterConnectionAction.vue +56 -0
  71. package/src/components/Generic/Actions/PrinterCreateAction.vue +22 -0
  72. package/src/components/Generic/Actions/PrinterDeleteAction.vue +29 -0
  73. package/src/components/Generic/Actions/PrinterQuickStopAction.vue +35 -0
  74. package/src/components/Generic/Actions/PrinterSettingsAction.vue +35 -0
  75. package/src/components/Generic/Actions/PrinterUrlAction.vue +24 -0
  76. package/src/components/Generic/Actions/RefreshFilesAction.vue +50 -0
  77. package/src/components/Generic/Actions/SyncPrinterNameAction.vue +36 -0
  78. package/src/components/Generic/Dialogs/AddOrUpdateCameraStreamDialog.vue +131 -0
  79. package/src/components/Generic/Dialogs/AddOrUpdateFloorDialog.vue +141 -0
  80. package/src/components/Generic/Dialogs/AddOrUpdatePrinterDialog.vue +303 -0
  81. package/src/components/Generic/Dialogs/BaseDialog.vue +81 -0
  82. package/src/components/Generic/Dialogs/BatchJsonCreateDialog.vue +109 -0
  83. package/src/components/Generic/Dialogs/BatchReprintDialog.vue +190 -0
  84. package/src/components/Generic/Dialogs/PrinterChecksPanel.vue +37 -0
  85. package/src/components/Generic/Dialogs/PrinterControlDialog.vue +202 -0
  86. package/src/components/Generic/Dialogs/PrinterMaintenanceDialog.vue +130 -0
  87. package/src/components/Generic/Dialogs/YamlImportExportDialog.vue +186 -0
  88. package/src/components/Generic/Dialogs/dialog.constants.ts +19 -0
  89. package/src/components/Generic/FileExplorerSideNav.vue +734 -0
  90. package/src/components/Generic/Loaders/GridLoader.vue +68 -0
  91. package/src/components/Generic/NavigationDrawer.vue +69 -0
  92. package/src/components/Generic/PrintJobsMenu.vue +148 -0
  93. package/src/components/Generic/Snackbars/AppErrorSnackbar.vue +64 -0
  94. package/src/components/Generic/Snackbars/AppInfoSnackbar.vue +63 -0
  95. package/src/components/Generic/Snackbars/AppProgressSnackbar.vue +158 -0
  96. package/src/components/Generic/Vuetify/TooltipButton.vue +47 -0
  97. package/src/components/HelpOverlay/HelpOverlay.vue +57 -0
  98. package/src/components/Login/LoginForm.vue +206 -0
  99. package/src/components/Login/LoginView.spec.ts +64 -0
  100. package/src/components/Login/LoginView.vue +65 -0
  101. package/src/components/Login/Logo.vue +13 -0
  102. package/src/components/Login/PermissionDenied.vue +109 -0
  103. package/src/components/Login/RegistrationForm.vue +207 -0
  104. package/src/components/Login/RegistrationView.vue +17 -0
  105. package/src/components/Login/__snapshots__/LoginView.spec.ts.snap +1051 -0
  106. package/src/components/NotFound/NotFoundView.vue +39 -0
  107. package/src/components/PrintStatistics/PrintStatistics.vue +168 -0
  108. package/src/components/PrintStatistics/PrintStatisticsView.vue +15 -0
  109. package/src/components/PrinterGrid/HomeToolbar.vue +90 -0
  110. package/src/components/PrinterGrid/PrinterGrid.vue +164 -0
  111. package/src/components/PrinterGrid/PrinterGridTile.vue +438 -0
  112. package/src/components/PrinterGrid/PrinterGridView.vue +210 -0
  113. package/src/components/PrinterList/FileControlList.vue +40 -0
  114. package/src/components/PrinterList/PrinterDetails.vue +91 -0
  115. package/src/components/PrinterList/PrintersView.vue +492 -0
  116. package/src/components/Settings/AccountSettings.vue +163 -0
  117. package/src/components/Settings/DiagnosticsSettings.vue +137 -0
  118. package/src/components/Settings/EmergencyCommands.vue +265 -0
  119. package/src/components/Settings/FloorSettings.vue +276 -0
  120. package/src/components/Settings/GridSettings.vue +127 -0
  121. package/src/components/Settings/OctoPrintSettings.vue +188 -0
  122. package/src/components/Settings/ServerProtectionSettings.vue +370 -0
  123. package/src/components/Settings/SettingsView.vue +73 -0
  124. package/src/components/Settings/SoftwareUpgradeSettings.vue +297 -0
  125. package/src/components/Settings/UserManagementSettings.vue +257 -0
  126. package/src/components/TopBar.vue +147 -0
  127. package/src/components.d.ts +70 -0
  128. package/src/directives/file-upload.directive.ts +117 -0
  129. package/src/directives/printer-drop-position.directive.ts +92 -0
  130. package/src/env.d.ts +6 -0
  131. package/src/main.ts +76 -0
  132. package/src/models/batch/reprint.dto.ts +79 -0
  133. package/src/models/batch.model.ts +11 -0
  134. package/src/models/camera-streams/camera-stream.ts +19 -0
  135. package/src/models/floors/floor.model.ts +30 -0
  136. package/src/models/octoprint/connection-options.model.ts +8 -0
  137. package/src/models/plugins/firmware-updates/prusa-firmware-release.model.ts +57 -0
  138. package/src/models/print-completions/print-completions.model.ts +49 -0
  139. package/src/models/printers/crud/create-printer.model.ts +26 -0
  140. package/src/models/printers/file-upload-commands.model.ts +4 -0
  141. package/src/models/printers/gcode/gcode-analysis.model.ts +30 -0
  142. package/src/models/printers/printer-current-job.model.ts +90 -0
  143. package/src/models/printers/printer-file.model.ts +48 -0
  144. package/src/models/printers/printer.model.ts +18 -0
  145. package/src/models/server/client-releases.model.ts +27 -0
  146. package/src/models/server/export-yaml.model.ts +11 -0
  147. package/src/models/server/features.model.ts +37 -0
  148. package/src/models/server/github-rate-limit.model.ts +21 -0
  149. package/src/models/server/version.model.ts +14 -0
  150. package/src/models/settings/printer-file-clean-settings.model.ts +5 -0
  151. package/src/models/settings/server-settings.dto.ts +19 -0
  152. package/src/models/settings/settings.model.ts +57 -0
  153. package/src/models/socketio-messages/socketio-message.model.ts +53 -0
  154. package/src/models/uploads/queued-upload.model.ts +12 -0
  155. package/src/models/user.model.ts +15 -0
  156. package/src/plugins/README.md +3 -0
  157. package/src/plugins/index.ts +17 -0
  158. package/src/plugins/vuetify.ts +53 -0
  159. package/src/router/index.ts +192 -0
  160. package/src/router/route-names.ts +14 -0
  161. package/src/router/utils.ts +23 -0
  162. package/src/shared/alert.events.ts +14 -0
  163. package/src/shared/app.constants.ts +23 -0
  164. package/src/shared/auth.constants.ts +34 -0
  165. package/src/shared/dialog.composable.ts +41 -0
  166. package/src/shared/drag.constants.ts +19 -0
  167. package/src/shared/experimental.constants.ts +1 -0
  168. package/src/shared/http-client.ts +162 -0
  169. package/src/shared/noun-adjectives.data.ts +24 -0
  170. package/src/shared/printer-grid.constants.ts +5 -0
  171. package/src/shared/printer-state.constants.ts +194 -0
  172. package/src/shared/snackbar.composable.ts +66 -0
  173. package/src/shared/socketio.service.ts +104 -0
  174. package/src/store/auth.store.ts +255 -0
  175. package/src/store/connection.store.ts +66 -0
  176. package/src/store/dialog.store.ts +114 -0
  177. package/src/store/features.store.ts +57 -0
  178. package/src/store/floor.store.ts +173 -0
  179. package/src/store/grid.store.ts +10 -0
  180. package/src/store/index.ts +4 -0
  181. package/src/store/printer-state.store.ts +246 -0
  182. package/src/store/printer.store.ts +236 -0
  183. package/src/store/profile.store.ts +25 -0
  184. package/src/store/settings.store.ts +64 -0
  185. package/src/store/test-printer.store.ts +70 -0
  186. package/src/store/uploads.store.ts +75 -0
  187. package/src/styles/README.md +3 -0
  188. package/src/styles/settings.scss +10 -0
  189. package/src/types/global.d.ts +15 -0
  190. package/src/utils/array.utils.ts +15 -0
  191. package/src/utils/date.utils.ts +5 -0
  192. package/src/utils/download-file.util.ts +25 -0
  193. package/src/utils/error.utils.ts +3 -0
  194. package/src/utils/file-size.util.ts +11 -0
  195. package/src/utils/id.type.ts +1 -0
  196. package/src/utils/sentry.util.ts +8 -0
  197. package/src/utils/test.util.ts +30 -0
  198. package/src/utils/time.utils.ts +2 -0
  199. package/src/utils/uploads-state.utils.ts +58 -0
  200. package/src/utils/validation.utils.ts +14 -0
  201. package/src/vite-env.d.ts +7 -0
  202. package/test/setup-axios-mock.ts +15 -0
  203. package/tsconfig.json +47 -0
  204. package/tsconfig.node.json +9 -0
  205. package/vite.config.mts +106 -0
@@ -0,0 +1,370 @@
1
+ <template>
2
+ <v-card>
3
+ <v-toolbar color="primary">
4
+ <v-avatar>
5
+ <v-icon>settings</v-icon>
6
+ </v-avatar>
7
+ <v-toolbar-title> Server Protection Settings </v-toolbar-title>
8
+ </v-toolbar>
9
+ <v-list lines="three">
10
+ <v-list-item v-if="!whitelistSettingsHidden">
11
+ <v-list-item-title> IP Whitelist </v-list-item-title>
12
+ <v-list-item-subtitle>
13
+ <v-alert color="warning">
14
+ <v-icon>info</v-icon> &nbsp; Be cautious, setting the wrong
15
+ whitelist could make you lose access to the server!
16
+ </v-alert>
17
+ Only allow access from specific IP Adresses or subnets. Note:
18
+ 127.0.0.1 will always be allowed access. Examples:
19
+ <br />
20
+ <v-chip size="small"> 192.168 </v-chip>
21
+ <v-chip size="small"> 192.168.1 </v-chip>
22
+ <v-chip size="small"> 192.168.1.1 </v-chip>
23
+ <br />
24
+ <v-row>
25
+ <v-col
26
+ cols="12"
27
+ md="2"
28
+ >
29
+ <v-checkbox
30
+ v-model="whitelistEnabled"
31
+ label="Enable IP Whitelist"
32
+ />
33
+ </v-col>
34
+ </v-row>
35
+ <v-row class="mt-0">
36
+ <v-col
37
+ cols="12"
38
+ md="2"
39
+ >
40
+ <v-text-field
41
+ v-model="ipAddress"
42
+ :disabled="!whitelistEnabled"
43
+ :rules="[ipAddressRule, (val) => !!val]"
44
+ append-icon="add"
45
+ label="IP Address"
46
+ @click:append="appendIpAddress(ipAddress)"
47
+ />
48
+ </v-col>
49
+ <v-col>
50
+ <v-chip-group>
51
+ <v-chip
52
+ v-for="ip in whitelistedIpAddresses"
53
+ :key="ip"
54
+ :disabled="!whitelistEnabled"
55
+ closable
56
+ @click:close="removeIpWhitelist(ip)"
57
+ >
58
+ {{ ip }}
59
+ </v-chip>
60
+ </v-chip-group>
61
+ </v-col>
62
+ </v-row>
63
+ <v-row>
64
+ <v-col>
65
+ <v-btn
66
+ color="default"
67
+ @click="resetWhitelistSettingsToDefault()"
68
+ >
69
+ reset to default
70
+ </v-btn>
71
+ <v-btn
72
+ color="primary"
73
+ @click="setWhitelistSettings()"
74
+ >
75
+ save whitelist settings
76
+ </v-btn>
77
+ </v-col>
78
+ </v-row>
79
+ </v-list-item-subtitle>
80
+ </v-list-item>
81
+
82
+ <v-list-item>
83
+ <v-list-item-title> Login Required </v-list-item-title>
84
+
85
+ <v-list-item-subtitle>
86
+ <v-row>
87
+ <v-col
88
+ cols="12"
89
+ md="2"
90
+ >
91
+ <v-checkbox
92
+ v-model="loginRequired"
93
+ label="Require Login"
94
+ />
95
+ </v-col>
96
+ </v-row>
97
+ <v-row>
98
+ <v-col>
99
+ <v-btn
100
+ color="primary"
101
+ @click="setLoginRequired()"
102
+ >
103
+ save login required setting
104
+ </v-btn>
105
+ </v-col>
106
+ </v-row>
107
+ </v-list-item-subtitle>
108
+ </v-list-item>
109
+
110
+ <v-list-item>
111
+ <v-list-item-title> Registration Enabled </v-list-item-title>
112
+ <v-list-item-subtitle>
113
+ <v-row>
114
+ <v-col
115
+ cols="12"
116
+ md="2"
117
+ >
118
+ <v-checkbox
119
+ v-model="registrationEnabled"
120
+ label="Enable Registration"
121
+ />
122
+ </v-col>
123
+ </v-row>
124
+ <v-row>
125
+ <v-col>
126
+ <v-btn
127
+ color="primary"
128
+ @click="setRegistrationEnabled()"
129
+ >
130
+ save registration enabled setting
131
+ </v-btn>
132
+ </v-col>
133
+ </v-row>
134
+ </v-list-item-subtitle>
135
+ </v-list-item>
136
+
137
+ <v-list-item>
138
+ <v-list-item-title>
139
+ Login Expiry Settings (advanced)
140
+ </v-list-item-title>
141
+
142
+ <v-list-item-subtitle>
143
+ <v-row>
144
+ <v-col
145
+ cols="12"
146
+ md="2"
147
+ >
148
+ <v-text-field
149
+ v-model="jwtExpiresIn"
150
+ :rules="[(val) => !!val && val >= 2 && val <= 120]"
151
+ label="JWT Expiry (minutes)"
152
+ />
153
+ </v-col>
154
+ </v-row>
155
+ <v-row>
156
+ <v-col
157
+ cols="12"
158
+ md="2"
159
+ >
160
+ <v-checkbox
161
+ v-model="refreshTokenAttemptsEnabled"
162
+ label="Enable Refresh Token Attempts"
163
+ @update:model-value="onRefreshTokenEnabledChange()"
164
+ />
165
+ </v-col>
166
+ </v-row>
167
+ <v-row>
168
+ <v-col
169
+ cols="12"
170
+ md="2"
171
+ >
172
+ <v-text-field
173
+ v-model="refreshTokenAttempts"
174
+ :disabled="!refreshTokenAttemptsEnabled"
175
+ :rules="[(val) => !!val && val >= 50]"
176
+ label="Refresh Token Attempts (disabled: -1)"
177
+ type="number"
178
+ />
179
+ </v-col>
180
+ </v-row>
181
+ <v-row>
182
+ <v-col
183
+ cols="12"
184
+ md="2"
185
+ >
186
+ <v-text-field
187
+ v-model="refreshTokenExpiry"
188
+ :rules="[(val) => !!val && val >= 1 && val <= 30]"
189
+ label="Refresh Token Expiry (days)"
190
+ />
191
+ </v-col>
192
+ </v-row>
193
+
194
+ <v-alert color="secondary">
195
+ <v-icon>info</v-icon> &nbsp; Be cautious, setting the wrong expiry
196
+ could make you lose access to the server or make your user
197
+ experience highly degraded!
198
+ </v-alert>
199
+
200
+ <v-row>
201
+ <v-col>
202
+ <v-btn
203
+ color="primary"
204
+ @click="saveLoginExpirySettings()"
205
+ >
206
+ save login expiry settings
207
+ </v-btn>
208
+ <v-btn
209
+ color="default"
210
+ @click="resetLoginExpirySettingsToDefault()"
211
+ >
212
+ reset to default
213
+ </v-btn>
214
+ </v-col>
215
+ </v-row>
216
+ </v-list-item-subtitle>
217
+ </v-list-item>
218
+ </v-list>
219
+ </v-card>
220
+ </template>
221
+
222
+ <script lang="ts" setup>
223
+ import { onMounted, ref } from 'vue'
224
+ import { whitelistSettingsHidden } from '@/shared/experimental.constants'
225
+ import { isValidIPOrMask } from '@/utils/validation.utils'
226
+ import { SettingsService } from '@/backend'
227
+ import { useSnackbar } from '@/shared/snackbar.composable'
228
+ import { useAuthStore } from '@/store/auth.store'
229
+ import { useRouter } from 'vue-router'
230
+ import { RouteNames } from '@/router/route-names'
231
+
232
+ const router = useRouter()
233
+ const snackbar = useSnackbar()
234
+ const authStore = useAuthStore()
235
+
236
+ const ipAddress = ref<string>('')
237
+ const whitelistEnabled = ref<boolean>(false)
238
+ const whitelistedIpAddresses = ref<string[]>([])
239
+
240
+ const loginRequired = ref<boolean>(false)
241
+ const registrationEnabled = ref<boolean>(false)
242
+
243
+ const jwtExpiresIn = ref<number>(3200)
244
+ const refreshTokenAttemptsEnabled = ref<boolean>(false)
245
+ const refreshTokenAttempts = ref<number>(-1)
246
+ const refreshTokenExpiry = ref<number>(14)
247
+
248
+ const ipAddressRule = (val: string) =>
249
+ isValidIPOrMask(val) ? true : 'Not a valid IP Address'
250
+
251
+ async function loadSettings() {
252
+ const settings = await SettingsService.getSettings()
253
+ loginRequired.value = settings.server.loginRequired
254
+ registrationEnabled.value = settings.server.registration
255
+
256
+ ipAddress.value = settings.connection?.clientIp ?? '127.0.0.1'
257
+ whitelistEnabled.value = settings.server.whitelistEnabled
258
+ whitelistedIpAddresses.value = settings.server.whitelistedIpAddresses
259
+
260
+ const sensitiveSettings = await SettingsService.getSettingsSensitive()
261
+ jwtExpiresIn.value = sensitiveSettings.credentials.jwtExpiresIn / 60
262
+ refreshTokenAttemptsEnabled.value =
263
+ sensitiveSettings.credentials.refreshTokenAttempts !== -1
264
+ refreshTokenAttempts.value =
265
+ sensitiveSettings.credentials.refreshTokenAttempts
266
+ refreshTokenExpiry.value =
267
+ sensitiveSettings.credentials.refreshTokenExpiry / 24 / 3600
268
+ }
269
+
270
+ onMounted(async () => {
271
+ await loadSettings()
272
+ })
273
+
274
+ function onRefreshTokenEnabledChange() {
275
+ if (!refreshTokenAttemptsEnabled.value) {
276
+ refreshTokenAttempts.value = -1
277
+ }
278
+ }
279
+
280
+ function removeIpWhitelist(removedIp: string) {
281
+ whitelistedIpAddresses.value = whitelistedIpAddresses.value.filter(
282
+ (ip) => ip.toLowerCase() !== removedIp.toLowerCase()
283
+ )
284
+ }
285
+
286
+ function appendIpAddress(ip: string) {
287
+ if (!isValidIPOrMask(ip)) return
288
+ whitelistedIpAddresses.value.push(ip.toLowerCase())
289
+ }
290
+
291
+ async function resetWhitelistSettingsToDefault() {
292
+ whitelistedIpAddresses.value = ['127.0.0.1', '::12']
293
+ whitelistEnabled.value = false
294
+ await setWhitelistSettings(false)
295
+ snackbar.info('Whitelist settings reset to default')
296
+ }
297
+
298
+ async function setWhitelistSettings(showSuccess = true) {
299
+ await SettingsService.setWhitelistSettings({
300
+ whitelistedIpAddresses: whitelistedIpAddresses.value,
301
+ whitelistEnabled: whitelistEnabled.value
302
+ })
303
+ if (showSuccess) {
304
+ snackbar.info('Whitelist settings updated')
305
+ }
306
+
307
+ await loadSettings()
308
+ }
309
+
310
+ async function setLoginRequired() {
311
+ const loginRequiredVal = loginRequired.value
312
+ if (
313
+ !loginRequiredVal &&
314
+ !confirm('Disabling login will expose your server. Continue?')
315
+ ) {
316
+ return
317
+ }
318
+
319
+ await SettingsService.updateLoginRequiredSettings(loginRequiredVal)
320
+
321
+ await authStore.logout(true)
322
+
323
+ await authStore.checkAuthenticationRequirements()
324
+ if (!loginRequiredVal) {
325
+ await router.push({ name: RouteNames.Home })
326
+ } else {
327
+ await router.push({ name: RouteNames.Login })
328
+ }
329
+ snackbar.info('Login Required settings updated')
330
+ }
331
+
332
+ async function setRegistrationEnabled() {
333
+ await SettingsService.updateRegistrationEnabledSettings(
334
+ registrationEnabled.value
335
+ )
336
+ await authStore.checkAuthenticationRequirements()
337
+ snackbar.info('Registration settings updated')
338
+ }
339
+
340
+ async function resetLoginExpirySettingsToDefault() {
341
+ jwtExpiresIn.value = 120
342
+ refreshTokenAttemptsEnabled.value = false
343
+ refreshTokenAttempts.value = -1
344
+ refreshTokenExpiry.value = 14
345
+ await saveLoginExpirySettings()
346
+ snackbar.info('Login expiry settings reset to default')
347
+ }
348
+
349
+ async function saveLoginExpirySettings(showSnackbar = true) {
350
+ if (jwtExpiresIn.value < 2 || jwtExpiresIn.value > 120) {
351
+ throw new Error('JWT Expiry must be between 2 and 120 minutes')
352
+ }
353
+ if (
354
+ refreshTokenAttemptsEnabled.value &&
355
+ (refreshTokenAttempts.value < 50 || refreshTokenAttempts.value > 1000)
356
+ ) {
357
+ throw new Error('Refresh Token Attempts must be between 50 and 1000')
358
+ }
359
+ if (refreshTokenExpiry.value < 1 || refreshTokenExpiry.value > 30) {
360
+ throw new Error('Refresh Token Expiry must be between 1 and 30 days')
361
+ }
362
+
363
+ await SettingsService.updateCredentialSettings(
364
+ jwtExpiresIn.value * 60,
365
+ refreshTokenAttempts.value,
366
+ refreshTokenExpiry.value * 24 * 3600
367
+ )
368
+ snackbar.info('Login expiry settings updated')
369
+ }
370
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <v-row no-gutters>
3
+ <div>
4
+ <v-navigation-drawer :permanent="true">
5
+ <v-list-item>
6
+ <v-list-item-title class="text-h6"> Settings </v-list-item-title>
7
+ <v-list-item-subtitle> Adjust your Fdm Monster </v-list-item-subtitle>
8
+ </v-list-item>
9
+
10
+ <v-divider />
11
+
12
+ <v-list
13
+ density="compact"
14
+ nav
15
+ >
16
+ <v-list-item
17
+ v-for="item in items"
18
+ :key="item.title"
19
+ :to="item.path"
20
+ link
21
+ :prepend-icon="item.icon"
22
+ :title="item.title"
23
+ router-link
24
+ />
25
+ </v-list>
26
+ </v-navigation-drawer>
27
+ </div>
28
+
29
+ <router-view class="grow" />
30
+ </v-row>
31
+ </template>
32
+
33
+ <script lang="ts" setup>
34
+ const items = ref([
35
+ {
36
+ title: 'Grid',
37
+ icon: 'grid_on',
38
+ path: '/settings/grid'
39
+ },
40
+ {
41
+ title: 'Floors',
42
+ icon: 'house_siding',
43
+ path: '/settings/floors'
44
+ },
45
+ {
46
+ title: 'User Management',
47
+ icon: 'group',
48
+ path: '/settings/user-management'
49
+ },
50
+ {
51
+ title: 'Account Settings',
52
+ icon: 'account_circle',
53
+ path: '/settings/account'
54
+ },
55
+ {
56
+ title: 'Server Protection',
57
+ icon: 'security',
58
+ path: '/settings/server-protection'
59
+ },
60
+ { title: 'OctoPrint Settings', icon: 'image', path: '/settings/octoprint' },
61
+ {
62
+ title: 'Emergency Commands',
63
+ icon: 'warning',
64
+ path: '/settings/emergency-commands'
65
+ },
66
+ {
67
+ title: 'Software Upgrade',
68
+ icon: 'upgrade',
69
+ path: '/settings/software-upgrade'
70
+ },
71
+ { title: 'Diagnostics', icon: 'bug_report', path: '/settings/diagnostics' }
72
+ ])
73
+ </script>