diff --git a/src/device.c b/src/device.c
index 537bd67..9127896 100644
--- a/src/device.c
+++ b/src/device.c
@@ -574,6 +574,10 @@ get_permissions_for_invocation (GDBusMethodInvocation *invocation)
required_perms |= FPRINT_DEVICE_PERMISSION_VERIFY;
required_perms |= FPRINT_DEVICE_PERMISSION_ENROLL;
}
+ else if (g_str_equal (method_name, "DeleteEnrolledFinger"))
+ {
+ required_perms |= FPRINT_DEVICE_PERMISSION_ENROLL;
+ }
else if (g_str_equal (method_name, "DeleteEnrolledFingers"))
{
required_perms |= FPRINT_DEVICE_PERMISSION_ENROLL;
@@ -1838,12 +1842,18 @@ fprint_device_list_enrolled_fingers (FprintDBusDevice *dbus_dev,
}
static void
-delete_enrolled_fingers (FprintDevice *rdev, const char *user)
+delete_enrolled_fingers (FprintDevice *rdev,
+ const char *user,
+ FpFinger finger)
{
FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
guint i;
- g_debug ("Deleting enrolled fingers for user %s", user);
+ if (finger != FP_FINGER_UNKNOWN)
+ g_debug ("Deleting enrolled finger %s for user %s",
+ fp_finger_to_name (finger), user);
+ else
+ g_debug ("Deleting enrolled fingers for user %s", user);
/* First try deleting the print from the device, we don't consider it
* fatal if this does not work. */
@@ -1867,6 +1877,9 @@ delete_enrolled_fingers (FprintDevice *rdev, const char *user)
{
g_autoptr(GError) error = NULL;
+ if (finger != FP_FINGER_UNKNOWN && fp_print_get_finger (print) != finger)
+ continue;
+
if (!fp_device_delete_print_sync (priv->dev, print, NULL, &error))
{
g_warning ("Error deleting print from device: %s", error->message);
@@ -1876,8 +1889,15 @@ delete_enrolled_fingers (FprintDevice *rdev, const char *user)
}
}
- for (i = FP_FINGER_FIRST; i <= FP_FINGER_LAST; i++)
- store.print_data_delete (priv->dev, i, user);
+ if (finger != FP_FINGER_UNKNOWN)
+ {
+ store.print_data_delete (priv->dev, finger, user);
+ }
+ else
+ {
+ for (i = FP_FINGER_FIRST; i <= FP_FINGER_LAST; i++)
+ store.print_data_delete (priv->dev, i, user);
+ }
}
#ifdef __linux__
@@ -1982,7 +2002,7 @@ fprint_device_delete_enrolled_fingers (FprintDBusDevice *dbus_dev,
g_assert (user);
g_assert (g_str_equal (username, "") || g_str_equal (user, username));
- delete_enrolled_fingers (rdev, user);
+ delete_enrolled_fingers (rdev, user, FP_FINGER_UNKNOWN);
if (!opened && fp_device_has_storage (priv->dev))
fp_device_close_sync (priv->dev, NULL, NULL);
@@ -2020,13 +2040,59 @@ fprint_device_delete_enrolled_fingers2 (FprintDBusDevice *dbus_dev,
session = session_data_get (priv);
- delete_enrolled_fingers (rdev, session->username);
+ delete_enrolled_fingers (rdev, session->username, FP_FINGER_UNKNOWN);
fprint_dbus_device_complete_delete_enrolled_fingers2 (dbus_dev,
invocation);
return TRUE;
}
+static gboolean
+fprint_device_delete_enrolled_finger (FprintDBusDevice *dbus_dev,
+ GDBusMethodInvocation *invocation,
+ const gchar *finger_name)
+{
+ FprintDevice *rdev = FPRINT_DEVICE (dbus_dev);
+ FprintDevicePrivate *priv = fprint_device_get_instance_private (rdev);
+ FpFinger finger = finger_name_to_fp_finger (finger_name);
+
+ g_autoptr(SessionData) session = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (!_fprint_device_check_claimed (rdev, invocation, &error))
+ {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ return TRUE;
+ }
+
+ if (finger == FP_FINGER_UNKNOWN)
+ {
+ g_dbus_method_invocation_return_error_literal (invocation,
+ FPRINT_ERROR,
+ FPRINT_ERROR_INVALID_FINGERNAME,
+ "Invalid finger name");
+ return TRUE;
+ }
+
+ if (!can_start_action (rdev, &error))
+ {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ return TRUE;
+ }
+
+ priv->current_action = ACTION_DELETE;
+
+ session = session_data_get (priv);
+
+ /* FIXME: Should we return an error if the requested finger is not enrolled?! */
+ delete_enrolled_fingers (rdev, session->username, finger);
+
+ priv->current_action = ACTION_NONE;
+
+ fprint_dbus_device_complete_delete_enrolled_finger (dbus_dev, invocation);
+ return TRUE;
+}
+
static gboolean
handle_unauthorized_access (FprintDevice *rdev,
GDBusMethodInvocation *invocation,
@@ -2104,6 +2170,7 @@ static void
fprint_device_dbus_skeleton_iface_init (FprintDBusDeviceIface *iface)
{
iface->handle_claim = fprint_device_claim;
+ iface->handle_delete_enrolled_finger = fprint_device_delete_enrolled_finger;
iface->handle_delete_enrolled_fingers = fprint_device_delete_enrolled_fingers;
iface->handle_delete_enrolled_fingers2 = fprint_device_delete_enrolled_fingers2;
iface->handle_enroll_start = fprint_device_enroll_start;
diff --git a/src/device.xml b/src/device.xml
index df2521f..1dd922f 100644
--- a/src/device.xml
+++ b/src/device.xml
@@ -247,7 +247,7 @@
No further prints can be enrolled on this device, Device.EnrollStop should now be called.
- Delete other prints from the device first to continue
+ Delete other prints from the device first to continue
(e.g. from other users). Note that old prints or prints from other operating systems may be deleted automatically
to resolve this error without any notification.
@@ -307,7 +307,8 @@
This call only exists for compatibility reasons, you should instead claim the device using
Device.Claim and then call
- DeleteEnrolledFingers2.
+ DeleteEnrolledFingers2 or
+ DeleteEnrolledFinger.
@@ -335,6 +336,31 @@
+
+
+
+ A string representing the finger to delete. See
+ Fingerprint names.
+ Note that "any" is not a valid finger name for this method.
+
+
+
+
+
+ Delete the enrolled fingerprint for the user currently claiming the device with Device.Claim.
+
+
+
+
+ if the caller lacks the appropriate PolicyKit authorization
+ if the device was not claimed
+ if the finger name passed is invalid
+
+
+
+
+
+
The username for whom to claim the device. See Usernames.
diff --git a/tests/fprintd.py b/tests/fprintd.py
index 16d8485..3e7e784 100755
--- a/tests/fprintd.py
+++ b/tests/fprintd.py
@@ -894,6 +894,13 @@ class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
with self.assertFprintError('PermissionDenied'):
self.device.DeleteEnrolledFingers2()
+ def test_unallowed_delete_single_with_verify_claim(self):
+ self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.verify'])
+ self.device.Claim('(s)', '')
+
+ with self.assertFprintError('PermissionDenied'):
+ self.device.DeleteEnrolledFingers('(s)', 'right-thumb')
+
def test_unallowed_verify_with_enroll_claim(self):
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
self.device.Claim('(s)', '')
@@ -948,6 +955,10 @@ class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
def test_unclaimed_delete_enrolled_fingers(self):
self.device.DeleteEnrolledFingers('(s)', 'testuser')
+ def test_unclaimed_delete_enrolled_finger(self):
+ with self.assertFprintError('ClaimDevice'):
+ self.device.DeleteEnrolledFinger('(s)', 'left-index-finger')
+
def test_unclaimed_delete_enrolled_fingers2(self):
with self.assertFprintError('ClaimDevice'):
self.device.DeleteEnrolledFingers2()
@@ -1107,10 +1118,22 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
raise(e)
super().tearDown()
- def test_wrong_finger_enroll_start(self):
+ def test_any_finger_enroll_start(self):
with self.assertFprintError('InvalidFingername'):
self.device.EnrollStart('(s)', 'any')
+ def test_wrong_finger_enroll_start(self):
+ with self.assertFprintError('InvalidFingername'):
+ self.device.EnrollStart('(s)', 'sixth-right-finger')
+
+ def test_any_finger_delete_print(self):
+ with self.assertFprintError('InvalidFingername'):
+ self.device.DeleteEnrolledFinger('(s)', 'any')
+
+ def test_wrong_finger_delete_print(self):
+ with self.assertFprintError('InvalidFingername'):
+ self.device.DeleteEnrolledFinger('(s)', 'sixth-left-finger')
+
def test_verify_with_no_enrolled_prints(self):
with self.assertFprintError('NoEnrolledPrints'):
self.device.VerifyStart('(s)', 'any')
@@ -1189,6 +1212,21 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser')))
self.assertTrue(os.path.exists(self.state_dir))
+ def test_enroll_delete_single(self):
+ self.enroll_image('whorl', finger='right-index-finger')
+ self.enroll_image('tented_arch', finger='left-index-finger')
+
+ self.assertTrue(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
+ self.assertTrue(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/2')))
+
+ self.device.DeleteEnrolledFinger('(s)', 'right-index-finger')
+ self.assertTrue(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/2')))
+ self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
+
+ self.device.DeleteEnrolledFinger('(s)', 'left-index-finger')
+ self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/2')))
+ self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
+
def test_enroll_invalid_storage_dir(self):
# Directory will not exist yet
os.makedirs(self.state_dir, mode=0o500)
@@ -1423,6 +1461,13 @@ class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
with self.assertFprintError('PermissionDenied'):
self.device.DeleteEnrolledFingers2()
+ def test_unallowed_delete_enrolled_finger(self):
+ self.enroll_image('whorl')
+
+ self._polkitd_obj.SetAllowed([''])
+ with self.assertFprintError('PermissionDenied'):
+ self.device.DeleteEnrolledFinger('(s)', 'left-little-finger')
+
def test_delete_enrolled_fingers_from_other_client(self):
with self.assertFprintError('AlreadyInUse'):
self.call_device_method_from_other_client('DeleteEnrolledFingers', ['testuser'])