1 /*!
2 * \copyright Copyright (c) 2015-2021 Governikus GmbH & Co. KG, Germany
3 */
4
5 #include "WorkflowContext.h"
6
7 #include "ReaderManager.h"
8
9 #include <QWeakPointer>
10
11 using namespace governikus;
12
13
onWorkflowCancelled()14 void WorkflowContext::onWorkflowCancelled()
15 {
16 mWorkflowCancelled = true;
17 }
18
19
WorkflowContext()20 WorkflowContext::WorkflowContext()
21 : QObject()
22 , mStateApproved(false)
23 , mWorkflowKilled(false)
24 , mCurrentState(QStringLiteral("Initial"))
25 , mReaderPlugInTypes()
26 , mReaderName()
27 , mCardConnection()
28 , mCardVanishedDuringPacePinCount(0)
29 , mCardVanishedDuringPacePinTimer()
30 , mCan()
31 , mPin()
32 , mPuk()
33 , mEstablishPaceChannelType(PacePasswordId::UNKNOWN)
34 , mPaceOutputData()
35 , mExpectedReader()
36 , mLastPaceResult(CardReturnCode::OK)
37 , mStatus(GlobalStatus::Code::No_Error)
38 , mStartPaosResult(ECardApiResult::createOk())
39 , mErrorReportedToUser(true)
40 , mPaceResultReportedToUser(false)
41 , mWorkflowFinished(false)
42 , mWorkflowCancelled(false)
43 , mWorkflowCancelledInState(false)
44 , mNextWorkflowPending(false)
45 , mCurrentReaderHasEidCardButInsufficientApduLength(false)
46 {
47 connect(this, &WorkflowContext::fireCancelWorkflow, this, &WorkflowContext::onWorkflowCancelled);
48 }
49
50
~WorkflowContext()51 WorkflowContext::~WorkflowContext()
52 {
53 #ifndef QT_NO_DEBUG
54 if (!QCoreApplication::applicationName().startsWith(QLatin1String("Test")))
55 {
56 Q_ASSERT(getPin().isEmpty() && "PACE passwords must be cleared as soon as possible.");
57 Q_ASSERT(getCan().isEmpty() && "PACE passwords must be cleared as soon as possible.");
58 Q_ASSERT(getPuk().isEmpty() && "PACE passwords must be cleared as soon as possible.");
59 }
60 #endif
61 }
62
63
isErrorReportedToUser() const64 bool WorkflowContext::isErrorReportedToUser() const
65 {
66 return mErrorReportedToUser || mWorkflowKilled;
67 }
68
69
setErrorReportedToUser(bool pErrorReportedToUser)70 void WorkflowContext::setErrorReportedToUser(bool pErrorReportedToUser)
71 {
72 mErrorReportedToUser = pErrorReportedToUser;
73 }
74
75
isPaceResultReportedToUser() const76 bool WorkflowContext::isPaceResultReportedToUser() const
77 {
78 return mPaceResultReportedToUser;
79 }
80
81
setPaceResultReportedToUser(bool pReported)82 void WorkflowContext::setPaceResultReportedToUser(bool pReported)
83 {
84 mPaceResultReportedToUser = pReported;
85 }
86
87
setStateApproved(bool pApproved)88 void WorkflowContext::setStateApproved(bool pApproved)
89 {
90 if (mStateApproved != pApproved)
91 {
92 mStateApproved = pApproved;
93 Q_EMIT fireStateApprovedChanged(mStateApproved);
94 }
95 }
96
97
killWorkflow()98 void WorkflowContext::killWorkflow()
99 {
100 qWarning() << "Killing the current workflow.";
101 mWorkflowKilled = true;
102 mStatus = GlobalStatus::Code::Card_Cancellation_By_User;
103 if (!mStateApproved)
104 {
105 setStateApproved(true);
106 }
107
108 Q_EMIT fireCancelWorkflow();
109 }
110
111
isWorkflowKilled() const112 bool WorkflowContext::isWorkflowKilled() const
113 {
114 return mWorkflowKilled;
115 }
116
117
isStateApproved() const118 bool WorkflowContext::isStateApproved() const
119 {
120 return mStateApproved;
121 }
122
123
getCurrentState() const124 const QString& WorkflowContext::getCurrentState() const
125 {
126 return mCurrentState;
127 }
128
129
setCurrentState(const QString & pNewState)130 void WorkflowContext::setCurrentState(const QString& pNewState)
131 {
132 mCurrentState = pNewState;
133 Q_EMIT fireStateChanged(pNewState);
134
135 if (mWorkflowKilled)
136 {
137 setStateApproved(true);
138 }
139 }
140
141
getReaderPlugInTypes() const142 const QVector<ReaderManagerPlugInType>& WorkflowContext::getReaderPlugInTypes() const
143 {
144 return mReaderPlugInTypes;
145 }
146
147
setReaderPlugInTypes(const QVector<ReaderManagerPlugInType> & pReaderPlugInTypes)148 void WorkflowContext::setReaderPlugInTypes(const QVector<ReaderManagerPlugInType>& pReaderPlugInTypes)
149 {
150 if (mReaderPlugInTypes != pReaderPlugInTypes)
151 {
152 mReaderPlugInTypes = pReaderPlugInTypes;
153 Q_EMIT fireReaderPlugInTypesChanged();
154 }
155 }
156
157
getReaderName() const158 const QString& WorkflowContext::getReaderName() const
159 {
160 return mReaderName;
161 }
162
163
setReaderName(const QString & pReaderName)164 void WorkflowContext::setReaderName(const QString& pReaderName)
165 {
166 if (mReaderName != pReaderName)
167 {
168 mReaderName = pReaderName;
169 Q_EMIT fireReaderNameChanged();
170 }
171 }
172
173
getCardConnection() const174 const QSharedPointer<CardConnection>& WorkflowContext::getCardConnection() const
175 {
176 return mCardConnection;
177 }
178
179
setCardConnection(const QSharedPointer<CardConnection> & pCardConnection)180 void WorkflowContext::setCardConnection(const QSharedPointer<CardConnection>& pCardConnection)
181 {
182 if (mCardConnection != pCardConnection)
183 {
184 mCardConnection = pCardConnection;
185 Q_EMIT fireCardConnectionChanged();
186 }
187 }
188
189
resetCardConnection()190 void WorkflowContext::resetCardConnection()
191 {
192 setCardConnection(QSharedPointer<CardConnection>());
193 if (!mReaderName.isEmpty())
194 {
195 const auto readerManager = Env::getSingleton<ReaderManager>();
196 readerManager->updateReaderInfo(mReaderName);
197 }
198 }
199
200
isNpaRepositioningRequired() const201 bool WorkflowContext::isNpaRepositioningRequired() const
202 {
203 if (mCardVanishedDuringPacePinCount >= 10)
204 {
205 return true;
206 }
207
208 const qint64 fourSeconds = 4000;
209 if (mCardVanishedDuringPacePinTimer.isValid() && mCardVanishedDuringPacePinTimer.elapsed() > fourSeconds)
210 {
211 return true;
212 }
213
214 return false;
215 }
216
217
setNpaPositionVerified()218 void WorkflowContext::setNpaPositionVerified()
219 {
220 mCardVanishedDuringPacePinCount = 0;
221 mCardVanishedDuringPacePinTimer.invalidate();
222 }
223
224
handleWrongNpaPosition()225 void WorkflowContext::handleWrongNpaPosition()
226 {
227 if (mCardVanishedDuringPacePinCount > 0 && !mCardVanishedDuringPacePinTimer.isValid())
228 {
229 mCardVanishedDuringPacePinTimer.restart();
230 }
231 mCardVanishedDuringPacePinCount += 1;
232 resetCardConnection();
233 }
234
235
isPinBlocked()236 bool WorkflowContext::isPinBlocked()
237 {
238 return mCardConnection != nullptr && mCardConnection->getReaderInfo().getRetryCounter() == 0;
239 }
240
241
getPuk() const242 const QString& WorkflowContext::getPuk() const
243 {
244 return mPuk;
245 }
246
247
setPuk(const QString & pPuk)248 void WorkflowContext::setPuk(const QString& pPuk)
249 {
250 if (mPuk != pPuk)
251 {
252 mPuk = pPuk;
253 Q_EMIT firePukChanged();
254 }
255 }
256
257
getCan() const258 const QString& WorkflowContext::getCan() const
259 {
260 return mCan;
261 }
262
263
setCan(const QString & pCan)264 void WorkflowContext::setCan(const QString& pCan)
265 {
266 if (mCan != pCan)
267 {
268 mCan = pCan;
269 Q_EMIT fireCanChanged();
270 }
271 }
272
273
getPin() const274 const QString& WorkflowContext::getPin() const
275 {
276 return mPin;
277 }
278
279
setPin(const QString & pPin)280 void WorkflowContext::setPin(const QString& pPin)
281 {
282 if (mPin != pPin)
283 {
284 mPin = pPin;
285 Q_EMIT firePinChanged();
286 }
287 }
288
289
getEstablishPaceChannelType() const290 PacePasswordId WorkflowContext::getEstablishPaceChannelType() const
291 {
292 return mEstablishPaceChannelType;
293 }
294
295
setEstablishPaceChannelType(PacePasswordId pType)296 void WorkflowContext::setEstablishPaceChannelType(PacePasswordId pType)
297 {
298 mEstablishPaceChannelType = pType;
299 Q_EMIT firePasswordTypeChanged();
300 }
301
302
resetPacePasswords()303 void WorkflowContext::resetPacePasswords()
304 {
305 setCan(QString());
306 setPin(QString());
307 setPuk(QString());
308 }
309
310
getPaceOutputData() const311 EstablishPaceChannelOutput* WorkflowContext::getPaceOutputData() const
312 {
313 return mPaceOutputData.data();
314 }
315
316
setPaceOutputData(const EstablishPaceChannelOutput & pPaceOutputData)317 void WorkflowContext::setPaceOutputData(const EstablishPaceChannelOutput& pPaceOutputData)
318 {
319 mPaceOutputData.reset(new EstablishPaceChannelOutput(pPaceOutputData));
320 }
321
322
getLastPaceResult() const323 CardReturnCode WorkflowContext::getLastPaceResult() const
324 {
325 return mLastPaceResult;
326 }
327
328
setLastPaceResult(CardReturnCode pLastPaceResult)329 void WorkflowContext::setLastPaceResult(CardReturnCode pLastPaceResult)
330 {
331 mPaceResultReportedToUser = false;
332 mLastPaceResult = pLastPaceResult;
333 Q_EMIT firePaceResultUpdated();
334 }
335
336
resetLastPaceResult()337 void WorkflowContext::resetLastPaceResult()
338 {
339 setLastPaceResult(CardReturnCode::OK);
340 }
341
342
rememberReader()343 void WorkflowContext::rememberReader()
344 {
345 if (mCardConnection)
346 {
347 mExpectedReader = mCardConnection->getReaderInfo();
348 }
349 else
350 {
351 mExpectedReader = ReaderInfo();
352 }
353 }
354
355
isExpectedReader() const356 bool WorkflowContext::isExpectedReader() const
357 {
358 return mExpectedReader.getName() == mReaderName;
359 }
360
361
getExpectedReader() const362 const ReaderInfo& WorkflowContext::getExpectedReader() const
363 {
364 return mExpectedReader;
365 }
366
367
getExpectedRetryCounter() const368 int WorkflowContext::getExpectedRetryCounter() const
369 {
370 return mExpectedReader.getCardInfo().getRetryCounter();
371 }
372
373
setExpectedRetryCounter(int pExpectedRetryCounter)374 void WorkflowContext::setExpectedRetryCounter(int pExpectedRetryCounter)
375 {
376 mExpectedReader.getCardInfo().setRetryCounter(pExpectedRetryCounter);
377 }
378
379
getStatus() const380 const GlobalStatus& WorkflowContext::getStatus() const
381 {
382 return mStatus;
383 }
384
385
setStatus(const GlobalStatus & pStatus)386 void WorkflowContext::setStatus(const GlobalStatus& pStatus)
387 {
388 mStatus = pStatus;
389 mErrorReportedToUser = false;
390 Q_EMIT fireResultChanged();
391 }
392
393
getStartPaosResult() const394 const ECardApiResult WorkflowContext::getStartPaosResult() const
395 {
396 return mStartPaosResult;
397 }
398
399
setStartPaosResult(const ECardApiResult & pStartPaosResult)400 void WorkflowContext::setStartPaosResult(const ECardApiResult& pStartPaosResult)
401 {
402 mStartPaosResult = pStartPaosResult;
403 }
404
405
isWorkflowFinished() const406 bool WorkflowContext::isWorkflowFinished() const
407 {
408 return mWorkflowFinished;
409 }
410
411
setWorkflowFinished(bool pWorkflowFinished)412 void WorkflowContext::setWorkflowFinished(bool pWorkflowFinished)
413 {
414 mWorkflowFinished = pWorkflowFinished;
415 }
416
417
isWorkflowCancelled() const418 bool WorkflowContext::isWorkflowCancelled() const
419 {
420 return mWorkflowCancelled;
421 }
422
423
isWorkflowCancelledInState() const424 bool WorkflowContext::isWorkflowCancelledInState() const
425 {
426 return mWorkflowCancelledInState;
427 }
428
429
setWorkflowCancelledInState()430 void WorkflowContext::setWorkflowCancelledInState()
431 {
432 mWorkflowCancelledInState = true;
433 }
434
435
isCanAllowedMode() const436 bool WorkflowContext::isCanAllowedMode() const
437 {
438 return false;
439 }
440
441
hasNextWorkflowPending() const442 bool WorkflowContext::hasNextWorkflowPending() const
443 {
444 return mNextWorkflowPending;
445 }
446
447
setNextWorkflowPending(bool pNextWorkflowPending)448 void WorkflowContext::setNextWorkflowPending(bool pNextWorkflowPending)
449 {
450 if (pNextWorkflowPending != mNextWorkflowPending)
451 {
452 mNextWorkflowPending = pNextWorkflowPending;
453 Q_EMIT fireNextWorkflowPending();
454 }
455 }
456
457
currentReaderHasEidCardButInsufficientApduLength() const458 bool WorkflowContext::currentReaderHasEidCardButInsufficientApduLength() const
459 {
460 return mCurrentReaderHasEidCardButInsufficientApduLength;
461 }
462
463
setCurrentReaderHasEidCardButInsufficientApduLength(bool pState)464 void WorkflowContext::setCurrentReaderHasEidCardButInsufficientApduLength(bool pState)
465 {
466 if (pState != mCurrentReaderHasEidCardButInsufficientApduLength)
467 {
468 mCurrentReaderHasEidCardButInsufficientApduLength = pState;
469 Q_EMIT fireReaderInfoChanged();
470 }
471 }
472