juice-shop
91 строка · 4.7 Кб
1/*
2* Copyright (c) 2014-2024 Bjoern Kimminich & the OWASP Juice Shop contributors.
3* SPDX-License-Identifier: MIT
4*/
5
6import { Injectable } from '@angular/core'
7import { type Backup } from '../Models/backup.model'
8import { CookieService } from 'ngx-cookie'
9import { saveAs } from 'file-saver'
10import { SnackBarHelperService } from './snack-bar-helper.service'
11import { MatSnackBar } from '@angular/material/snack-bar'
12import { forkJoin, from, of } from 'rxjs'
13import { ChallengeService } from './challenge.service'
14
15@Injectable({
16providedIn: 'root'
17})
18export class LocalBackupService {
19private readonly VERSION = 1
20
21constructor (private readonly cookieService: CookieService, private readonly challengeService: ChallengeService, private readonly snackBarHelperService: SnackBarHelperService, private readonly snackBar: MatSnackBar) { }
22
23save (fileName: string = 'owasp_juice_shop') {
24const backup: Backup = { version: this.VERSION }
25
26backup.banners = {
27welcomeBannerStatus: this.cookieService.get('welcomebanner_status') ? this.cookieService.get('welcomebanner_status') : undefined,
28cookieConsentStatus: this.cookieService.get('cookieconsent_status') ? this.cookieService.get('cookieconsent_status') : undefined
29}
30backup.language = this.cookieService.get('language') ? this.cookieService.get('language') : undefined
31
32const continueCode = this.challengeService.continueCode()
33const continueCodeFindIt = this.challengeService.continueCodeFindIt()
34const continueCodeFixIt = this.challengeService.continueCodeFixIt()
35forkJoin([continueCode, continueCodeFindIt, continueCodeFixIt]).subscribe(([continueCode, continueCodeFindIt, continueCodeFixIt]) => {
36backup.continueCode = continueCode
37backup.continueCodeFindIt = continueCodeFindIt
38backup.continueCodeFixIt = continueCodeFixIt
39const blob = new Blob([JSON.stringify(backup)], { type: 'text/plain;charset=utf-8' })
40saveAs(blob, `${fileName}-${new Date().toISOString().split('T')[0]}.json`)
41}, () => {
42console.log('Failed to retrieve continue code(s) for backup from server. Using cookie values as fallback.')
43backup.continueCode = this.cookieService.get('continueCode') ? this.cookieService.get('continueCode') : undefined
44backup.continueCodeFindIt = this.cookieService.get('continueCodeFindIt') ? this.cookieService.get('continueCodeFindIt') : undefined
45backup.continueCodeFixIt = this.cookieService.get('continueCodeFixIt') ? this.cookieService.get('continueCodeFixIt') : undefined
46const blob = new Blob([JSON.stringify(backup)], { type: 'text/plain;charset=utf-8' })
47saveAs(blob, `${fileName}-${new Date().toISOString().split('T')[0]}.json`)
48})
49}
50
51restore (backupFile: File) {
52return from(backupFile.text().then((backupData) => {
53const backup: Backup = JSON.parse(backupData)
54
55if (backup.version === this.VERSION) {
56this.restoreCookie('welcomebanner_status', backup.banners?.welcomeBannerStatus)
57this.restoreCookie('cookieconsent_status', backup.banners?.cookieConsentStatus)
58this.restoreCookie('language', backup.language)
59this.restoreCookie('continueCodeFindIt', backup.continueCodeFindIt)
60this.restoreCookie('continueCodeFixIt', backup.continueCodeFixIt)
61this.restoreCookie('continueCode', backup.continueCode)
62
63const snackBarRef = this.snackBar.open('Backup has been restored from ' + backupFile.name, 'Apply changes now', {
64duration: 10000
65})
66snackBarRef.onAction().subscribe(() => {
67const hackingProgress = backup.continueCode ? this.challengeService.restoreProgress(encodeURIComponent(backup.continueCode)) : of(true)
68const findItProgress = backup.continueCodeFindIt ? this.challengeService.restoreProgressFindIt(encodeURIComponent(backup.continueCodeFindIt)) : of(true)
69const fixItProgress = backup.continueCodeFixIt ? this.challengeService.restoreProgressFixIt(encodeURIComponent(backup.continueCodeFixIt)) : of(true)
70forkJoin([hackingProgress, findItProgress, fixItProgress]).subscribe(() => {
71location.reload()
72}, (err) => { console.log(err) })
73})
74} else {
75this.snackBarHelperService.open(`Version ${backup.version} is incompatible with expected version ${this.VERSION}`, 'errorBar')
76}
77}).catch((err: Error) => {
78this.snackBarHelperService.open(`Backup restore operation failed: ${err.message}`, 'errorBar')
79}))
80}
81
82private restoreCookie (cookieName: string, cookieValue: string) {
83if (cookieValue) {
84const expires = new Date()
85expires.setFullYear(expires.getFullYear() + 1)
86this.cookieService.put(cookieName, cookieValue, { expires })
87} else {
88this.cookieService.remove(cookieName)
89}
90}
91}
92