mirror of https://github.com/rancher/dashboard.git
Merge pull request #3351 from westlywright/bug.user.change.password
Add `userMustChangePassword` Handling
This commit is contained in:
commit
309ef29dcb
|
|
@ -776,7 +776,7 @@ changePassword:
|
|||
deleteKeys:
|
||||
label: Delete all existing API keys
|
||||
changeOnLogin:
|
||||
label: Ask user to change their password on first login
|
||||
label: Ask user to change their password on next login
|
||||
generatePassword:
|
||||
label: Generate a random password
|
||||
currentPassword:
|
||||
|
|
@ -2594,7 +2594,7 @@ probe:
|
|||
placeholder: Select a check type
|
||||
|
||||
project:
|
||||
members:
|
||||
members:
|
||||
label: Members
|
||||
user: User
|
||||
role: Role
|
||||
|
|
@ -3133,13 +3133,16 @@ servicesPage:
|
|||
label: Service Type
|
||||
|
||||
setup:
|
||||
welcome: Welcome to {vendor}!
|
||||
setPassword: The first order of business is to set a strong password for the default <code>admin</code> user. We suggest using this random one generated just for you, but enter your own if you like.
|
||||
newPassword: New Password
|
||||
confirmPassword: Confirm New Password
|
||||
useRandom: Use a randomly generated password
|
||||
useManual: Set a specific password to use
|
||||
defaultPasswordError: It looks like this is your first time visting the Rancher UI, but the local admin account password is already set to something unique. Log in with that account below to continue the setup process.
|
||||
eula: I agree to the <a href="https://rancher.com/eula" target="_blank" rel="noopener noreferrer nofollow">terms and conditions</a> for using Rancher.
|
||||
newPassword: New Password
|
||||
newUserSetPassword: The first order of business is to set a strong password. We suggest using this random one generated just for you, but enter your own if you like.
|
||||
serverUrl:
|
||||
label: Server URL
|
||||
skip: Skip
|
||||
tip: What URL should be used for this Rancher installation? All the nodes in your clusters will need to be able to reach this. You can skip setting this for now, and update it later in General Settings>Advanced Settings.
|
||||
setPassword: The first order of business is to set a strong password for the default <code>{username}</code> user. We suggest using this random one generated just for you, but enter your own if you like.
|
||||
telemetry:
|
||||
label: Allow collection of anonymous statistics to help us improve Rancher
|
||||
tip: 'Rancher Labs would like to collect a bit of anonymized information
|
||||
|
|
@ -3148,11 +3151,9 @@ setup:
|
|||
what specific resources or endpoints you are deploying is included.
|
||||
Once enabled you can view exactly what data will be sent at <code>/v1-telemetry</code>.
|
||||
<a href="https://rancher.com/docs/rancher/v2.x/en/faq/telemetry/" target="_blank" rel="noopener noreferrer nofollow">More Info</a>'
|
||||
eula: I agree to the <a href="https://rancher.com/eula" target="_blank" rel="noopener noreferrer nofollow">terms and conditions</a> for using Rancher.
|
||||
serverUrl:
|
||||
label: Server URL
|
||||
tip: What URL should be used for this Rancher installation? All the nodes in your clusters will need to be able to reach this. You can skip setting this for now, and update it later in General Settings>Advanced Settings.
|
||||
skip: Skip
|
||||
useManual: Set a specific password to use
|
||||
useRandom: Use a randomly generated password
|
||||
welcome: Welcome to {vendor}!
|
||||
|
||||
sortableTable:
|
||||
actionAvailability:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ export default {
|
|||
type: String,
|
||||
default: null
|
||||
},
|
||||
mustChangePassword: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
async fetch() {
|
||||
if (this.isChange) {
|
||||
|
|
@ -27,11 +31,11 @@ export default {
|
|||
type: NORMAN.USER,
|
||||
opt: { url: '/v3/users', filter: { me: true } }
|
||||
});
|
||||
const user = users?.[0];
|
||||
|
||||
if (users && users.length === 1) {
|
||||
this.username = users[0].username;
|
||||
}
|
||||
this.username = user?.username;
|
||||
}
|
||||
this.userChangeOnLogin = this.mustChangePassword;
|
||||
},
|
||||
data(ctx) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ export default {
|
|||
ref="changePassword"
|
||||
v-model="form.password"
|
||||
:mode="mode"
|
||||
:must-change-password="value.mustChangePassword"
|
||||
@valid="validation.password = $event"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -93,10 +93,10 @@ export default async function({
|
|||
|
||||
if (ok) {
|
||||
if (initialPass) {
|
||||
return redirect({ name: 'auth-setup', query: { [SETUP]: initialPass } });
|
||||
} else {
|
||||
return redirect({ name: 'auth-setup' });
|
||||
store.dispatch('auth/setInitialPass', initialPass);
|
||||
}
|
||||
|
||||
return redirect({ name: 'auth-setup' });
|
||||
} else {
|
||||
const t = store.getters['i18n/t'];
|
||||
|
||||
|
|
@ -125,6 +125,13 @@ export default async function({
|
|||
}
|
||||
|
||||
if ( store.getters['auth/enabled'] !== false && !store.getters['auth/loggedIn'] ) {
|
||||
await store.dispatch('auth/getUser');
|
||||
const v3User = store.getters['auth/v3User'] || {};
|
||||
|
||||
if (v3User?.mustChangePassword) {
|
||||
return redirect({ name: 'auth-setup' });
|
||||
}
|
||||
|
||||
// In newer versions the API calls return the auth state instead of having to make a new call all the time.
|
||||
const fromHeader = store.getters['auth/fromHeader'];
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { configType } from '@/models/management.cattle.io.authconfig';
|
|||
import { mapGetters } from 'vuex';
|
||||
import { importLogin } from '@/utils/dynamic-importer';
|
||||
import { _ALL_IF_AUTHED } from '@/plugins/steve/actions';
|
||||
import { MANAGEMENT } from '@/config/types';
|
||||
import { MANAGEMENT, NORMAN } from '@/config/types';
|
||||
import { SETTING } from '@/config/settings';
|
||||
import { LOGIN_ERRORS } from '@/store/auth';
|
||||
import { getVendor, getProduct, setVendor } from '../../config/private-label';
|
||||
|
|
@ -190,6 +190,18 @@ export default {
|
|||
password: this.password
|
||||
}
|
||||
});
|
||||
|
||||
const user = await this.$store.dispatch('rancher/findAll', {
|
||||
type: NORMAN.USER,
|
||||
opt: { url: '/v3/users?me=true' }
|
||||
});
|
||||
|
||||
if (!!user?.[0]) {
|
||||
this.$store.dispatch('auth/gotUser', user[0]);
|
||||
|
||||
this.needsSetup = this.needsSetup || user[0].mustChangePassword;
|
||||
}
|
||||
|
||||
if ( this.remember ) {
|
||||
this.$cookies.set(USERNAME, this.username, {
|
||||
encode: x => x,
|
||||
|
|
@ -202,7 +214,8 @@ export default {
|
|||
}
|
||||
|
||||
if (this.needsSetup) {
|
||||
this.$router.push({ name: 'auth-setup', query: { setup: this.password } });
|
||||
this.$store.dispatch('auth/setInitialPass', this.password);
|
||||
this.$router.push({ name: 'auth-setup' });
|
||||
} else {
|
||||
this.$router.replace('/');
|
||||
}
|
||||
|
|
@ -318,7 +331,12 @@ export default {
|
|||
}
|
||||
|
||||
.login-messages {
|
||||
height: 20px
|
||||
height: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.text-error {
|
||||
max-width: 80%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { randomStr } from '@/utils/string';
|
|||
import LabeledInput from '@/components/form/LabeledInput';
|
||||
import CopyToClipboard from '@/components/CopyToClipboard';
|
||||
import AsyncButton from '@/components/AsyncButton';
|
||||
import { SETUP } from '@/config/query-params';
|
||||
import { LOGGED_OUT, SETUP } from '@/config/query-params';
|
||||
import { NORMAN, MANAGEMENT } from '@/config/types';
|
||||
import { findBy } from '@/utils/array';
|
||||
import Checkbox from '@/components/form/Checkbox';
|
||||
|
|
@ -12,11 +12,24 @@ import RadioGroup from '@/components/form/RadioGroup';
|
|||
import { setSetting, SETTING } from '@/config/settings';
|
||||
import { _ALL_IF_AUTHED } from '@/plugins/steve/actions';
|
||||
import { isDevBuild } from '@/utils/version';
|
||||
import { exceptionToErrorsArray } from '@/utils/error';
|
||||
|
||||
const calcIsFirstLogin = (store) => {
|
||||
const firstLoginSetting = store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.FIRST_LOGIN);
|
||||
|
||||
return firstLoginSetting?.value === 'true';
|
||||
};
|
||||
|
||||
const calcMustChangePassword = async(store) => {
|
||||
await store.dispatch('auth/getUser');
|
||||
|
||||
return store.getters['auth/v3User']?.mustChangePassword;
|
||||
};
|
||||
|
||||
export default {
|
||||
layout: 'unauthenticated',
|
||||
|
||||
async middleware({ store, redirect } ) {
|
||||
async middleware({ store, redirect, route } ) {
|
||||
try {
|
||||
await store.dispatch('management/findAll', {
|
||||
type: MANAGEMENT.SETTING,
|
||||
|
|
@ -27,11 +40,26 @@ export default {
|
|||
} catch (e) {
|
||||
}
|
||||
|
||||
const firstLoginSetting = store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.FIRST_LOGIN);
|
||||
const isFirstLogin = calcIsFirstLogin(store);
|
||||
const mustChangePassword = calcMustChangePassword(store);
|
||||
|
||||
if (firstLoginSetting?.value !== 'true') {
|
||||
return redirect('/');
|
||||
if (isFirstLogin) {
|
||||
// Always show setup if this is the first log in
|
||||
return;
|
||||
} else if (mustChangePassword) {
|
||||
// If the password needs changing and this isn't the first log in ensure we have the password
|
||||
if (!!store.getters['auth/initialPass']) {
|
||||
// Got it... show setup
|
||||
return;
|
||||
}
|
||||
// Haven't got it... redirect to log in so we get it
|
||||
await store.dispatch('auth/logout', null, { root: true });
|
||||
|
||||
return redirect(302, `/auth/login?${ LOGGED_OUT }`);
|
||||
}
|
||||
|
||||
// For all other cases we don't need to show setup
|
||||
return redirect('/');
|
||||
},
|
||||
|
||||
components: {
|
||||
|
|
@ -51,8 +79,10 @@ export default {
|
|||
}
|
||||
|
||||
const principals = await store.dispatch('rancher/findAll', { type: NORMAN.PRINCIPAL, opt: { url: '/v3/principals' } });
|
||||
const me = findBy(principals, 'me', true);
|
||||
|
||||
const current = route.query[SETUP] || 'admin';
|
||||
const current = route.query[SETUP] || store.getters['auth/initialPass'] || 'admin';
|
||||
const v3User = store.getters['auth/v3User'] ?? {};
|
||||
|
||||
let serverUrl;
|
||||
|
||||
|
|
@ -64,17 +94,24 @@ export default {
|
|||
serverUrl = window.location.origin;
|
||||
}
|
||||
|
||||
const isFirstLogin = calcIsFirstLogin(store);
|
||||
const mustChangePassword = calcMustChangePassword(store);
|
||||
|
||||
return {
|
||||
vendor: getVendor(),
|
||||
product: getProduct(),
|
||||
step: parseInt(route.query.step, 10) || 1,
|
||||
|
||||
useRandom: false,
|
||||
haveCurrent: !!current,
|
||||
username: 'admin',
|
||||
useRandom: true,
|
||||
haveCurrent: !!current,
|
||||
username: me?.loginName || 'admin',
|
||||
mustSetup: isFirstLogin,
|
||||
mustChangePassword: isFirstLogin || mustChangePassword,
|
||||
current,
|
||||
password: '',
|
||||
confirm: '',
|
||||
password: randomStr(),
|
||||
confirm: '',
|
||||
|
||||
v3User,
|
||||
|
||||
serverUrl,
|
||||
|
||||
|
|
@ -89,7 +126,7 @@ export default {
|
|||
|
||||
computed: {
|
||||
passwordSubmitDisabled() {
|
||||
if (!this.eula) {
|
||||
if (!this.eula && this.mustSetup) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -138,13 +175,15 @@ export default {
|
|||
methods: {
|
||||
async finishPassword(buttonCb) {
|
||||
try {
|
||||
await this.$store.dispatch('loadManagement');
|
||||
if (this.mustSetup) {
|
||||
await this.$store.dispatch('loadManagement');
|
||||
|
||||
await Promise.all([
|
||||
setSetting(this.$store, SETTING.EULA_AGREED, (new Date()).toISOString() ),
|
||||
setSetting(this.$store, SETTING.TELEMETRY, this.telemetry ? 'in' : 'out'),
|
||||
setSetting(this.$store, SETTING.FIRST_LOGIN, 'false'),
|
||||
]);
|
||||
await Promise.all([
|
||||
setSetting(this.$store, SETTING.EULA_AGREED, (new Date()).toISOString() ),
|
||||
setSetting(this.$store, SETTING.TELEMETRY, this.telemetry ? 'in' : 'out'),
|
||||
setSetting(this.$store, SETTING.FIRST_LOGIN, 'false'),
|
||||
]);
|
||||
}
|
||||
|
||||
await this.$store.dispatch('rancher/request', {
|
||||
url: '/v3/users?action=changepassword',
|
||||
|
|
@ -154,10 +193,22 @@ export default {
|
|||
newPassword: this.password
|
||||
},
|
||||
});
|
||||
this.step = 2;
|
||||
buttonCb(true);
|
||||
|
||||
const user = this.v3User;
|
||||
|
||||
user.mustChangePassword = false;
|
||||
this.$store.dispatch('auth/gotUser', user);
|
||||
|
||||
if (!this.mustSetup && this.mustChangePassword) {
|
||||
buttonCb(true);
|
||||
this.done();
|
||||
} else {
|
||||
this.step = 2;
|
||||
buttonCb(true);
|
||||
}
|
||||
} catch (err) {
|
||||
buttonCb(false);
|
||||
this.errors = exceptionToErrorsArray(err);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -177,77 +228,90 @@ export default {
|
|||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="setup">
|
||||
<div class="row">
|
||||
<div class="col span-6">
|
||||
<h1 class="text-center">
|
||||
{{ t('setup.welcome', {product}) }}
|
||||
</h1>
|
||||
<div class="col span-6 form-col">
|
||||
<div>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-center">
|
||||
{{ t('setup.welcome', {product}) }}
|
||||
</h1>
|
||||
|
||||
<template v-if="step===1">
|
||||
<p class="text-center mb-40 mt-20 setup-title">
|
||||
<t k="setup.setPassword" :raw="true" />
|
||||
</p>
|
||||
<template v-if="step===1">
|
||||
<p
|
||||
class="text-center mb-40 mt-20 setup-title"
|
||||
v-html="t(mustSetup ? 'setup.setPassword' : 'setup.newUserSetPassword', { username }, true)"
|
||||
></p>
|
||||
|
||||
<!-- For password managers... -->
|
||||
<input type="hidden" name="username" autocomplete="username" :value="username" />
|
||||
<div class="mb-20">
|
||||
<RadioGroup v-model="useRandom" name="password-mode" :options="[{label: t('setup.useRandom'), value: true}, {label: t('setup.useManual'), value: false}]" />
|
||||
</div>
|
||||
<div class="mb-20">
|
||||
<!-- For password managers... -->
|
||||
<input type="hidden" name="username" autocomplete="username" :value="username" />
|
||||
<div class="mb-20">
|
||||
<RadioGroup v-model="useRandom" name="password-mode" :options="[{label: t('setup.useRandom'), value: true}, {label: t('setup.useManual'), value: false}]" />
|
||||
</div>
|
||||
<div class="mb-20">
|
||||
<LabeledInput
|
||||
ref="password"
|
||||
v-model.trim="password"
|
||||
:type="useRandom ? 'text' : 'password'"
|
||||
:disabled="useRandom"
|
||||
label-key="setup.newPassword"
|
||||
>
|
||||
<template v-if="useRandom" #suffix>
|
||||
<div class="addon" style="padding: 0 0 0 12px;">
|
||||
<CopyToClipboard :text="password" class="btn-sm" />
|
||||
</div>
|
||||
</template>
|
||||
</LabeledInput>
|
||||
</div>
|
||||
<LabeledInput
|
||||
ref="password"
|
||||
v-model.trim="password"
|
||||
:type="useRandom ? 'text' : 'password'"
|
||||
:disabled="useRandom"
|
||||
label-key="setup.newPassword"
|
||||
>
|
||||
<template v-if="useRandom" #suffix>
|
||||
<div class="addon" style="padding: 0 0 0 12px;">
|
||||
<CopyToClipboard :text="password" class="btn-sm" />
|
||||
</div>
|
||||
</template>
|
||||
</LabeledInput>
|
||||
</div>
|
||||
<LabeledInput
|
||||
v-show="!useRandom"
|
||||
v-model.trim="confirm"
|
||||
autocomplete="new-password"
|
||||
type="password"
|
||||
label-key="setup.confirmPassword"
|
||||
/>
|
||||
v-show="!useRandom"
|
||||
v-model.trim="confirm"
|
||||
autocomplete="new-password"
|
||||
type="password"
|
||||
label-key="setup.confirmPassword"
|
||||
/>
|
||||
|
||||
<hr class="mt-40 mb-40 " />
|
||||
<div v-if="mustSetup">
|
||||
<div class="checkbox mt-40">
|
||||
<Checkbox v-model="telemetry" :label="t('setup.telemetry.label')" type="checkbox" />
|
||||
<i v-tooltip="{content:t('setup.telemetry.tip', {}, true), delay: {hide:500}, autoHide: false}" class="icon icon-info" />
|
||||
</div>
|
||||
<div class="checkbox pt-10 eula">
|
||||
<Checkbox v-model="eula" type="checkbox" />
|
||||
<span v-html="t('setup.eula', {}, true)"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<Checkbox v-model="telemetry" :label="t('setup.telemetry.label')" type="checkbox" />
|
||||
<i v-tooltip="{content:t('setup.telemetry.tip', {}, true), delay: {hide:500}, autoHide: false}" class="icon icon-info" />
|
||||
</div>
|
||||
<div class="checkbox pt-10 eula">
|
||||
<Checkbox v-model="eula" type="checkbox" />
|
||||
<span v-html="t('setup.eula', {}, true)"></span>
|
||||
</div>
|
||||
<div class="text-center mt-20">
|
||||
<AsyncButton key="passwordSubmit" type="submit" mode="continue" :disabled="passwordSubmitDisabled" @click="finishPassword" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="text-center mt-20">
|
||||
<AsyncButton key="passwordSubmit" type="submit" mode="continue" :disabled="passwordSubmitDisabled" @click="finishPassword" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p>
|
||||
<t k="setup.serverUrl.tip" :raw="true" />
|
||||
</p>
|
||||
<div class="mt-20">
|
||||
<LabeledInput v-model="serverUrl" :label="t('setup.serverUrl.label')" />
|
||||
</div>
|
||||
<div class="text-center mt-20">
|
||||
<button type="button" class="btn role-link" @click="done">
|
||||
{{ t('setup.serverUrl.skip') }}
|
||||
</button>
|
||||
<AsyncButton type="submit" mode="continue" @click="setServerUrl" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<p>
|
||||
<t k="setup.serverUrl.tip" :raw="true" />
|
||||
</p>
|
||||
<div class="mt-20">
|
||||
<LabeledInput v-model="serverUrl" :label="t('setup.serverUrl.label')" />
|
||||
<div class="setup-errors mt-20">
|
||||
<h4 v-for="err in errors" :key="err" class="text-error text-center">
|
||||
{{ err }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="text-center mt-20">
|
||||
<button type="button" class="btn role-link" @click="done">
|
||||
{{ t('setup.serverUrl.skip') }}
|
||||
</button>
|
||||
<AsyncButton type="submit" mode="continue" @click="setServerUrl" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col span-6 landscape" />
|
||||
|
|
@ -275,7 +339,6 @@ export default {
|
|||
overflow: hidden;
|
||||
|
||||
.row {
|
||||
align-items: center;
|
||||
& .checkbox {
|
||||
margin: auto
|
||||
}
|
||||
|
|
@ -285,12 +348,28 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
.form-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
& > div:first-of-type {
|
||||
flex:3;
|
||||
}
|
||||
& > div:nth-of-type(2) {
|
||||
flex: 9;
|
||||
}
|
||||
}
|
||||
|
||||
.setup-title {
|
||||
::v-deep code {
|
||||
font-size: 12px;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.setup-errors {
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { randomStr } from '@/utils/string';
|
||||
import { parse as parseUrl, removeParam, addParams } from '@/utils/url';
|
||||
import { findBy, addObjects } from '@/utils/array';
|
||||
import { GITHUB_NONCE, GITHUB_REDIRECT, GITHUB_SCOPE } from '@/config/query-params';
|
||||
import { NORMAN } from '@/config/types';
|
||||
import { addObjects, findBy } from '@/utils/array';
|
||||
import { openAuthPopup, returnTo } from '@/utils/auth';
|
||||
import { GITHUB_SCOPE, GITHUB_NONCE, GITHUB_REDIRECT } from '@/config/query-params';
|
||||
import { base64Encode } from '@/utils/crypto';
|
||||
import { randomStr } from '@/utils/string';
|
||||
import { addParams, parse as parseUrl, removeParam } from '@/utils/url';
|
||||
|
||||
export const BASE_SCOPES = {
|
||||
github: ['read:org'],
|
||||
|
|
@ -28,6 +29,8 @@ export const state = function() {
|
|||
hasAuth: null,
|
||||
loggedIn: false,
|
||||
principalId: null,
|
||||
v3User: null,
|
||||
initialPass: null,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -48,6 +51,14 @@ export const getters = {
|
|||
return state.principalId;
|
||||
},
|
||||
|
||||
v3User(state) {
|
||||
return state.v3User;
|
||||
},
|
||||
|
||||
initialPass(state) {
|
||||
return state.initialPass;
|
||||
},
|
||||
|
||||
isGithub(state) {
|
||||
return state.principalId && state.principalId.startsWith('github_user://');
|
||||
}
|
||||
|
|
@ -58,6 +69,11 @@ export const mutations = {
|
|||
state.fromHeader = fromHeader;
|
||||
},
|
||||
|
||||
gotUser(state, v3User) {
|
||||
// Always deference to avoid race condition when setting `mustChangePassword`
|
||||
state.v3User = { ...v3User };
|
||||
},
|
||||
|
||||
hasAuth(state, hasAuth) {
|
||||
state.hasAuth = !!hasAuth;
|
||||
},
|
||||
|
|
@ -75,7 +91,13 @@ export const mutations = {
|
|||
|
||||
state.loggedIn = false;
|
||||
state.principalId = null;
|
||||
state.v3User = null;
|
||||
state.initialPass = null;
|
||||
},
|
||||
|
||||
initialPass(state, pass) {
|
||||
state.initialPass = pass;
|
||||
}
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
|
|
@ -83,6 +105,27 @@ export const actions = {
|
|||
commit('gotHeader', fromHeader);
|
||||
},
|
||||
|
||||
async getUser({ dispatch, commit, getters }) {
|
||||
if (getters.v3User) {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await dispatch('rancher/findAll', {
|
||||
type: NORMAN.USER,
|
||||
opt: { url: '/v3/users', filter: { me: true } }
|
||||
}, { root: true });
|
||||
|
||||
commit('gotUser', user?.[0]);
|
||||
},
|
||||
|
||||
gotUser({ commit }, user) {
|
||||
commit('gotUser', user);
|
||||
},
|
||||
|
||||
setInitialPass({ commit }, pass) {
|
||||
commit('initialPass', pass);
|
||||
},
|
||||
|
||||
getAuthProviders({ dispatch }) {
|
||||
return dispatch('rancher/findAll', {
|
||||
type: 'authProvider',
|
||||
|
|
|
|||
Loading…
Reference in New Issue