Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
TousAntiCovid sources
Cléa Server
Commits
372df546
Commit
372df546
authored
Sep 07, 2021
by
Bergamote Orange
Browse files
wip
parent
0da7a191
Pipeline
#289340
failed with stages
in 7 minutes and 56 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
clea-ws-rest/src/main/java/fr/gouv/clea/ws/service/ReportService.java
View file @
372df546
...
...
@@ -10,16 +10,20 @@ import fr.inria.clea.lsp.exception.CleaEncodingException;
import
fr.inria.clea.lsp.utils.TimeUtils
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.stereotype.Service
;
import
java.time.Duration
;
import
java.time.Instant
;
import
java.time.temporal.ChronoUnit
;
import
java.util.*
;
import
java.util.stream.Collectors
;
import
static
fr
.
gouv
.
clea
.
ws
.
utils
.
MessageFormatter
.
truncateQrCode
;
import
static
java
.
time
.
Instant
.
now
;
import
static
java
.
time
.
temporal
.
ChronoUnit
.
DAYS
;
import
static
java
.
util
.
Base64
.
getUrlDecoder
;
import
static
java
.
util
.
Comparator
.
comparing
;
import
static
java
.
util
.
stream
.
Collectors
.
toList
;
import
static
org
.
apache
.
commons
.
lang3
.
StringUtils
.
isNotBlank
;
@Service
@RequiredArgsConstructor
...
...
@@ -32,8 +36,8 @@ public class ReportService {
private
final
ProducerService
producerService
;
public
int
report
(
Instant
pivotDate
,
List
<
Visit
>
visits
)
{
final
var
now
=
Instant
.
now
();
public
int
report
(
final
Instant
pivotDate
,
final
List
<
Visit
>
visits
)
{
final
var
now
=
now
();
final
var
validatedPivotDate
=
this
.
validatePivotDate
(
pivotDate
,
now
);
final
var
verifiedAndDecodedVisits
=
visits
.
stream
()
...
...
@@ -44,7 +48,7 @@ public class ReportService {
.
filter
(
visit
->
!
isFuture
(
visit
,
now
))
.
map
(
it
->
decode
(
it
,
validatedPivotDate
))
.
filter
(
Objects:
:
nonNull
)
.
collect
(
Collectors
.
toList
());
.
collect
(
toList
());
final
var
uniqueDecodedVisits
=
this
.
pruneDuplicates
(
verifiedAndDecodedVisits
);
producerService
.
produceVisits
(
uniqueDecodedVisits
);
...
...
@@ -52,7 +56,7 @@ public class ReportService {
final
var
closeScanTimeVisits
=
new
VisitsInSameUnitCounter
(
properties
.
getExposureTimeUnitInSeconds
()
);
uniqueDecodedVisits
.
stream
().
sorted
(
Comparator
.
comparing
((
DecodedVisit:
:
getQrCodeScanTime
)))
uniqueDecodedVisits
.
stream
().
sorted
(
comparing
((
DecodedVisit:
:
getQrCodeScanTime
)))
.
forEach
(
closeScanTimeVisits:
:
incrementIfScannedInSameTimeUnitThanLastScanTime
);
producerService
.
produceStat
(
...
...
@@ -68,55 +72,55 @@ public class ReportService {
return
uniqueDecodedVisits
.
size
();
}
private
boolean
nonBlankBase64urlLocationSpecificPart
(
Visit
visit
)
{
return
StringUtils
.
isNotBlank
(
visit
.
getLocationSpecificPart
());
private
boolean
nonBlankBase64urlLocationSpecificPart
(
final
Visit
visit
)
{
return
isNotBlank
(
visit
.
getLocationSpecificPart
());
}
private
boolean
nonNullScanTime
(
Visit
visit
)
{
return
visit
.
get
QrCode
ScanTime
()
!=
null
;
private
boolean
nonNullScanTime
(
final
Visit
visit
)
{
return
visit
.
getScanTime
()
!=
null
;
}
private
DecodedVisit
decode
(
Visit
visit
,
Instant
pivotDate
)
{
private
DecodedVisit
decode
(
final
Visit
visit
,
final
Instant
pivotDate
)
{
try
{
final
var
binaryLocationSpecificPart
=
Base64
.
getUrlDecoder
().
decode
(
visit
.
getLocationSpecificPart
());
final
var
binaryLocationSpecificPart
=
getUrlDecoder
().
decode
(
visit
.
getLocationSpecificPart
());
return
DecodedVisit
.
builder
()
.
encryptedLocationSpecificPart
(
decoder
.
decodeHeader
(
binaryLocationSpecificPart
))
.
qrCodeScanTime
(
visit
.
get
QrCode
ScanTime
())
.
isBackward
(
visit
.
get
QrCode
ScanTime
().
isBefore
(
pivotDate
))
.
qrCodeScanTime
(
visit
.
getScanTime
())
.
isBackward
(
visit
.
getScanTime
().
isBefore
(
pivotDate
))
.
build
();
}
catch
(
CleaEncodingException
e
)
{
log
.
warn
(
"report: {} rejected: Invalid format"
,
MessageFormatter
.
truncateQrCode
(
visit
.
getLocationSpecificPart
())
truncateQrCode
(
visit
.
getLocationSpecificPart
())
);
return
null
;
}
}
private
boolean
isOutdated
(
Visit
visit
,
Instant
now
)
{
final
var
daysBetweenScanTimeAndNow
=
DAYS
.
between
(
visit
.
get
QrCode
ScanTime
(),
now
);
private
boolean
isOutdated
(
final
Visit
visit
,
final
Instant
now
)
{
final
var
daysBetweenScanTimeAndNow
=
DAYS
.
between
(
visit
.
getScanTime
(),
now
);
if
(
daysBetweenScanTimeAndNow
>
properties
.
getRetentionDurationInDays
())
{
log
.
warn
(
"report: {} rejected: Outdated"
,
MessageFormatter
.
truncateQrCode
(
visit
.
getLocationSpecificPart
()));
log
.
warn
(
"report: {} rejected: Outdated"
,
truncateQrCode
(
visit
.
getLocationSpecificPart
()));
return
true
;
}
return
false
;
}
private
boolean
isFuture
(
Visit
visit
,
Instant
now
)
{
boolean
future
=
visit
.
get
QrCode
ScanTime
().
isAfter
(
now
);
private
boolean
isFuture
(
final
Visit
visit
,
final
Instant
now
)
{
boolean
future
=
visit
.
getScanTime
().
isAfter
(
now
);
if
(
future
)
{
log
.
warn
(
"report: {} rejected: In future"
,
MessageFormatter
.
truncateQrCode
(
visit
.
getLocationSpecificPart
())
"report: {} rejected: In future"
,
truncateQrCode
(
visit
.
getLocationSpecificPart
())
);
}
return
future
;
}
private
boolean
isDuplicatedScan
(
DecodedVisit
lsp
,
List
<
DecodedVisit
>
cleaned
)
{
private
boolean
isDuplicatedScan
(
final
DecodedVisit
lsp
,
final
List
<
DecodedVisit
>
cleaned
)
{
return
cleaned
.
stream
().
anyMatch
(
cleanedLsp
->
this
.
isDuplicatedScan
(
lsp
,
cleanedLsp
));
}
private
boolean
isDuplicatedScan
(
DecodedVisit
one
,
DecodedVisit
other
)
{
private
boolean
isDuplicatedScan
(
final
DecodedVisit
one
,
final
DecodedVisit
other
)
{
if
(!
one
.
getLocationTemporaryPublicId
().
equals
(
other
.
getLocationTemporaryPublicId
()))
{
return
false
;
}
...
...
@@ -134,7 +138,7 @@ public class ReportService {
return
false
;
}
private
List
<
DecodedVisit
>
pruneDuplicates
(
List
<
DecodedVisit
>
locationSpecificParts
)
{
private
List
<
DecodedVisit
>
pruneDuplicates
(
final
List
<
DecodedVisit
>
locationSpecificParts
)
{
List
<
DecodedVisit
>
cleaned
=
new
ArrayList
<>();
locationSpecificParts
.
forEach
(
it
->
{
if
(!
this
.
isDuplicatedScan
(
it
,
cleaned
))
{
...
...
@@ -144,7 +148,7 @@ public class ReportService {
return
cleaned
;
}
private
Instant
validatePivotDate
(
Instant
pivotDate
,
Instant
now
)
{
private
Instant
validatePivotDate
(
final
Instant
pivotDate
,
final
Instant
now
)
{
Instant
nowWithoutMilis
=
now
.
truncatedTo
(
ChronoUnit
.
SECONDS
);
Instant
retentionDateLimit
=
nowWithoutMilis
.
minus
(
properties
.
getRetentionDurationInDays
(),
DAYS
);
if
(
pivotDate
.
isAfter
(
now
)
||
pivotDate
.
isBefore
(
retentionDateLimit
))
{
...
...
clea-ws-rest/src/main/java/fr/gouv/clea/ws/service/model/Visit.java
View file @
372df546
...
...
@@ -15,11 +15,11 @@ public class Visit {
*/
String
locationSpecificPart
;
Instant
qrCodeS
canTime
;
Instant
s
canTime
;
public
Visit
(
String
locationSpecificPart
,
Long
qrCodeS
canTimeAsNtpTimestamp
)
{
public
Visit
(
String
locationSpecificPart
,
Long
s
canTimeAsNtpTimestamp
)
{
this
.
locationSpecificPart
=
locationSpecificPart
;
this
.
qrCodeS
canTime
=
qrCodeS
canTimeAsNtpTimestamp
==
null
?
null
:
TimeUtils
.
instantFromTimestamp
(
qrCodeS
canTimeAsNtpTimestamp
);
this
.
s
canTime
=
s
canTimeAsNtpTimestamp
==
null
?
null
:
TimeUtils
.
instantFromTimestamp
(
s
canTimeAsNtpTimestamp
);
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment