juice-shop

Форк
0
/
code-snippet.component.ts 
207 строк · 6.2 Кб
1
/*
2
 * Copyright (c) 2014-2024 Bjoern Kimminich & the OWASP Juice Shop contributors.
3
 * SPDX-License-Identifier: MIT
4
 */
5

6
import { CodeSnippetService, type CodeSnippet } from '../Services/code-snippet.service'
7
import { CodeFixesService } from '../Services/code-fixes.service'
8
import { CookieService } from 'ngx-cookie'
9
import { ChallengeService } from '../Services/challenge.service'
10
import { VulnLinesService, type result } from '../Services/vuln-lines.service'
11
import { Component, Inject, type OnInit } from '@angular/core'
12

13
import { MAT_DIALOG_DATA } from '@angular/material/dialog'
14
import { UntypedFormControl } from '@angular/forms'
15
import { ConfigurationService } from '../Services/configuration.service'
16
import { type ThemePalette } from '@angular/material/core'
17

18
enum ResultState {
19
  Undecided,
20
  Right,
21
  Wrong,
22
}
23

24
export interface Solved {
25
  findIt: boolean
26
  fixIt: boolean
27
}
28

29
export interface RandomFixes {
30
  fix: string
31
  index: number
32
}
33

34
@Component({
35
  selector: 'code-snippet',
36
  templateUrl: './code-snippet.component.html',
37
  styleUrls: ['./code-snippet.component.scss'],
38
  host: { class: 'code-snippet' }
39
})
40
export class CodeSnippetComponent implements OnInit {
41
  public snippet: CodeSnippet = null
42
  public fixes: string [] = null
43
  public selectedLines: number[]
44
  public selectedFix: number = 0
45
  public tab: UntypedFormControl = new UntypedFormControl(0)
46
  public lock: ResultState = ResultState.Undecided
47
  public result: ResultState = ResultState.Undecided
48
  public hint: string = null
49
  public explanation: string = null
50
  public solved: Solved = { findIt: false, fixIt: false }
51
  public showFeedbackButtons: boolean = true
52
  public randomFixes: RandomFixes[] = []
53

54
  constructor (@Inject(MAT_DIALOG_DATA) public dialogData: any, private readonly configurationService: ConfigurationService, private readonly codeSnippetService: CodeSnippetService, private readonly vulnLinesService: VulnLinesService, private readonly codeFixesService: CodeFixesService, private readonly challengeService: ChallengeService, private readonly cookieService: CookieService) { }
55

56
  ngOnInit () {
57
    this.configurationService.getApplicationConfiguration().subscribe((config) => {
58
      this.showFeedbackButtons = config.challenges.showFeedbackButtons
59
    }, (err) => { console.log(err) })
60

61
    this.codeSnippetService.get(this.dialogData.key).subscribe((snippet) => {
62
      this.snippet = snippet
63
      this.solved.findIt = false
64
      if (this.dialogData.codingChallengeStatus >= 1) {
65
        this.result = ResultState.Right
66
        this.lock = ResultState.Right
67
        this.solved.findIt = true
68
      }
69
    }, (err) => {
70
      this.snippet = { snippet: err.error }
71
    })
72
    this.codeFixesService.get(this.dialogData.key).subscribe((fixes) => {
73
      this.fixes = fixes.fixes
74
      if (this.fixes) {
75
        this.shuffle()
76
      }
77
      this.solved.fixIt = this.dialogData.codingChallengeStatus >= 2
78
    }, () => {
79
      this.fixes = null
80
    })
81
  }
82

83
  addLine = (lines: number[]) => {
84
    this.selectedLines = lines
85
  }
86

87
  setFix = (fix: number) => {
88
    this.selectedFix = fix
89
    this.explanation = null
90
  }
91

92
  changeFix (event: Event) {
93
    this.setFix(parseInt((event.target as HTMLSelectElement).value, 10))
94
  }
95

96
  toggleTab = (event: number) => {
97
    this.tab.setValue(event)
98
    this.result = ResultState.Undecided
99
    if (event === 0) {
100
      if (this.solved.findIt) this.result = ResultState.Right
101
    }
102
    if (event === 1) {
103
      if (this.solved.fixIt) this.result = ResultState.Right
104
    }
105
  }
106

107
  checkFix = () => {
108
    this.codeFixesService.check(this.dialogData.key, this.randomFixes[this.selectedFix].index).subscribe((verdict) => {
109
      this.setVerdict(verdict.verdict)
110
      this.explanation = verdict.explanation
111
    })
112
  }
113

114
  checkLines = () => {
115
    this.vulnLinesService.check(this.dialogData.key, this.selectedLines).subscribe((verdict: result) => {
116
      this.setVerdict(verdict.verdict)
117
      this.hint = verdict.hint
118
    })
119
  }
120

121
  lockIcon (): string {
122
    if (this.fixes === null) {
123
      return 'lock'
124
    }
125
    switch (this.lock) {
126
      case ResultState.Right:
127
        return 'lock_open'
128
      case ResultState.Wrong:
129
        return 'lock'
130
      case ResultState.Undecided:
131
        return 'lock'
132
    }
133
  }
134

135
  lockColor (): ThemePalette {
136
    switch (this.lockIcon()) {
137
      case 'lock_open':
138
        return 'accent'
139
      case 'lock':
140
        return 'warn'
141
    }
142
  }
143

144
  shuffle () {
145
    this.randomFixes = this.fixes
146
      .map((fix, index) => ({ fix, index, sort: Math.random() }))
147
      .sort((a, b) => a.sort - b.sort)
148
      .map(({ fix, index }) => ({ fix, index }))
149
  }
150

151
  setVerdict = (verdict: boolean) => {
152
    if (this.result === ResultState.Right) return
153
    if (verdict) {
154
      if (this.tab.value === 0) {
155
        this.solved.findIt = true
156
        this.challengeService.continueCodeFindIt().subscribe((continueCode) => {
157
          if (!continueCode) {
158
            throw (new Error('Received invalid continue code from the server!'))
159
          }
160
          const expires = new Date()
161
          expires.setFullYear(expires.getFullYear() + 1)
162
          this.cookieService.put('continueCodeFindIt', continueCode, { expires })
163
        }, (err) => { console.log(err) })
164
      } else {
165
        this.solved.fixIt = true
166
        this.challengeService.continueCodeFixIt().subscribe((continueCode) => {
167
          if (!continueCode) {
168
            throw (new Error('Received invalid continue code from the server!'))
169
          }
170
          const expires = new Date()
171
          expires.setFullYear(expires.getFullYear() + 1)
172
          this.cookieService.put('continueCodeFixIt', continueCode, { expires })
173
        }, (err) => { console.log(err) })
174
      }
175
      this.result = ResultState.Right
176
      this.lock = ResultState.Right
177
      import('../../confetti').then(module => {
178
        module.shootConfetti()
179
      })
180
        .then(() => {
181
          if (this.tab.value === 0 && this.fixes !== null) this.toggleTab(1)
182
        })
183
    } else {
184
      this.result = ResultState.Wrong
185
    }
186
  }
187

188
  resultIcon (): string {
189
    switch (this.result) {
190
      case ResultState.Right:
191
        return 'check'
192
      case ResultState.Wrong:
193
        return 'clear'
194
      default:
195
        return 'send'
196
    }
197
  }
198

199
  resultColor (): ThemePalette {
200
    switch (this.resultIcon()) {
201
      case 'check':
202
        return 'accent'
203
      case 'clear':
204
        return 'warn'
205
    }
206
  }
207
}
208

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.