mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
fix password input for backups and add adjective noun randomizer
This commit is contained in:
@@ -7,7 +7,13 @@ import {
|
|||||||
Validators,
|
Validators,
|
||||||
} from '@angular/forms'
|
} from '@angular/forms'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import { ErrorService, i18nPipe, normalizeHostname } from '@start9labs/shared'
|
import {
|
||||||
|
ErrorService,
|
||||||
|
i18nPipe,
|
||||||
|
normalizeHostname,
|
||||||
|
randomServerName,
|
||||||
|
serverNameValidator,
|
||||||
|
} from '@start9labs/shared'
|
||||||
import { TuiAutoFocus, TuiMapperPipe, TuiValidator } from '@taiga-ui/cdk'
|
import { TuiAutoFocus, TuiMapperPipe, TuiValidator } from '@taiga-ui/cdk'
|
||||||
import {
|
import {
|
||||||
TuiButton,
|
TuiButton,
|
||||||
@@ -42,10 +48,17 @@ import { StateService } from '../services/state.service'
|
|||||||
@if (isFresh) {
|
@if (isFresh) {
|
||||||
<tui-textfield>
|
<tui-textfield>
|
||||||
<label tuiLabel>{{ 'Server Name' | i18n }}</label>
|
<label tuiLabel>{{ 'Server Name' | i18n }}</label>
|
||||||
<input tuiInput tuiAutoFocus formControlName="name" />
|
<input tuiInput formControlName="name" />
|
||||||
|
<button
|
||||||
|
tuiIconButton
|
||||||
|
type="button"
|
||||||
|
appearance="icon"
|
||||||
|
iconStart="@tui.refresh-cw"
|
||||||
|
(click)="randomizeName()"
|
||||||
|
></button>
|
||||||
</tui-textfield>
|
</tui-textfield>
|
||||||
<tui-error formControlName="name" />
|
<tui-error formControlName="name" />
|
||||||
@if (form.controls.name.value?.trim()) {
|
@if (form.controls.name.value?.trim() && !form.controls.name.errors) {
|
||||||
<tui-error class="g-secondary" error="{{ derivedHostname }}.local" />
|
<tui-error class="g-secondary" error="{{ derivedHostname }}.local" />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,6 +140,8 @@ import { StateService } from '../services/state.service'
|
|||||||
minlength: 'Must be 12 characters or greater',
|
minlength: 'Must be 12 characters or greater',
|
||||||
maxlength: 'Must be 64 character or less',
|
maxlength: 'Must be 64 character or less',
|
||||||
match: 'Passwords do not match',
|
match: 'Passwords do not match',
|
||||||
|
hostnameMinLength: 'Hostname must be at least 4 characters',
|
||||||
|
hostnameMaxLength: 'Hostname must be 63 characters or less',
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -147,7 +162,10 @@ export default class PasswordPage {
|
|||||||
Validators.maxLength(64),
|
Validators.maxLength(64),
|
||||||
]),
|
]),
|
||||||
confirm: new FormControl(''),
|
confirm: new FormControl(''),
|
||||||
name: new FormControl('', this.isFresh ? [Validators.required] : []),
|
name: new FormControl(
|
||||||
|
this.isFresh ? randomServerName() : '',
|
||||||
|
this.isFresh ? [Validators.required, serverNameValidator] : [],
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
readonly validator = (value: string) => (control: AbstractControl) =>
|
readonly validator = (value: string) => (control: AbstractControl) =>
|
||||||
@@ -155,6 +173,10 @@ export default class PasswordPage {
|
|||||||
? null
|
? null
|
||||||
: { match: this.i18n.transform('Passwords do not match') }
|
: { match: this.i18n.transform('Passwords do not match') }
|
||||||
|
|
||||||
|
randomizeName() {
|
||||||
|
this.form.controls.name.setValue(randomServerName())
|
||||||
|
}
|
||||||
|
|
||||||
get derivedHostname(): string {
|
get derivedHostname(): string {
|
||||||
return normalizeHostname(this.form.controls.name.value || '')
|
return normalizeHostname(this.form.controls.name.value || '')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import {
|
|||||||
import { T } from '@start9labs/start-sdk'
|
import { T } from '@start9labs/start-sdk'
|
||||||
import * as jose from 'node-jose'
|
import * as jose from 'node-jose'
|
||||||
import { interval, map, Observable } from 'rxjs'
|
import { interval, map, Observable } from 'rxjs'
|
||||||
import { ApiService } from './api.service'
|
|
||||||
import { InstallOsParams, InstallOsRes } from '../types'
|
import { InstallOsParams, InstallOsRes } from '../types'
|
||||||
|
import { ApiService } from './api.service'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
@@ -127,7 +127,7 @@ export class MockApiService extends ApiService {
|
|||||||
return {
|
return {
|
||||||
'9876-5432-1234-5678': {
|
'9876-5432-1234-5678': {
|
||||||
hostname: 'adjective-noun',
|
hostname: 'adjective-noun',
|
||||||
version: '0.3.6',
|
version: '0.4.0',
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
passwordHash:
|
passwordHash:
|
||||||
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||||
@@ -135,7 +135,7 @@ export class MockApiService extends ApiService {
|
|||||||
},
|
},
|
||||||
'9876-5432-1234-5671': {
|
'9876-5432-1234-5671': {
|
||||||
hostname: 'adjective-noun',
|
hostname: 'adjective-noun',
|
||||||
version: '0.3.6',
|
version: '0.4.0',
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
passwordHash:
|
passwordHash:
|
||||||
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||||
@@ -299,7 +299,7 @@ const MOCK_DISKS: DiskInfo[] = [
|
|||||||
startOs: {
|
startOs: {
|
||||||
'small-server-id': {
|
'small-server-id': {
|
||||||
hostname: 'small-server',
|
hostname: 'small-server',
|
||||||
version: '0.3.6',
|
version: '0.4.0',
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
passwordHash:
|
passwordHash:
|
||||||
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||||
@@ -348,7 +348,7 @@ const MOCK_DISKS: DiskInfo[] = [
|
|||||||
startOs: {
|
startOs: {
|
||||||
'1234-5678-9876-5432': {
|
'1234-5678-9876-5432': {
|
||||||
hostname: 'existing-server',
|
hostname: 'existing-server',
|
||||||
version: '0.3.6',
|
version: '0.4.0',
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
passwordHash:
|
passwordHash:
|
||||||
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { ChangeDetectionStrategy, Component } from '@angular/core'
|
import { ChangeDetectionStrategy, Component } from '@angular/core'
|
||||||
import { FormsModule } from '@angular/forms'
|
import { FormsModule } from '@angular/forms'
|
||||||
import { TuiAutoFocus } from '@taiga-ui/cdk'
|
import { TuiAutoFocus } from '@taiga-ui/cdk'
|
||||||
import { TuiButton, TuiDialogContext, TuiInput } from '@taiga-ui/core'
|
import { TuiButton, TuiDialogContext, TuiIcon, TuiInput } from '@taiga-ui/core'
|
||||||
|
import { TuiPassword } from '@taiga-ui/kit'
|
||||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||||
import { i18nPipe } from '../i18n/i18n.pipe'
|
import { i18nPipe } from '../i18n/i18n.pipe'
|
||||||
import { i18nKey } from '../i18n/i18n.providers'
|
import { i18nKey } from '../i18n/i18n.providers'
|
||||||
@@ -27,22 +28,12 @@ import { i18nKey } from '../i18n/i18n.providers'
|
|||||||
tuiAutoFocus
|
tuiAutoFocus
|
||||||
[ngModelOptions]="{ standalone: true }"
|
[ngModelOptions]="{ standalone: true }"
|
||||||
[(ngModel)]="value"
|
[(ngModel)]="value"
|
||||||
[class.masked]="options.useMask && masked && value"
|
|
||||||
[placeholder]="options.placeholder || ''"
|
[placeholder]="options.placeholder || ''"
|
||||||
|
[type]="options.useMask ? 'password' : 'text'"
|
||||||
|
[autocomplete]="options.useMask ? 'off' : ''"
|
||||||
/>
|
/>
|
||||||
@if (options.useMask) {
|
@if (options.useMask) {
|
||||||
<button
|
<tui-icon tuiPassword />
|
||||||
tuiIconButton
|
|
||||||
type="button"
|
|
||||||
appearance="icon"
|
|
||||||
title="Toggle masking"
|
|
||||||
size="xs"
|
|
||||||
class="button"
|
|
||||||
[iconStart]="masked ? '@tui.eye' : '@tui.eye-off'"
|
|
||||||
(click)="masked = !masked"
|
|
||||||
>
|
|
||||||
{{ 'Reveal/Hide' | i18n }}
|
|
||||||
</button>
|
|
||||||
}
|
}
|
||||||
</tui-textfield>
|
</tui-textfield>
|
||||||
@if (error) {
|
@if (error) {
|
||||||
@@ -71,24 +62,22 @@ import { i18nKey } from '../i18n/i18n.providers'
|
|||||||
.error {
|
.error {
|
||||||
color: var(--tui-status-negative);
|
color: var(--tui-status-negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
|
||||||
pointer-events: auto;
|
|
||||||
margin-left: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.masked {
|
|
||||||
-webkit-text-security: disc;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
imports: [FormsModule, TuiButton, TuiInput, TuiAutoFocus, i18nPipe],
|
imports: [
|
||||||
|
FormsModule,
|
||||||
|
TuiButton,
|
||||||
|
TuiIcon,
|
||||||
|
TuiInput,
|
||||||
|
TuiPassword,
|
||||||
|
TuiAutoFocus,
|
||||||
|
i18nPipe,
|
||||||
|
],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class PromptModal {
|
export class PromptModal {
|
||||||
private readonly context =
|
private readonly context =
|
||||||
injectContext<TuiDialogContext<string, PromptOptions>>()
|
injectContext<TuiDialogContext<string, PromptOptions>>()
|
||||||
|
|
||||||
masked = this.options.useMask
|
|
||||||
value = this.options.initialValue || ''
|
value = this.options.initialValue || ''
|
||||||
error = ''
|
error = ''
|
||||||
|
|
||||||
|
|||||||
@@ -57,3 +57,5 @@ export * from './util/unused'
|
|||||||
export * from './util/keyboards'
|
export * from './util/keyboards'
|
||||||
export * from './util/languages'
|
export * from './util/languages'
|
||||||
export * from './util/hostname'
|
export * from './util/hostname'
|
||||||
|
export * from './util/random-server-name'
|
||||||
|
export * from './util/server-name-validator'
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* TS port of the Rust `normalize()` function from core/src/hostname.rs.
|
* TS port of the Rust `normalize()` function from core/src/hostname.rs.
|
||||||
* Converts a free-text name into a valid hostname.
|
* Strips non-alphanumeric characters and produces a raw hostname string.
|
||||||
*/
|
*/
|
||||||
export function normalizeHostname(name: string): string {
|
export function normalizeHostnameRaw(name: string): string {
|
||||||
let prevWasDash = true
|
let prevWasDash = true
|
||||||
let normalized = ''
|
let normalized = ''
|
||||||
|
|
||||||
@@ -20,5 +20,12 @@ export function normalizeHostname(name: string): string {
|
|||||||
normalized = normalized.slice(0, -1)
|
normalized = normalized.slice(0, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return normalized || 'start9'
|
return normalized
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a free-text name into a valid hostname, with 'start9' fallback.
|
||||||
|
*/
|
||||||
|
export function normalizeHostname(name: string): string {
|
||||||
|
return normalizeHostnameRaw(name) || 'start9'
|
||||||
}
|
}
|
||||||
|
|||||||
16
web/projects/shared/src/util/random-server-name.ts
Normal file
16
web/projects/shared/src/util/random-server-name.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { ADJECTIVES, NOUNS } from './server-name-words'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random server name in "Adjective Noun" format.
|
||||||
|
* Uses the same word lists as the Rust backend (core/src/assets/).
|
||||||
|
*/
|
||||||
|
export function randomServerName(): string {
|
||||||
|
const adj = ADJECTIVES[Math.floor(Math.random() * ADJECTIVES.length)]!
|
||||||
|
const noun = NOUNS[Math.floor(Math.random() * NOUNS.length)]!
|
||||||
|
|
||||||
|
return `${capitalize(adj)} ${capitalize(noun)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function capitalize(word: string): string {
|
||||||
|
return word.charAt(0).toUpperCase() + word.slice(1)
|
||||||
|
}
|
||||||
26
web/projects/shared/src/util/server-name-validator.ts
Normal file
26
web/projects/shared/src/util/server-name-validator.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { AbstractControl, ValidationErrors } from '@angular/forms'
|
||||||
|
import { normalizeHostnameRaw } from './hostname'
|
||||||
|
|
||||||
|
// Matches backend normalize() threshold (core/src/hostname.rs:109)
|
||||||
|
const HOSTNAME_MIN_LENGTH = 4
|
||||||
|
// DNS label limit
|
||||||
|
const HOSTNAME_MAX_LENGTH = 63
|
||||||
|
|
||||||
|
export function serverNameValidator(
|
||||||
|
control: AbstractControl,
|
||||||
|
): ValidationErrors | null {
|
||||||
|
const name = (control.value || '').trim()
|
||||||
|
if (!name) return null
|
||||||
|
|
||||||
|
const hostname = normalizeHostnameRaw(name)
|
||||||
|
|
||||||
|
if (hostname.length < HOSTNAME_MIN_LENGTH) {
|
||||||
|
return { hostnameMinLength: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostname.length > HOSTNAME_MAX_LENGTH) {
|
||||||
|
return { hostnameMaxLength: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
8948
web/projects/shared/src/util/server-name-words.ts
Normal file
8948
web/projects/shared/src/util/server-name-words.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,12 @@
|
|||||||
import { Component } from '@angular/core'
|
import { Component } from '@angular/core'
|
||||||
import { FormsModule } from '@angular/forms'
|
import { FormsModule } from '@angular/forms'
|
||||||
import { i18nPipe, normalizeHostname } from '@start9labs/shared'
|
import {
|
||||||
import { TuiButton, TuiDialogContext, TuiInput } from '@taiga-ui/core'
|
i18nPipe,
|
||||||
|
normalizeHostname,
|
||||||
|
normalizeHostnameRaw,
|
||||||
|
randomServerName,
|
||||||
|
} from '@start9labs/shared'
|
||||||
|
import { TuiButton, TuiDialogContext, TuiError, TuiInput } from '@taiga-ui/core'
|
||||||
import { injectContext } from '@taiga-ui/polymorpheus'
|
import { injectContext } from '@taiga-ui/polymorpheus'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -9,15 +14,28 @@ import { injectContext } from '@taiga-ui/polymorpheus'
|
|||||||
<tui-textfield>
|
<tui-textfield>
|
||||||
<label tuiLabel>{{ 'Server Name' | i18n }}</label>
|
<label tuiLabel>{{ 'Server Name' | i18n }}</label>
|
||||||
<input tuiInput [(ngModel)]="name" />
|
<input tuiInput [(ngModel)]="name" />
|
||||||
|
<button
|
||||||
|
tuiIconButton
|
||||||
|
type="button"
|
||||||
|
appearance="icon"
|
||||||
|
iconStart="@tui.refresh-cw"
|
||||||
|
(click)="randomizeName()"
|
||||||
|
></button>
|
||||||
</tui-textfield>
|
</tui-textfield>
|
||||||
@if (name.trim()) {
|
@if (hostnameError) {
|
||||||
|
<tui-error [error]="hostnameError" />
|
||||||
|
} @else if (name.trim()) {
|
||||||
<p class="hostname-preview">{{ normalizeHostname(name) }}.local</p>
|
<p class="hostname-preview">{{ normalizeHostname(name) }}.local</p>
|
||||||
}
|
}
|
||||||
<footer>
|
<footer>
|
||||||
<button tuiButton appearance="secondary" (click)="cancel()">
|
<button tuiButton appearance="secondary" (click)="cancel()">
|
||||||
{{ 'Cancel' | i18n }}
|
{{ 'Cancel' | i18n }}
|
||||||
</button>
|
</button>
|
||||||
<button tuiButton [disabled]="!name.trim()" (click)="confirm()">
|
<button
|
||||||
|
tuiButton
|
||||||
|
[disabled]="!name.trim() || hostnameError"
|
||||||
|
(click)="confirm()"
|
||||||
|
>
|
||||||
{{ 'Save' | i18n }}
|
{{ 'Save' | i18n }}
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
@@ -35,7 +53,7 @@ import { injectContext } from '@taiga-ui/polymorpheus'
|
|||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
imports: [FormsModule, TuiButton, TuiInput, i18nPipe],
|
imports: [FormsModule, TuiButton, TuiError, TuiInput, i18nPipe],
|
||||||
})
|
})
|
||||||
export class ServerNameDialog {
|
export class ServerNameDialog {
|
||||||
private readonly context =
|
private readonly context =
|
||||||
@@ -49,6 +67,22 @@ export class ServerNameDialog {
|
|||||||
name = this.context.data.initialName
|
name = this.context.data.initialName
|
||||||
readonly normalizeHostname = normalizeHostname
|
readonly normalizeHostname = normalizeHostname
|
||||||
|
|
||||||
|
get hostnameError(): string | null {
|
||||||
|
const name = this.name.trim()
|
||||||
|
if (!name) return null
|
||||||
|
|
||||||
|
const hostname = normalizeHostnameRaw(name)
|
||||||
|
|
||||||
|
if (hostname.length < 4) return 'Hostname must be at least 4 characters'
|
||||||
|
if (hostname.length > 63) return 'Hostname must be 63 characters or less'
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
randomizeName() {
|
||||||
|
this.name = randomServerName()
|
||||||
|
}
|
||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
this.context.completeWith(null)
|
this.context.completeWith(null)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
|
import { GetPackagesRes } from '@start9labs/marketplace'
|
||||||
|
import { ISB, IST, T } from '@start9labs/start-sdk'
|
||||||
import {
|
import {
|
||||||
InstalledState,
|
InstalledState,
|
||||||
PackageDataEntry,
|
PackageDataEntry,
|
||||||
} from 'src/app/services/patch-db/data-model'
|
} from 'src/app/services/patch-db/data-model'
|
||||||
import { ActionRes } from './api.types'
|
|
||||||
import { BTC_ICON, LND_ICON, PROXY_ICON, REGISTRY_ICON } from './api-icons'
|
|
||||||
import { configBuilderToSpec } from 'src/app/utils/configBuilderToSpec'
|
import { configBuilderToSpec } from 'src/app/utils/configBuilderToSpec'
|
||||||
import { T, ISB, IST } from '@start9labs/start-sdk'
|
import { BTC_ICON, LND_ICON, PROXY_ICON, REGISTRY_ICON } from './api-icons'
|
||||||
import { GetPackagesRes } from '@start9labs/marketplace'
|
import { ActionRes } from './api.types'
|
||||||
|
|
||||||
import markdown from './md-sample.md'
|
import markdown from './md-sample.md'
|
||||||
|
|
||||||
@@ -33,14 +33,14 @@ export namespace Mock {
|
|||||||
'0.4.1': {
|
'0.4.1': {
|
||||||
headline: 'v0.4.1',
|
headline: 'v0.4.1',
|
||||||
releaseNotes: 'Testing some release notes',
|
releaseNotes: 'Testing some release notes',
|
||||||
sourceVersion: '>=0.3.5:0 <=0.3.6-alpha.17:0',
|
sourceVersion: '>=0.3.5:0 <=0.4.0-alpha.17:0',
|
||||||
authorized: ['G24CSA5HNYEPIXJNMK7ZM4KD5SX5N6X4'],
|
authorized: ['G24CSA5HNYEPIXJNMK7ZM4KD5SX5N6X4'],
|
||||||
iso: {},
|
iso: {},
|
||||||
squashfs: {
|
squashfs: {
|
||||||
aarch64: {
|
aarch64: {
|
||||||
publishedAt: '2025-03-21T23:55:29.583006392Z',
|
publishedAt: '2025-03-21T23:55:29.583006392Z',
|
||||||
urls: [
|
urls: [
|
||||||
'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_aarch64.squashfs',
|
'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_aarch64.squashfs',
|
||||||
],
|
],
|
||||||
commitment: {
|
commitment: {
|
||||||
hash: 'OUnANnZePtf7rSbj38JESl+iJAV0z0aiZ4opCiwpGbo=',
|
hash: 'OUnANnZePtf7rSbj38JESl+iJAV0z0aiZ4opCiwpGbo=',
|
||||||
@@ -54,7 +54,7 @@ export namespace Mock {
|
|||||||
'aarch64-nonfree': {
|
'aarch64-nonfree': {
|
||||||
publishedAt: '2025-03-21T23:56:38.299572946Z',
|
publishedAt: '2025-03-21T23:56:38.299572946Z',
|
||||||
urls: [
|
urls: [
|
||||||
'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_aarch64-nonfree.squashfs',
|
'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_aarch64-nonfree.squashfs',
|
||||||
],
|
],
|
||||||
commitment: {
|
commitment: {
|
||||||
hash: '6k+0RcyRQV+5A+h06OqpHxd4IT6IlFkfdy9dfHIP90c=',
|
hash: '6k+0RcyRQV+5A+h06OqpHxd4IT6IlFkfdy9dfHIP90c=',
|
||||||
@@ -68,7 +68,7 @@ export namespace Mock {
|
|||||||
raspberrypi: {
|
raspberrypi: {
|
||||||
publishedAt: '2025-03-22T00:08:17.083064390Z',
|
publishedAt: '2025-03-22T00:08:17.083064390Z',
|
||||||
urls: [
|
urls: [
|
||||||
'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_raspberrypi.squashfs',
|
'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_raspberrypi.squashfs',
|
||||||
],
|
],
|
||||||
commitment: {
|
commitment: {
|
||||||
hash: 'K+XuTZxo1KVsKjNSV8PPOMruCvAEZwerF9mbpFl53Gk=',
|
hash: 'K+XuTZxo1KVsKjNSV8PPOMruCvAEZwerF9mbpFl53Gk=',
|
||||||
@@ -82,7 +82,7 @@ export namespace Mock {
|
|||||||
x86_64: {
|
x86_64: {
|
||||||
publishedAt: '2025-03-22T00:05:57.684319247Z',
|
publishedAt: '2025-03-22T00:05:57.684319247Z',
|
||||||
urls: [
|
urls: [
|
||||||
'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_x86_64.squashfs',
|
'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_x86_64.squashfs',
|
||||||
],
|
],
|
||||||
commitment: {
|
commitment: {
|
||||||
hash: '3UVkx3TQMBPlSU1OnV48Om9vjjA3s+Nk6dX3auYGpBo=',
|
hash: '3UVkx3TQMBPlSU1OnV48Om9vjjA3s+Nk6dX3auYGpBo=',
|
||||||
@@ -96,7 +96,7 @@ export namespace Mock {
|
|||||||
'x86_64-nonfree': {
|
'x86_64-nonfree': {
|
||||||
publishedAt: '2025-03-22T00:07:11.893777122Z',
|
publishedAt: '2025-03-22T00:07:11.893777122Z',
|
||||||
urls: [
|
urls: [
|
||||||
'https://alpha-registry-x.start9.com/startos/v0.3.6-alpha.17/startos-0.3.6-alpha.17-b8ff331~dev_x86_64-nonfree.squashfs',
|
'https://alpha-registry-x.start9.com/startos/v0.4.0-alpha.17/startos-0.4.0-alpha.17-b8ff331~dev_x86_64-nonfree.squashfs',
|
||||||
],
|
],
|
||||||
commitment: {
|
commitment: {
|
||||||
hash: 'IS1gJ56n/HlQqFbl1upMOAtLxyxB0cY0H89Ha+9h1lE=',
|
hash: 'IS1gJ56n/HlQqFbl1upMOAtLxyxB0cY0H89Ha+9h1lE=',
|
||||||
@@ -454,7 +454,7 @@ export namespace Mock {
|
|||||||
marketingUrl: 'https://bitcoin.org',
|
marketingUrl: 'https://bitcoin.org',
|
||||||
docsUrls: ['https://bitcoin.org'],
|
docsUrls: ['https://bitcoin.org'],
|
||||||
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: BTC_ICON,
|
icon: BTC_ICON,
|
||||||
@@ -496,7 +496,7 @@ export namespace Mock {
|
|||||||
marketingUrl: 'https://bitcoinknots.org',
|
marketingUrl: 'https://bitcoinknots.org',
|
||||||
docsUrls: ['https://bitcoinknots.org'],
|
docsUrls: ['https://bitcoinknots.org'],
|
||||||
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: BTC_ICON,
|
icon: BTC_ICON,
|
||||||
@@ -548,7 +548,7 @@ export namespace Mock {
|
|||||||
marketingUrl: 'https://bitcoin.org',
|
marketingUrl: 'https://bitcoin.org',
|
||||||
docsUrls: ['https://bitcoin.org'],
|
docsUrls: ['https://bitcoin.org'],
|
||||||
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: BTC_ICON,
|
icon: BTC_ICON,
|
||||||
@@ -590,7 +590,7 @@ export namespace Mock {
|
|||||||
marketingUrl: 'https://bitcoinknots.org',
|
marketingUrl: 'https://bitcoinknots.org',
|
||||||
docsUrls: ['https://bitcoinknots.org'],
|
docsUrls: ['https://bitcoinknots.org'],
|
||||||
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: BTC_ICON,
|
icon: BTC_ICON,
|
||||||
@@ -644,7 +644,7 @@ export namespace Mock {
|
|||||||
marketingUrl: 'https://lightning.engineering/',
|
marketingUrl: 'https://lightning.engineering/',
|
||||||
docsUrls: ['https://lightning.engineering/'],
|
docsUrls: ['https://lightning.engineering/'],
|
||||||
releaseNotes: 'Upstream release to 0.17.5',
|
releaseNotes: 'Upstream release to 0.17.5',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: LND_ICON,
|
icon: LND_ICON,
|
||||||
@@ -699,7 +699,7 @@ export namespace Mock {
|
|||||||
marketingUrl: 'https://lightning.engineering/',
|
marketingUrl: 'https://lightning.engineering/',
|
||||||
docsUrls: ['https://lightning.engineering/'],
|
docsUrls: ['https://lightning.engineering/'],
|
||||||
releaseNotes: 'Upstream release to 0.17.4',
|
releaseNotes: 'Upstream release to 0.17.4',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: LND_ICON,
|
icon: LND_ICON,
|
||||||
@@ -758,7 +758,7 @@ export namespace Mock {
|
|||||||
marketingUrl: 'https://bitcoin.org',
|
marketingUrl: 'https://bitcoin.org',
|
||||||
docsUrls: ['https://bitcoin.org'],
|
docsUrls: ['https://bitcoin.org'],
|
||||||
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: BTC_ICON,
|
icon: BTC_ICON,
|
||||||
@@ -800,7 +800,7 @@ export namespace Mock {
|
|||||||
marketingUrl: 'https://bitcoinknots.org',
|
marketingUrl: 'https://bitcoinknots.org',
|
||||||
docsUrls: [],
|
docsUrls: [],
|
||||||
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
releaseNotes: 'Even better support for Bitcoin and wallets!',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: BTC_ICON,
|
icon: BTC_ICON,
|
||||||
@@ -852,7 +852,7 @@ export namespace Mock {
|
|||||||
marketingUrl: 'https://lightning.engineering/',
|
marketingUrl: 'https://lightning.engineering/',
|
||||||
docsUrls: [],
|
docsUrls: [],
|
||||||
releaseNotes: 'Upstream release and minor fixes.',
|
releaseNotes: 'Upstream release and minor fixes.',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: LND_ICON,
|
icon: LND_ICON,
|
||||||
@@ -907,7 +907,7 @@ export namespace Mock {
|
|||||||
docsUrls: [],
|
docsUrls: [],
|
||||||
marketingUrl: '',
|
marketingUrl: '',
|
||||||
releaseNotes: 'Upstream release and minor fixes.',
|
releaseNotes: 'Upstream release and minor fixes.',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
sdkVersion: '0.4.0-beta.49',
|
sdkVersion: '0.4.0-beta.49',
|
||||||
gitHash: 'fakehash',
|
gitHash: 'fakehash',
|
||||||
icon: PROXY_ICON,
|
icon: PROXY_ICON,
|
||||||
@@ -1013,7 +1013,7 @@ export namespace Mock {
|
|||||||
createdAt: '2019-12-26T14:20:30.872Z',
|
createdAt: '2019-12-26T14:20:30.872Z',
|
||||||
code: 2,
|
code: 2,
|
||||||
level: 'success',
|
level: 'success',
|
||||||
title: 'Welcome to StartOS 0.3.6!',
|
title: 'Welcome to StartOS 0.4.0!',
|
||||||
message: 'Click "View Details" to learn all about the new version',
|
message: 'Click "View Details" to learn all about the new version',
|
||||||
data: markdown,
|
data: markdown,
|
||||||
seen: false,
|
seen: false,
|
||||||
@@ -1207,7 +1207,7 @@ export namespace Mock {
|
|||||||
'1234-5678-9876-5432': {
|
'1234-5678-9876-5432': {
|
||||||
hostname: 'adjective-noun',
|
hostname: 'adjective-noun',
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
version: '0.3.6',
|
version: '0.4.0',
|
||||||
passwordHash:
|
passwordHash:
|
||||||
// password is asdfasdf
|
// password is asdfasdf
|
||||||
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||||
@@ -1247,7 +1247,7 @@ export namespace Mock {
|
|||||||
'1234-5678-9876-5432': {
|
'1234-5678-9876-5432': {
|
||||||
hostname: 'adjective-noun',
|
hostname: 'adjective-noun',
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
version: '0.3.6',
|
version: '0.4.0',
|
||||||
passwordHash:
|
passwordHash:
|
||||||
// password is asdfasdf
|
// password is asdfasdf
|
||||||
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
'$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||||
@@ -1282,7 +1282,7 @@ export namespace Mock {
|
|||||||
// startOs: {
|
// startOs: {
|
||||||
// abcdefgh: {
|
// abcdefgh: {
|
||||||
// hostname: 'adjective-noun.local',
|
// hostname: 'adjective-noun.local',
|
||||||
// version: '0.3.6',
|
// version: '0.4.0',
|
||||||
// timestamp: new Date().toISOString(),
|
// timestamp: new Date().toISOString(),
|
||||||
// passwordHash:
|
// passwordHash:
|
||||||
// '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
// '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||||
@@ -1321,7 +1321,7 @@ export namespace Mock {
|
|||||||
// startOs: {
|
// startOs: {
|
||||||
// 'different-server': {
|
// 'different-server': {
|
||||||
// hostname: 'different-server.local',
|
// hostname: 'different-server.local',
|
||||||
// version: '0.3.6',
|
// version: '0.4.0',
|
||||||
// timestamp: new Date().toISOString(),
|
// timestamp: new Date().toISOString(),
|
||||||
// passwordHash:
|
// passwordHash:
|
||||||
// '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
// '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ',
|
||||||
@@ -1387,19 +1387,19 @@ export namespace Mock {
|
|||||||
// ]
|
// ]
|
||||||
|
|
||||||
export const BackupInfo: T.BackupInfo = {
|
export const BackupInfo: T.BackupInfo = {
|
||||||
version: '0.3.6',
|
version: '0.4.0',
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
packageBackups: {
|
packageBackups: {
|
||||||
bitcoind: {
|
bitcoind: {
|
||||||
title: 'Bitcoin Core',
|
title: 'Bitcoin Core',
|
||||||
version: '0.21.0:0',
|
version: '0.21.0:0',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
'btc-rpc-proxy': {
|
'btc-rpc-proxy': {
|
||||||
title: 'Bitcoin Proxy',
|
title: 'Bitcoin Proxy',
|
||||||
version: '0.2.2:0',
|
version: '0.2.2:0',
|
||||||
osVersion: '0.3.6',
|
osVersion: '0.4.0',
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||||
import { Mock } from './api.fixures'
|
|
||||||
import { knownAuthorities } from 'src/app/utils/acme'
|
import { knownAuthorities } from 'src/app/utils/acme'
|
||||||
|
import { Mock } from './api.fixures'
|
||||||
const version = require('../../../../../../package.json').version
|
const version = require('../../../../../../package.json').version
|
||||||
|
|
||||||
export const mockPatchData: DataModel = {
|
export const mockPatchData: DataModel = {
|
||||||
|
|||||||
Reference in New Issue
Block a user