Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Liveness Timeout Images #253

Open
wants to merge 19 commits into
base: new-smart-selfie-capture
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/auto-author-assign.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# .github/workflows/auto-author-assign.yml
name: Auto Author Assign

on:
pull_request_target:
types: [opened, reopened]

permissions:
pull-requests: write

jobs:
assign-author:
if: ${{ !contains(github.event.pull_request.assignees, '') }}
runs-on: ubuntu-latest
steps:
- uses: toshimaru/auto-author-assign@v2.1.1
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Release Notes

## 10.2.17
### Added skipApiSubmission: Whether to skip api submission to SmileID and return only captured images on SmartSelfie enrollment, SmartSelfie authentic , Document verification and Enhanced DocV

## 10.2.16
### Fixed
* Clear images on retry or start capture with the same jobId
Expand Down
4 changes: 2 additions & 2 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ PODS:
- Sentry (8.36.0):
- Sentry/Core (= 8.36.0)
- Sentry/Core (8.36.0)
- SmileID (10.2.16):
- SmileID (10.2.17):
- FingerprintJS
- lottie-ios (~> 4.4.2)
- ZIPFoundation (~> 0.9)
Expand Down Expand Up @@ -51,7 +51,7 @@ SPEC CHECKSUMS:
lottie-ios: fcb5e73e17ba4c983140b7d21095c834b3087418
netfox: 9d5cc727fe7576c4c7688a2504618a156b7d44b7
Sentry: f8374b5415bc38dfb5645941b3ae31230fbeae57
SmileID: 93184d185549dec6858a3cc567bd9423de79abbb
SmileID: dc04628f6e1572fc6e407649bfd05f91647ed947
SwiftLint: 3fe909719babe5537c552ee8181c0031392be933
ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c

Expand Down
8 changes: 4 additions & 4 deletions Example/SmileID.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 36;
CURRENT_PROJECT_VERSION = 37;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 99P7YGX9Q6;
Expand All @@ -901,7 +901,7 @@
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.3.0;
MARKETING_VERSION = 1.3.1;
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "com.smileidentity.example-ios";
PRODUCT_NAME = "Smile ID";
Expand All @@ -924,7 +924,7 @@
CODE_SIGN_IDENTITY = "Apple Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 36;
CURRENT_PROJECT_VERSION = 37;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 99P7YGX9Q6;
Expand All @@ -934,7 +934,7 @@
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.3.0;
MARKETING_VERSION = 1.3.1;
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "com.smileidentity.example-ios";
PRODUCT_NAME = "Smile ID";
Expand Down
4 changes: 2 additions & 2 deletions Example/SmileID/Home/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct HomeView: View {
)
ProductCell(
image: "smart_selfie_enroll",
name: "SmartSelfie™ Enrollment (Strict Mode)",
name: "SmartSelfie™ Enrollment (Strict Mode)\n(BETA)",
onClick: {
viewModel.onProductClicked()
},
Expand All @@ -74,7 +74,7 @@ struct HomeView: View {
)
ProductCell(
image: "smart_selfie_authentication",
name: "SmartSelfie™ Authentication (Strict Mode)",
name: "SmartSelfie™ Authentication (Strict Mode)\n(BETA)",
onClick: {
viewModel.onProductClicked()
},
Expand Down
10 changes: 10 additions & 0 deletions Example/SmileID/Home/ProductCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ struct ProductCell<Content: View>: View {
content: {
NavigationView {
content()
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button {
isPresented = false
} label: {
Text(SmileIDResourcesHelper.localizedString(for: "Action.Cancel"))
.foregroundColor(SmileID.theme.accent)
}
}
}
}
.environment(\.modalMode, $isPresented)
}
Expand Down
30 changes: 5 additions & 25 deletions Example/Tests/FaceValidatorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ class FaceValidatorTests: XCTestCase {
func testValidateWithValidFace() {
let result = performValidation(
faceBoundingBox: CGRect(x: 65, y: 164, width: 190, height: 190),
selfieQualityData: SelfieQualityData(failed: 0.1, passed: 0.9),
brighness: 100
selfieQualityData: SelfieQualityData(failed: 0.1, passed: 0.9)
)

XCTAssertTrue(result.faceInBounds)
Expand All @@ -36,8 +35,7 @@ class FaceValidatorTests: XCTestCase {
func testValidateWithFaceTooSmall() {
let result = performValidation(
faceBoundingBox: CGRect(x: 65, y: 164, width: 100, height: 100),
selfieQualityData: SelfieQualityData(failed: 0.1, passed: 0.9),
brighness: 100
selfieQualityData: SelfieQualityData(failed: 0.1, passed: 0.9)
)

XCTAssertFalse(result.faceInBounds)
Expand All @@ -48,8 +46,7 @@ class FaceValidatorTests: XCTestCase {
func testValidateWithFaceTooLarge() {
let result = performValidation(
faceBoundingBox: CGRect(x: 65, y: 164, width: 250, height: 250),
selfieQualityData: SelfieQualityData(failed: 0.1, passed: 0.9),
brighness: 100
selfieQualityData: SelfieQualityData(failed: 0.1, passed: 0.9)
)

XCTAssertFalse(result.faceInBounds)
Expand All @@ -60,32 +57,18 @@ class FaceValidatorTests: XCTestCase {
func testValidWithFaceOffCentre() {
let result = performValidation(
faceBoundingBox: CGRect(x: 125, y: 164, width: 190, height: 190),
selfieQualityData: SelfieQualityData(failed: 0.1, passed: 0.9),
brighness: 100
selfieQualityData: SelfieQualityData(failed: 0.1, passed: 0.9)
)

XCTAssertFalse(result.faceInBounds)
XCTAssertFalse(result.hasDetectedValidFace)
XCTAssertEqual(result.userInstruction, .headInFrame)
}

func testValidateWithPoorBrightness() {
let result = performValidation(
faceBoundingBox: CGRect(x: 65, y: 164, width: 190, height: 190),
selfieQualityData: SelfieQualityData(failed: 0.1, passed: 0.9),
brighness: 70
)

XCTAssertTrue(result.faceInBounds)
XCTAssertFalse(result.hasDetectedValidFace)
XCTAssertEqual(result.userInstruction, .goodLight)
}

func testValidateWithPoorSelfieQuality() {
let result = performValidation(
faceBoundingBox: CGRect(x: 65, y: 164, width: 190, height: 190),
selfieQualityData: SelfieQualityData(failed: 0.6, passed: 0.4),
brighness: 70
selfieQualityData: SelfieQualityData(failed: 0.6, passed: 0.4)
)

XCTAssertTrue(result.faceInBounds)
Expand All @@ -97,7 +80,6 @@ class FaceValidatorTests: XCTestCase {
let result = performValidation(
faceBoundingBox: CGRect(x: 65, y: 164, width: 190, height: 190),
selfieQualityData: SelfieQualityData(failed: 0.3, passed: 0.7),
brighness: 100,
livenessTask: .lookLeft
)

Expand All @@ -112,7 +94,6 @@ extension FaceValidatorTests {
func performValidation(
faceBoundingBox: CGRect,
selfieQualityData: SelfieQualityData,
brighness: Int,
livenessTask: LivenessTask? = nil
) -> FaceValidationResult {
let faceGeometry = FaceGeometryData(
Expand All @@ -125,7 +106,6 @@ extension FaceValidatorTests {
faceValidator.validate(
faceGeometry: faceGeometry,
selfieQuality: selfieQualityData,
brightness: brighness,
currentLivenessTask: livenessTask
)

Expand Down
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
{
"pins" : [
{
"identity" : "fingerprintjs-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/fingerprintjs/fingerprintjs-ios",
"state" : {
"revision" : "bd93291c149e328919a9a2881575494f6ea9245f",
"version" : "1.5.0"
}
},
{
"identity" : "lottie-spm",
"kind" : "remoteSourceControl",
Expand Down
8 changes: 6 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/weichsel/ZIPFoundation.git", .upToNextMajor(from: "0.9.0")),
.package(url: "https://github.com/airbnb/lottie-spm", from: "4.4.2"),
.package(url: "https://github.com/fingerprintjs/fingerprintjs-ios", from: "4.4.2")
.package(url: "https://github.com/fingerprintjs/fingerprintjs-ios", from: "1.5.0")
],
targets: [
.target(
name: "SmileID",
dependencies: ["ZIPFoundation", "FingerprintJS", .product(name: "Lottie", package: "lottie-spm")],
dependencies: [
.product(name: "ZIPFoundation", package: "ZIPFoundation"),
.product(name: "FingerprintJS", package: "fingerprintjs-ios"),
.product(name: "Lottie", package: "lottie-spm")
],
path: "Sources/SmileID",
resources: [.process("Resources")]
),
Expand Down
4 changes: 2 additions & 2 deletions SmileID.podspec
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Pod::Spec.new do |s|
s.name = 'SmileID'
s.version = '10.2.16'
s.version = '10.2.17'
s.summary = 'The Official Smile Identity iOS SDK.'
s.homepage = 'https://docs.usesmileid.com/integration-options/mobile/ios-v10-beta'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'Japhet' => 'japhet@usesmileid.com', 'Juma Allan' => 'juma@usesmileid.com', 'Vansh Gandhi' => 'vansh@usesmileid.com'}
s.source = { :git => "https://github.com/smileidentity/ios.git", :tag => "v10.2.16" }
s.source = { :git => "https://github.com/smileidentity/ios.git", :tag => "v10.2.17" }
s.ios.deployment_target = '13.0'
s.dependency 'ZIPFoundation', '~> 0.9'
s.dependency 'FingerprintJS'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,27 @@ enum DocumentCaptureFlow: Equatable {
case processing(ProcessingState)
}

internal class IOrchestratedDocumentVerificationViewModel<T, U: JobResult>: ObservableObject {
class IOrchestratedDocumentVerificationViewModel<T, U: JobResult>: ObservableObject {
// Input properties
internal let userId: String
internal let jobId: String
internal let allowNewEnroll: Bool
internal let countryCode: String
internal let documentType: String?
internal let captureBothSides: Bool
internal let jobType: JobType
internal let extraPartnerParams: [String: String]
let userId: String
let jobId: String
let allowNewEnroll: Bool
let countryCode: String
let documentType: String?
let captureBothSides: Bool
let skipApiSubmission: Bool
let jobType: JobType
let extraPartnerParams: [String: String]

// Other properties
internal var documentFrontFile: Data?
internal var documentBackFile: Data?
internal var selfieFile: URL?
internal var livenessFiles: [URL]?
internal var savedFiles: DocumentCaptureResultStore?
internal var stepToRetry: DocumentCaptureFlow?
internal var didSubmitJob: Bool = false
internal var error: Error?
var documentFrontFile: Data?
var documentBackFile: Data?
var selfieFile: URL?
var livenessFiles: [URL]?
var savedFiles: DocumentCaptureResultStore?
var stepToRetry: DocumentCaptureFlow?
var didSubmitJob: Bool = false
var error: Error?
var localMetadata: LocalMetadata

// UI properties
Expand All @@ -39,13 +40,14 @@ internal class IOrchestratedDocumentVerificationViewModel<T, U: JobResult>: Obse
@Published var errorMessage: String?
@Published var step = DocumentCaptureFlow.frontDocumentCapture

internal init(
init(
userId: String,
jobId: String,
allowNewEnroll: Bool,
countryCode: String,
documentType: String?,
captureBothSides: Bool,
skipApiSubmission: Bool,
selfieFile: URL?,
jobType: JobType,
extraPartnerParams: [String: String] = [:],
Expand All @@ -57,6 +59,7 @@ internal class IOrchestratedDocumentVerificationViewModel<T, U: JobResult>: Obse
self.countryCode = countryCode
self.documentType = documentType
self.captureBothSides = captureBothSides
self.skipApiSubmission = skipApiSubmission
self.selfieFile = selfieFile
self.jobType = jobType
self.extraPartnerParams = extraPartnerParams
Expand Down Expand Up @@ -177,6 +180,10 @@ internal class IOrchestratedDocumentVerificationViewModel<T, U: JobResult>: Obse
selfie: selfieFile,
livenessImages: livenessFiles ?? []
)
if skipApiSubmission {
DispatchQueue.main.async { self.step = .processing(.success) }
return
}
let authRequest = AuthenticationRequest(
jobType: jobType,
enrollment: false,
Expand All @@ -197,7 +204,7 @@ internal class IOrchestratedDocumentVerificationViewModel<T, U: JobResult>: Obse
let authResponse = try await SmileID.api.authenticate(request: authRequest)
let prepUploadRequest = PrepUploadRequest(
partnerParams: authResponse.partnerParams.copy(extras: self.extraPartnerParams),
allowNewEnroll: String(allowNewEnroll), // TODO: - Fix when Michael changes this to boolean
allowNewEnroll: String(allowNewEnroll), // TODO: - Fix when Michael changes this to boolean
metadata: localMetadata.metadata.items,
timestamp: authResponse.timestamp,
signature: authResponse.signature
Expand Down Expand Up @@ -321,14 +328,14 @@ extension IOrchestratedDocumentVerificationViewModel: SmartSelfieResultDelegate
}

// swiftlint:disable opening_brace
internal class OrchestratedDocumentVerificationViewModel:
class OrchestratedDocumentVerificationViewModel:
IOrchestratedDocumentVerificationViewModel<DocumentVerificationResultDelegate, DocumentVerificationJobResult>
{
override func onFinished(delegate: DocumentVerificationResultDelegate) {
if let savedFiles,
let selfiePath = getRelativePath(from: selfieFile),
let documentFrontPath = getRelativePath(from: savedFiles.documentFront),
let documentBackPath = getRelativePath(from: savedFiles.documentBack)
let selfiePath = getRelativePath(from: selfieFile),
let documentFrontPath = getRelativePath(from: savedFiles.documentFront),
let documentBackPath = getRelativePath(from: savedFiles.documentBack)
{
delegate.didSucceed(
selfie: selfiePath,
Expand All @@ -347,16 +354,16 @@ internal class OrchestratedDocumentVerificationViewModel:
}

// swiftlint:disable opening_brace
internal class OrchestratedEnhancedDocumentVerificationViewModel:
class OrchestratedEnhancedDocumentVerificationViewModel:
IOrchestratedDocumentVerificationViewModel<
EnhancedDocumentVerificationResultDelegate, EnhancedDocumentVerificationJobResult
>
{
override func onFinished(delegate: EnhancedDocumentVerificationResultDelegate) {
if let savedFiles,
let selfiePath = getRelativePath(from: selfieFile),
let documentFrontPath = getRelativePath(from: savedFiles.documentFront),
let documentBackPath = getRelativePath(from: savedFiles.documentBack)
let selfiePath = getRelativePath(from: selfieFile),
let documentFrontPath = getRelativePath(from: savedFiles.documentFront),
let documentBackPath = getRelativePath(from: savedFiles.documentBack)
{
delegate.didSucceed(
selfie: selfiePath,
Expand Down
Loading
Loading