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