mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
add reset password to UI (#2341)
This commit is contained in:
@@ -24,6 +24,9 @@ import {
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
import { DOCUMENT } from '@angular/common'
|
||||
import { getServerInfo } from 'src/app/util/get-server-info'
|
||||
import { GenericFormPage } from 'src/app/modals/generic-form/generic-form.page'
|
||||
import { ConfigSpec } from 'src/app/pkg-config/config-types'
|
||||
import * as argon2 from '@start9labs/argon2'
|
||||
|
||||
@Component({
|
||||
selector: 'server-show',
|
||||
@@ -82,6 +85,102 @@ export class ServerShowPage {
|
||||
await modal.present()
|
||||
}
|
||||
|
||||
async presentAlertResetPassword() {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Warning',
|
||||
message:
|
||||
'You will still need your current password to decrypt existing backups!',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
},
|
||||
{
|
||||
text: 'Continue',
|
||||
handler: () => this.presentModalResetPassword(),
|
||||
cssClass: 'enter-click',
|
||||
},
|
||||
],
|
||||
cssClass: 'alert-warning-message',
|
||||
})
|
||||
|
||||
await alert.present()
|
||||
}
|
||||
|
||||
async presentModalResetPassword(): Promise<void> {
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: GenericFormPage,
|
||||
componentProps: {
|
||||
title: 'Change Master Password',
|
||||
spec: PasswordSpec,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Save',
|
||||
handler: (value: any) => {
|
||||
return this.resetPassword(value)
|
||||
},
|
||||
isSubmit: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
await modal.present()
|
||||
}
|
||||
|
||||
private async resetPassword(value: {
|
||||
currPass: string
|
||||
newPass: string
|
||||
newPass2: string
|
||||
}): Promise<boolean> {
|
||||
let err = ''
|
||||
|
||||
if (value.newPass !== value.newPass2) {
|
||||
err = 'New passwords do not match'
|
||||
} else if (value.newPass.length < 12) {
|
||||
err = 'New password must be 12 characters or greater'
|
||||
} else if (value.newPass.length > 64) {
|
||||
err = 'New password must be less than 65 characters'
|
||||
}
|
||||
|
||||
// confirm current password is correct
|
||||
const { 'password-hash': passwordHash } = await getServerInfo(this.patch)
|
||||
try {
|
||||
argon2.verify(passwordHash, value.currPass)
|
||||
} catch (e) {
|
||||
err = 'Current password is invalid'
|
||||
}
|
||||
|
||||
if (err) {
|
||||
this.errToast.present(err)
|
||||
return false
|
||||
}
|
||||
|
||||
const loader = await this.loadingCtrl.create({
|
||||
message: 'Changing master password...',
|
||||
})
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.embassyApi.resetPassword({
|
||||
'old-password': value.currPass,
|
||||
'new-password': value.newPass,
|
||||
})
|
||||
const toast = await this.toastCtrl.create({
|
||||
header: 'Password changed!',
|
||||
position: 'bottom',
|
||||
duration: 2000,
|
||||
})
|
||||
|
||||
toast.present()
|
||||
return true
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
return false
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
async updateEos(): Promise<void> {
|
||||
const modal = await this.modalCtrl.create({
|
||||
component: OSUpdatePage,
|
||||
@@ -436,6 +535,14 @@ export class ServerShowPage {
|
||||
detail: true,
|
||||
disabled$: of(false),
|
||||
},
|
||||
{
|
||||
title: 'Change Master Password',
|
||||
description: `Change your StartOS master password`,
|
||||
icon: 'key-outline',
|
||||
action: () => this.presentAlertResetPassword(),
|
||||
detail: false,
|
||||
disabled$: of(!this.secure),
|
||||
},
|
||||
{
|
||||
title: 'Experimental Features',
|
||||
description: 'Try out new and potentially unstable new features',
|
||||
@@ -530,11 +637,7 @@ export class ServerShowPage {
|
||||
description: 'Get help from the Start9 team and community',
|
||||
icon: 'chatbubbles-outline',
|
||||
action: () =>
|
||||
window.open(
|
||||
'https://start9.com/contact',
|
||||
'_blank',
|
||||
'noreferrer',
|
||||
),
|
||||
window.open('https://start9.com/contact', '_blank', 'noreferrer'),
|
||||
detail: true,
|
||||
disabled$: of(false),
|
||||
},
|
||||
@@ -636,3 +739,30 @@ interface SettingBtn {
|
||||
detail: boolean
|
||||
disabled$: Observable<boolean>
|
||||
}
|
||||
|
||||
const PasswordSpec: ConfigSpec = {
|
||||
currPass: {
|
||||
type: 'string',
|
||||
name: 'Current Password',
|
||||
placeholder: 'CurrentPass',
|
||||
nullable: false,
|
||||
masked: true,
|
||||
copyable: false,
|
||||
},
|
||||
newPass: {
|
||||
type: 'string',
|
||||
name: 'New Password',
|
||||
placeholder: 'NewPass',
|
||||
nullable: false,
|
||||
masked: true,
|
||||
copyable: false,
|
||||
},
|
||||
newPass2: {
|
||||
type: 'string',
|
||||
name: 'Retype New Password',
|
||||
placeholder: 'NewPass',
|
||||
nullable: false,
|
||||
masked: true,
|
||||
copyable: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -30,6 +30,12 @@ export module RR {
|
||||
export type LogoutReq = {} // auth.logout
|
||||
export type LogoutRes = null
|
||||
|
||||
export type ResetPasswordReq = {
|
||||
'old-password': string
|
||||
'new-password': string
|
||||
} // auth.reset-password
|
||||
export type ResetPasswordRes = null
|
||||
|
||||
// server
|
||||
|
||||
export type EchoReq = { message: string } // server.echo
|
||||
@@ -84,11 +90,6 @@ export module RR {
|
||||
export type KillSessionsReq = { ids: string[] } // sessions.kill
|
||||
export type KillSessionsRes = null
|
||||
|
||||
// password
|
||||
|
||||
export type UpdatePasswordReq = { password: string } // password.set
|
||||
export type UpdatePasswordRes = null
|
||||
|
||||
// notification
|
||||
|
||||
export type GetNotificationsReq = {
|
||||
|
||||
@@ -51,6 +51,10 @@ export abstract class ApiService {
|
||||
|
||||
abstract killSessions(params: RR.KillSessionsReq): Promise<RR.KillSessionsRes>
|
||||
|
||||
abstract resetPassword(
|
||||
params: RR.ResetPasswordReq,
|
||||
): Promise<RR.ResetPasswordRes>
|
||||
|
||||
// server
|
||||
|
||||
abstract echo(params: RR.EchoReq): Promise<RR.EchoRes>
|
||||
@@ -126,9 +130,6 @@ export abstract class ApiService {
|
||||
|
||||
abstract getEos(): Promise<RR.GetMarketplaceEosRes>
|
||||
|
||||
// password
|
||||
// abstract updatePassword (params: RR.UpdatePasswordReq): Promise<RR.UpdatePasswordRes>
|
||||
|
||||
// notification
|
||||
|
||||
abstract getNotifications(
|
||||
|
||||
@@ -94,6 +94,12 @@ export class LiveApiService extends ApiService {
|
||||
return this.rpcRequest({ method: 'auth.session.kill', params })
|
||||
}
|
||||
|
||||
async resetPassword(
|
||||
params: RR.ResetPasswordReq,
|
||||
): Promise<RR.ResetPasswordRes> {
|
||||
return this.rpcRequest({ method: 'auth.reset-password', params })
|
||||
}
|
||||
|
||||
// server
|
||||
|
||||
async echo(params: RR.EchoReq): Promise<RR.EchoRes> {
|
||||
|
||||
@@ -156,6 +156,13 @@ export class MockApiService extends ApiService {
|
||||
return null
|
||||
}
|
||||
|
||||
async resetPassword(
|
||||
params: RR.ResetPasswordReq,
|
||||
): Promise<RR.ResetPasswordRes> {
|
||||
await pauseFor(2000)
|
||||
return null
|
||||
}
|
||||
|
||||
// server
|
||||
|
||||
async echo(params: RR.EchoReq): Promise<RR.EchoRes> {
|
||||
@@ -377,12 +384,6 @@ export class MockApiService extends ApiService {
|
||||
return Mock.MarketplaceEos
|
||||
}
|
||||
|
||||
// password
|
||||
// async updatePassword (params: RR.UpdatePasswordReq): Promise<RR.UpdatePasswordRes> {
|
||||
// await pauseFor(2000)
|
||||
// return null
|
||||
// }
|
||||
|
||||
// notification
|
||||
|
||||
async getNotifications(
|
||||
|
||||
Reference in New Issue
Block a user