import { Component } from '../../../lib/vues6/vues6.js' import { session } from '../../service/Session.service.js' import { password_service } from '../../service/Password.service.js' import { auth_api } from '../../service/AuthApi.service.js' import { location_service } from '../../service/Location.service.js' import { message_service } from '../../service/Message.service.js' import { utility } from '../../service/Utility.service.js' import { profile_service } from '../../service/Profile.service.js' const template = `
Profile Image

{{ profile_first }} {{ profile_last }}

{{ profile_tagline }}
` export default class EditProfileComponent extends Component { static get selector() { return 'coreid-profile-edit' } static get template() { return template } static get props() { return ['user_id'] } profile_first = '' profile_last = '' profile_email = '' profile_tagline = '' last_reset = '' mfa_enable_date = '' has_mfa_recovery = false mfa_recovery_date = '' mfa_recovery_codes = 0 form_message = 'No changes.' has_mfa = false ready = false app_passwords = [] on_key_up = ($event) => {} vue_on_create() { this.app_name = session.get('app.name') this.load().then(() => { this.ready = true }) const save = utility.debounce(this.save_form.bind(this)) this.on_key_up = () => { this.form_message = 'Saving...' save() } } get_submit_data() { return { first_name: this.profile_first, last_name: this.profile_last, email: this.profile_email, tagline: this.profile_tagline, user_id: this.user_id || 'me', } } on_profile_change_click() { this.$refs.profile_photo_uploader.show() } async on_profile_photo_upload() { this.$refs.profile_photo_uploader.close() let src = this.$refs.photo.src if ( src.indexOf('?') > 0 ) src = src.split('?')[0] this.$refs.photo.src = `${src}?i=${(new Date).getTime()}` } valid_email() { return this.$refs.email_input.validity.valid } async save_form($event) { const submit_data = this.get_submit_data() try { if ( !this.valid_email() ) { this.form_message = 'Invalid e-mail address.' } else { await profile_service.update_profile(submit_data) this.form_message = 'All changes saved.' } } catch(e) { this.form_message = 'Unknown error occurred while saving.' } } populate_from_session() { this.profile_first = session.get('user.first_name') this.profile_last = session.get('user.last_name') this.profile_email = session.get('user.email') this.profile_tagline = session.get('user.tagline') } async load() { const result = await profile_service.get_profile(this.user_id || 'me') if ( !result ) throw new Error('Unable to load profile!') this.profile_first = result.first_name this.profile_last = result.last_name this.profile_email = result.email this.profile_tagline = result.tagline if ( !this.user_id || this.user_id === 'me' ) { const reset = (await password_service.get_resets()).reverse()[0] if (reset && reset.reset_on) { this.last_reset = (new Date(reset.reset_on)).toLocaleDateString() } const mfa = await auth_api.has_mfa() this.has_mfa = mfa && mfa.mfa_enabled if (this.has_mfa) { this.mfa_enable_date = (new Date(mfa.mfa_enable_date)).toLocaleDateString() const result = await auth_api.has_mfa_recovery() if ( result && result.has_recovery ) { this.has_mfa_recovery = true this.mfa_recovery_date = (new Date(result.generated)).toLocaleDateString() this.mfa_recovery_codes = result.remaining_codes } } await this.load_app_passwords() } } async load_app_passwords() { let app_pws = await auth_api.app_passwords() if ( !Array.isArray(app_pws) ) app_pws = [] this.app_passwords = app_pws.map(x => { if ( x.expires ) x.expires = (new Date(x.expires)).toLocaleDateString() if ( x.created ) x.created = (new Date(x.created)).toLocaleDateString() return x }) } disable_mfa() { location_service.redirect('/auth/mfa/disable') } enable_mfa() { location_service.redirect('/auth/mfa/setup') } change_password() { location_service.redirect('/password/reset') } on_click_generate_app_password() { this.$refs.app_password_modal.trigger() } async deactivate_app_password($event, pw) { message_service.modal({ title: 'Deactivate app password?', message: `You are about to deactivate the app password for ${pw.name}. If you do this, ${pw.name} will no longer be able to sign-in on your behalf. Continue?`, buttons: [ { text: 'Cancel', type: 'close', }, { text: 'Deactivate', type: 'close', class: ['btn', 'btn-danger'], on_click: async () => { await auth_api.delete_app_password(pw.uuid) await this.load_app_passwords() }, }, ], }) } async on_mfa_recovery_generate($event) { if ( !this.has_mfa ) return if ( !this.has_mfa_recovery ) { await this.generate_mfa_recovery() } else { message_service.modal({ title: 'Are you sure?', message: 'There are already MFA recovery codes associated with your account. If you re-generate them, you will be unable to use the old ones. Continue?', buttons: [ { text: 'Cancel', type: 'close', }, { text: 'Re-generate', type: 'close', class: ['btn', 'btn-warning'], on_click: async () => { await this.generate_mfa_recovery() }, }, ], }) } } async generate_mfa_recovery() { const codes = await auth_api.generate_mfa_recovery() if ( codes ) { this.display_mfa_recovery_modal(codes) } else { message_service.alert({ type: 'error', message: 'An unknown error occurred while attempting to generate MFA recovery codes.' }) } await this.load() } display_mfa_recovery_modal(codes) { const code_display = codes.map(x => `
  • ${x}
  • `).join('\n') message_service.modal({ title: 'MFA Recovery Codes', message: `We've generated recovery codes for your account. You can use these to recover access to your account in the event that you lose your MFA device.

    Be sure to put these somewhere safe. After you close this modal, they will disappear:

    `, buttons: [ { text: 'Close', type: 'close', }, ], }) } }