Skip to content

Commit b98a701

Browse files
committed
Added login skip feature
Modified button, tracking credentials saved and login skipped outside LoginPage, disabling command execution which uses login objects.
1 parent 2ea234d commit b98a701

File tree

12 files changed

+283
-134
lines changed

12 files changed

+283
-134
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lazy-admin",
3-
"version": "0.4.2",
3+
"version": "0.4.3",
44
"description": "GUI for PowerShell scripts to simplify day to day IT tasks.",
55
"productName": "Lazy Admin",
66
"cordovaId": "eu.houby-studio.lazy-admin",
@@ -50,4 +50,4 @@
5050
"browserslist": [
5151
"last 1 version, not dead, ie >= 11"
5252
]
53-
}
53+
}

scripts-definitions/base-module-example.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@
479479
"icon": "mdi-powershell",
480480
"returns": "PSObject",
481481
"insidePsSession": false,
482-
"usesLoginObjects": false,
482+
"usesLoginObjects": true,
483483
"friendlyName": {
484484
"default": "Nothing really",
485485
"en-us": "Nothing really",

src/i18n/cs-cz/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ export default {
55
usernameRequired: 'Zadejte přihlašovací jméno!', // Used in: LoginPage.vue
66
password: 'Heslo', // Used in: LoginPage.vue
77
passwordRequired: 'Zadejte přihlašovací heslo!', // Used in: LoginPage.vue
8-
login: 'Vstoupit', // Used in: LoginPage.vue
8+
login: 'Přihlásit', // Used in: LoginPage.vue
9+
loginSkip: 'Přeskočit', // Used in: LoginPage.vue
910
language: 'Jazyk', // Used in: LoginPage.vue
1011
changeUser: 'Jiný uživatel', // Used in: LoginPage.vue
1112
install: 'Instalovat', // Used in: LoginPage.vue, FullLayout.vue
@@ -14,6 +15,7 @@ export default {
1415
pwshMissing: 'Nelze nalézt PowerShell Core. Používá se záložní Windows PowerShell.', // Used in: LoginPage.vue
1516
wrongUsernameOrPassword: 'Špatné přihlašovací jméno nebo heslo.', // Used in: LoginPage.vue
1617
foundsavedCredential: 'Nalezeny přihlašovací údaje pro uživatele {usr}.', // Used in: LoginPage.vue
18+
failedToLogin: 'Nepodařilo se přihlásení s neznámou chybou.', // Used in: LoginPage.vue
1719
search: 'Vyhledat', // Used in: FullLayout.vue
1820
history: 'Historie', // Used in: FullLayout.vue
1921
visibleGroups: 'Zobrazované příkazy', // Used in: FullLayout.vue

src/i18n/en-us/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export default {
66
password: 'Password', // Used in: LoginPage.vue
77
passwordRequired: 'Login password is required!', // Used in: LoginPage.vue
88
login: 'Login', // Used in: LoginPage.vue
9+
loginSkip: 'Skip', // Used in: LoginPage.vue
910
language: 'Language', // Used in: LoginPage.vue
1011
changeUser: 'Change User', // Used in: LoginPage.vue
1112
install: 'Install', // Used in: LoginPage.vue, FullLayout.vue
@@ -14,6 +15,7 @@ export default {
1415
pwshMissing: 'Couldn\'t find PowerShell Core, default. Using fallback Windows PowerShell.', // Used in: LoginPage.vue
1516
wrongUsernameOrPassword: 'Wrong username or password.', // Used in: LoginPage.vue
1617
foundsavedCredential: 'Found stored credentials for user {usr}.', // Used in: LoginPage.vue
18+
failedToLogin: 'Login failed with unknown error.', // Used in: LoginPage.vue
1719
search: 'Search', // Used in: FullLayout.vue
1820
history: 'History', // Used in: FullLayout.vue
1921
visibleGroups: 'Shown commands', // Used in: FullLayout.vue

src/layouts/FullLayout.vue

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,51 @@
339339
/>
340340
</div>
341341
</div>
342+
<!-- TOOLS RELATED TO APP NAVIGATION -->
343+
<q-toolbar-title class="q-px-none">
344+
<q-icon name="navigation" /> Control
345+
</q-toolbar-title>
346+
<div class="row text-center">
347+
<div class="col-xs-12 col-sm-6 col-md-3">
348+
<q-btn
349+
to="/"
350+
color="primary"
351+
label="Log out"
352+
style="width: 90%"
353+
class="q-mb-sm"
354+
no-wrap
355+
/>
356+
</div>
357+
<div class="col-xs-12 col-sm-6 col-md-3">
358+
<div class="text-h6">
359+
<q-btn
360+
color="primary"
361+
label="-"
362+
style="width: 90%"
363+
class="q-mb-sm"
364+
no-wrap
365+
/>
366+
</div>
367+
</div>
368+
<div class="col-xs-12 col-sm-6 col-md-3">
369+
<q-btn
370+
color="primary"
371+
label="-"
372+
style="width: 90%"
373+
class="q-mb-sm"
374+
no-wrap
375+
/>
376+
</div>
377+
<div class="col-xs-12 col-sm-6 col-md-3">
378+
<q-btn
379+
color="primary"
380+
label="-"
381+
style="width: 90%"
382+
class="q-mb-sm"
383+
no-wrap
384+
/>
385+
</div>
386+
</div>
342387
</q-card-section>
343388
<q-page-sticky
344389
:offset="[0, 0]"

src/pages/LoginPage.vue

Lines changed: 86 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@
77
class="q-pa-lg shadow-1"
88
>
99
<q-form
10-
@submit="login"
10+
@submit="showSkipLogin ? skipLogin() : login()"
1111
ref="loginform"
1212
class="q-gutter-md"
1313
>
1414
<q-card-section>
1515

1616
<q-input
17-
square
18-
filled
1917
v-model="username"
20-
type="text"
21-
ref="username"
2218
:disable="credentialsSaved"
2319
:label="$t('username')"
2420
:class="shake"
21+
:rules="showSkipLogin ? [ val => val.length >= 0 ] : [ val => val && val.length > 0 || $t('usernameRequired') ]"
22+
type="text"
23+
ref="username"
24+
square
25+
filled
2526
lazy-rules
2627
no-error-icon
27-
:rules="[ val => val && val.length > 0 || $t('usernameRequired') ]"
2828
>
2929
<template v-slot:append>
3030
<q-icon name="person" />
@@ -36,51 +36,55 @@
3636
mode="out-in"
3737
>
3838
<div
39-
style="q-gutter-md"
4039
v-if="credentialsSaved"
40+
style="q-gutter-md"
4141
>
4242
<q-btn
43+
:label="$t('changeUser')"
44+
@click="credentialsSaved = false"
4345
unelevated
4446
color="light"
4547
size="lg"
4648
class="full-width"
47-
:label="$t('changeUser')"
48-
@click="credentialsSaved = false"
4949
/>
5050
</div>
5151

5252
<q-input
53-
square
54-
filled
55-
v-model="password"
5653
v-else
54+
v-model="password"
5755
:type="isPwd ? 'password' : 'text'"
5856
:label="$t('password')"
57+
:rules="showSkipLogin ? [ val => val.length >= 0 ] : [ val => val && val.length > 0 || $t('passwordRequired') ]"
58+
square
59+
filled
5960
lazy-rules
6061
no-error-icon
61-
:rules="[ val => val && val.length > 0 || $t('passwordRequired') ]"
6262
>
6363
<template v-slot:append>
6464
<q-icon
6565
:name="isPwd ? 'visibility_off' : 'visibility'"
66-
class="cursor-pointer"
6766
@click="isPwd = !isPwd"
67+
class="cursor-pointer"
6868
/>
6969
</template>
7070
</q-input>
7171
</transition>
7272
</q-card-section>
7373
<q-card-actions class="q-px-md">
74-
<q-btn
75-
autofocus
76-
unelevated
74+
<q-btn-dropdown
75+
v-model="showSkipLogin"
76+
:label="showSkipLogin ? $t('loginSkip') : $t('login')"
77+
:disable="loginButtonDisabled"
78+
@input="resetValidation"
79+
dropdown-icon="mdi-skip-next"
7780
color="primary"
7881
size="lg"
7982
class="full-width"
8083
type="submit"
8184
ref="login"
82-
:label="$t('login')"
83-
:disable="loginButtonDisabled"
85+
unelevated
86+
persistent
87+
split
8488
/>
8589
</q-card-actions>
8690
</q-form>
@@ -111,8 +115,8 @@ export default {
111115
username: '',
112116
password: '',
113117
loginButtonDisabled: false,
118+
showSkipLogin: false,
114119
shakeUsername: false,
115-
credentialsSaved: false,
116120
isPwd: true,
117121
langOptions: [
118122
{ value: 'en-us', label: 'English' },
@@ -121,7 +125,7 @@ export default {
121125
}
122126
},
123127
computed: {
124-
...mapGetters('lazystore', ['getLanguage']),
128+
...mapGetters('lazystore', ['getLanguage', 'getLoginSkipped', 'getCredentialsSaved']),
125129
shake: {
126130
get () {
127131
// Add classes to trigger animations on username field when username is found in credential store
@@ -130,18 +134,66 @@ export default {
130134
},
131135
language: {
132136
get () {
133-
// retrieve language settings from mapped getter
134137
return this.getLanguage
135138
},
136139
set (val) {
137-
// set selected language to store
138140
this.$store.dispatch('lazystore/setLanguage', val)
139141
}
142+
},
143+
loginSkipped: {
144+
get () {
145+
return this.getLoginSkipped
146+
},
147+
set (val) {
148+
this.$store.dispatch('lazystore/setLoginSkipped', val)
149+
}
150+
},
151+
credentialsSaved: {
152+
get () {
153+
return this.getCredentialsSaved
154+
},
155+
set (val) {
156+
this.$store.dispatch('lazystore/setCredentialsSaved', val)
157+
}
140158
}
141159
},
142160
methods: {
161+
resetForm (credentialsProvided) {
162+
this.loginButtonDisabled = false
163+
this.credentialsSaved = false
164+
this.username = ''
165+
this.password = ''
166+
this.$refs.loginform.resetValidation()
167+
this.$refs.username.focus()
168+
this.$q.notify({
169+
timeout: 5000,
170+
multiLine: false,
171+
type: 'negative',
172+
icon: 'error',
173+
message: credentialsProvided ? this.$t('wrongUsernameOrPassword') : this.$t('failedToLogin'),
174+
actions: [
175+
{ label: this.$t('dismiss'), color: 'white' }
176+
]
177+
})
178+
},
179+
resetValidation () {
180+
this.$refs.loginform.resetValidation()
181+
},
182+
skipLogin () {
183+
this.loginButtonDisabled = true
184+
this.loginSkipped = true
185+
console.log('Skipping login, certain commands may be unavailable.')
186+
this.$pwsh.shell.addCommand(`$Global:CredentialObject = [System.Management.Automation.PSCredential]::Empty`)
187+
this.$pwsh.shell.invoke().then(output => {
188+
this.$router.push({ path: '/scripts' })
189+
}).catch(e => {
190+
console.error(`Failed to create empty Credential Object. Error message: ${e}`)
191+
this.resetForm(false)
192+
})
193+
},
143194
login () {
144195
this.loginButtonDisabled = true // Disable button during login attempt
196+
this.loginSkipped = false
145197
// Invoke function with either credential object or username and password
146198
if (this.credentialsSaved) {
147199
console.log(`Creating new PowerShell session with saved credentials for user "${this.username}".`)
@@ -159,28 +211,18 @@ export default {
159211
}
160212
if (data.error) {
161213
console.error(`Failed to create new PowerShell session with supplied credentials. Error message: ${output}`)
162-
this.loginButtonDisabled = false
163-
this.credentialsSaved = false
164-
this.username = ''
165-
this.password = ''
166-
this.$refs.loginform.resetValidation()
167-
this.$refs.username.focus()
168-
this.$q.notify({
169-
timeout: 5000,
170-
multiLine: false,
171-
type: 'negative',
172-
icon: 'error',
173-
message: this.$t('wrongUsernameOrPassword'),
174-
actions: [
175-
{ label: this.$t('dismiss'), color: 'white' }
176-
]
177-
})
214+
this.resetForm(true)
178215
} else {
179216
console.log(data.output) // Should write 'New Powershell session created succesfully.' from PS Function output
180217
// Route to main screen
181218
if (!this.credentialsSaved) {
182219
this.$pwsh.shell.addCommand(`if (Get-Command New-StoredCredential -ErrorAction SilentlyContinue) {New-StoredCredential -Target 'Lazy Admin' -UserName '${this.username}' -Password '${this.password}' -Comment 'Administrator credentials for Lazy Admin Utility.' -Type Generic -Persist LocalMachine | Out-Null}`)
183-
this.$pwsh.shell.invoke()
220+
this.$pwsh.shell.invoke().then(o => {
221+
console.log('Succesfully saved credentials to Credential Manager.')
222+
this.credentialsSaved = true
223+
}).catch(e => {
224+
console.error(`Failed to save credentials to Credential Manager. Error message: ${e}`)
225+
})
184226
}
185227
// Succesfully created session, push login and session commands to private pwsh variable
186228
if (this.credentialsSaved) {
@@ -190,6 +232,9 @@ export default {
190232
}
191233
this.$router.push({ path: '/scripts' })
192234
}
235+
}).catch(e => {
236+
console.error(`Failed to create new PowerShell session with supplied credentials. Error message: ${e}`)
237+
this.resetForm(false)
193238
})
194239
},
195240
pwshFallbackNotify () {
@@ -218,6 +263,7 @@ export default {
218263
this.$q.loading.show()
219264
// Insert throttle to button functions
220265
this.login = throttle(this.login, 800)
266+
this.skipLogin = throttle(this.skipLogin, 800)
221267
console.log(`Application started by user ${this.$q.electron.remote.process.env.USERDOMAIN}\\${this.$q.electron.remote.process.env.USERNAME} on computer ${this.$q.electron.remote.process.env.COMPUTERNAME}`)
222268
// Try to load saved credentials from Credential Manager
223269
this.$pwsh.shell.addCommand(GetSavedCredentials)

0 commit comments

Comments
 (0)