Skip to content

Commit c6da2c0

Browse files
committed
fix: address Copilot review feedback
- flag_3.py: add module logger, use log.debug instead of logging.info, two-step getattr for adversary, two blank lines before class, remove emoji from log messages, revert flag name to 'Empty operation' - training.vue: wrap all localStorage accesses in try/catch, add schema migration to support old selectedBadge key alongside new selectedBadgeName
1 parent 80a46dd commit c6da2c0

2 files changed

Lines changed: 28 additions & 15 deletions

File tree

app/flags/operations/flag_3.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import logging
2+
23
from plugins.training.app.c_flag import Flag
34

5+
log = logging.getLogger(__name__)
6+
7+
48
class OperationsFlag3(Flag):
5-
name = 'Empty Op'
9+
name = 'Empty operation'
610

711
challenge = (
812
'Run and finish an operation without selecting any agent groups or adversary profiles. Add at least 5 manual '
@@ -17,12 +21,15 @@ class OperationsFlag3(Flag):
1721
async def verify(self, services):
1822
data_svc = services.get('data_svc')
1923
if not data_svc:
20-
logging.error("[training.flag3] data_svc is None!")
24+
log.debug("[training.flag3] data_svc is None!")
2125
return False
2226

2327
operations = await data_svc.locate('operations')
2428
for op in operations:
25-
logging.info(f"[training.flag3] Checking operation '{op.name}' | state={op.state}, group={op.group}, adversary_id={getattr(op.adversary, 'adversary_id', None)}")
29+
adversary = getattr(op, 'adversary', None)
30+
adversary_id = getattr(adversary, 'adversary_id', None)
31+
log.debug("[training.flag3] Checking operation '%s' | state=%s, group=%s, adversary_id=%s",
32+
op.name, op.state, op.group, adversary_id)
2633

2734
# Gather all link lists that might exist
2835
chain_links = getattr(op, 'chain', []) or []
@@ -31,17 +38,18 @@ async def verify(self, services):
3138

3239
total_links = len(chain_links) + len(potential_links) + len(manual_links)
3340

34-
logging.info(f"[training.flag3] Found {len(chain_links)} chain links, {len(potential_links)} potential links, {len(manual_links)} manual links (total={total_links})")
41+
log.debug("[training.flag3] Found %d chain links, %d potential links, %d manual links (total=%d)",
42+
len(chain_links), len(potential_links), len(manual_links), total_links)
3543

3644
# Verify completion conditions
3745
if (
3846
op.finish
39-
and getattr(op.adversary, 'adversary_id', None) == 'ad-hoc'
47+
and adversary_id == 'ad-hoc'
4048
and total_links >= 5
4149
and not op.group
4250
):
43-
logging.info(f"[training.flag3] Operation '{op.name}' meets all criteria!")
51+
log.debug("[training.flag3] Operation '%s' meets all criteria!", op.name)
4452
return True
4553

46-
logging.info("[training.flag3] No operation met the criteria.")
47-
return False
54+
log.debug("[training.flag3] No operation met the criteria.")
55+
return False

gui/views/training.vue

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ const certificates = ref([
1717
{ name: "Blue Certificate" },
1818
]);
1919
20-
const learnerName = ref(localStorage.getItem('trainingCertName') || '');
20+
let _savedCertName = '';
21+
try { _savedCertName = localStorage.getItem('trainingCertName') || ''; } catch (e) { /* storage unavailable */ }
22+
const learnerName = ref(_savedCertName);
2123
const showIssueModal = ref(false);
2224
const skipSelectionWatcher = ref(false);
2325
@@ -67,7 +69,9 @@ watch(
6769
6870
function saveNameLocally() {
6971
const n = learnerName.value.trim();
70-
if (n) localStorage.setItem('trainingCertName', n);
72+
if (n) {
73+
try { localStorage.setItem('trainingCertName', n); } catch (e) { /* storage unavailable */ }
74+
}
7175
}
7276
7377
async function issueCertificate() {
@@ -117,14 +121,15 @@ async function issueCertificate() {
117121
}
118122
119123
const restoreSelections = () => {
120-
const savedState = localStorage.getItem("trainingState");
124+
let savedState = null;
125+
try { savedState = localStorage.getItem("trainingState"); } catch (e) { /* storage unavailable */ }
121126
if (savedState) {
122127
try {
123128
const parsed = JSON.parse(savedState);
124129
selectedCert.value = parsed.selectedCert || "";
125-
selectedBadge.value = parsed.selectedBadgeName
126-
? { name: parsed.selectedBadgeName }
127-
: "";
130+
// Support both new key (selectedBadgeName) and old key (selectedBadge) for migration
131+
const badgeName = parsed.selectedBadgeName || parsed.selectedBadge?.name || "";
132+
selectedBadge.value = badgeName ? { name: badgeName } : null;
128133
} catch (err) {
129134
console.warn("Failed to parse saved training state:", err);
130135
}
@@ -138,7 +143,7 @@ const persistSelections = () => {
138143
selectedCert: selectedCert.value,
139144
selectedBadgeName: selectedBadge.value?.name || "",
140145
};
141-
localStorage.setItem("trainingState", JSON.stringify(state));
146+
try { localStorage.setItem("trainingState", JSON.stringify(state)); } catch (e) { /* storage unavailable */ }
142147
};
143148
144149
const getTraining = () => {

0 commit comments

Comments
 (0)