Dbus identities (#1259)
* Dbus Identities and Trust * Update src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java * PR feedback updates * Documentation and consistent case sensitivity * doc for listIdentities and getIdentity
This commit is contained in:
		
							parent
							
								
									c62a1e829f
								
							
						
					
					
						commit
						a96c4938b1
					
				@ -416,6 +416,24 @@ Only works if sent from a secondary device.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Exceptions: Failure
 | 
					Exceptions: Failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== Identity related methods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					listIdentities() -> identities<a(oss)>::
 | 
				
			||||||
 | 
					* identities : Array of structs (objectPath, id, name)
 | 
				
			||||||
 | 
					** objectPath : DBusPath representing the identity object path
 | 
				
			||||||
 | 
					** uuid : Internal uuid of the identity
 | 
				
			||||||
 | 
					** number : Phone number of the identity (or uuid if not known)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Lists all know identities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					getIdentity(Number<s>) -> identityPath<o>::
 | 
				
			||||||
 | 
					* Number : Phone number 
 | 
				
			||||||
 | 
					* identityPath : DBusPath object for the identity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gets the identity Dbus path for a given phone number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Exceptions: Failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=== Signal.Group interface
 | 
					=== Signal.Group interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The following methods listen to the group's object path, which can be obtained from the listGroups() method and is constructed as follows:
 | 
					The following methods listen to the group's object path, which can be obtained from the listGroups() method and is constructed as follows:
 | 
				
			||||||
@ -531,6 +549,42 @@ removeDevice() -> <>::
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Exceptions: Failure
 | 
					Exceptions: Failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Signal.Identity interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following methods listen to the Identities object path, which is constructed as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<ACCOUNT_PATH> + "/Identities/" + identity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					identity : Either the phone number of a contact with underscore (_) replacing plus (+) , or if not known its uuid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Identities have the following (case-sensitive) properties:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Number<s> (read-only) : Phone number of the contact
 | 
				
			||||||
 | 
					* Uuid<x> (read-only) : Internal uuid representing the contact
 | 
				
			||||||
 | 
					* Fingerprint<x> (read-only) : Byte array representing the fingerprint
 | 
				
			||||||
 | 
					* SafetyNumber<s> (read-only) : String representation of the safety number used to verify trust
 | 
				
			||||||
 | 
					* TrustLevel<s> (read-only) : Current trust level (UNSTRUSTED, TRUSTED_UNVERIFIED, TRUSTED_VERIFIED)
 | 
				
			||||||
 | 
					* AddedDate<x> (read-only) : Long representing the number of milliseconds since the Unix epoch
 | 
				
			||||||
 | 
					* ScannableSafetyNumber<x> (read-only) : Byte array representation of the safety number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To get a property, use (replacing `--session` with `--system` if needed):
 | 
				
			||||||
 | 
					`dbus-send --session --dest=org.asamk.Signal --print-reply $OBJECT_PATH org.freedesktop.DBus.Properties.Get string:org.asamk.Signal.Identity string:$PROPERTY_NAME`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To get all properties, use:
 | 
				
			||||||
 | 
					`dbus-send --session --dest=org.asamk.Signal --print-reply $OBJECT_PATH org.freedesktop.DBus.Properties.GetAll string:org.asamk.Signal.Identity`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trust() -> <>::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Establish trust with the given identity. TrustLevel will become TRUSTED_UNVERFIED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Exceptions: Failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trustVerified(SafetyNumber<s>) -> <>::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Establish trust with the given identity using their safety number. TrustLevel will become TRUSTED_VERIFIED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Exceptions: Failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=== Signal.Configuration interface
 | 
					=== Signal.Configuration interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The configuration's object path, which exists only for primary devices, is constructed as follows:
 | 
					The configuration's object path, which exists only for primary devices, is constructed as follows:
 | 
				
			||||||
 | 
				
			|||||||
@ -138,6 +138,10 @@ public interface Signal extends DBusInterface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    DBusPath getDevice(long deviceId);
 | 
					    DBusPath getDevice(long deviceId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public DBusPath getIdentity(String number);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public List<StructIdentity> listIdentities();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    List<StructDevice> listDevices() throws Error.Failure;
 | 
					    List<StructDevice> listDevices() throws Error.Failure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DBusPath getThisDevice();
 | 
					    DBusPath getThisDevice();
 | 
				
			||||||
@ -551,6 +555,50 @@ public interface Signal extends DBusInterface {
 | 
				
			|||||||
        void enableLink(boolean requiresApproval) throws Error.Failure;
 | 
					        void enableLink(boolean requiresApproval) throws Error.Failure;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class StructIdentity extends Struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Position(0)
 | 
				
			||||||
 | 
					        DBusPath objectPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Position(1)
 | 
				
			||||||
 | 
					        String uuid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Position(2)
 | 
				
			||||||
 | 
					        String name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public StructIdentity(final DBusPath objectPath, final String uuid, final String name) {
 | 
				
			||||||
 | 
					            this.objectPath = objectPath;
 | 
				
			||||||
 | 
					            this.uuid = uuid;
 | 
				
			||||||
 | 
					            this.name = name;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public DBusPath getObjectPath() {
 | 
				
			||||||
 | 
					            return objectPath;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public String getUuid() {
 | 
				
			||||||
 | 
					            return uuid;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public String getName() {
 | 
				
			||||||
 | 
					            return name;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @DBusProperty(name = "Number", type = String.class, access = DBusProperty.Access.READ)
 | 
				
			||||||
 | 
					    @DBusProperty(name = "Uuid", type = String.class, access = DBusProperty.Access.READ)
 | 
				
			||||||
 | 
					    @DBusProperty(name = "Fingerprint", type = Byte[].class, access = DBusProperty.Access.READ)
 | 
				
			||||||
 | 
					    @DBusProperty(name = "SafetyNumber", type = String.class, access = DBusProperty.Access.READ)
 | 
				
			||||||
 | 
					    @DBusProperty(name = "TrustLevel", type = String.class, access = DBusProperty.Access.READ)
 | 
				
			||||||
 | 
					    @DBusProperty(name = "AddedDate", type = Integer.class, access = DBusProperty.Access.READ)
 | 
				
			||||||
 | 
					    @DBusProperty(name = "ScannableSafetyNumber", type = Byte[].class, access = DBusProperty.Access.READ)
 | 
				
			||||||
 | 
					    interface Identity extends DBusInterface, Properties {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void trust() throws Error.Failure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void trustVerified(String safetyNumber) throws Error.Failure;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    interface Error {
 | 
					    interface Error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class AttachmentInvalid extends DBusExecutionException {
 | 
					        class AttachmentInvalid extends DBusExecutionException {
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@ import org.asamk.signal.manager.api.UnregisteredRecipientException;
 | 
				
			|||||||
import org.asamk.signal.manager.api.UpdateGroup;
 | 
					import org.asamk.signal.manager.api.UpdateGroup;
 | 
				
			||||||
import org.asamk.signal.manager.api.UpdateProfile;
 | 
					import org.asamk.signal.manager.api.UpdateProfile;
 | 
				
			||||||
import org.asamk.signal.manager.api.UserStatus;
 | 
					import org.asamk.signal.manager.api.UserStatus;
 | 
				
			||||||
 | 
					import org.asamk.signal.manager.api.IdentityVerificationCode;
 | 
				
			||||||
import org.asamk.signal.util.SendMessageResultUtils;
 | 
					import org.asamk.signal.util.SendMessageResultUtils;
 | 
				
			||||||
import org.freedesktop.dbus.DBusPath;
 | 
					import org.freedesktop.dbus.DBusPath;
 | 
				
			||||||
import org.freedesktop.dbus.connections.impl.DBusConnection;
 | 
					import org.freedesktop.dbus.connections.impl.DBusConnection;
 | 
				
			||||||
@ -55,6 +56,7 @@ import java.util.Objects;
 | 
				
			|||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					import java.util.UUID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.asamk.signal.dbus.DbusUtils.makeValidObjectPathElement;
 | 
					import static org.asamk.signal.dbus.DbusUtils.makeValidObjectPathElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -68,6 +70,7 @@ public class DbusSignalImpl implements Signal {
 | 
				
			|||||||
    private DBusPath thisDevice;
 | 
					    private DBusPath thisDevice;
 | 
				
			||||||
    private final List<StructDevice> devices = new ArrayList<>();
 | 
					    private final List<StructDevice> devices = new ArrayList<>();
 | 
				
			||||||
    private final List<StructGroup> groups = new ArrayList<>();
 | 
					    private final List<StructGroup> groups = new ArrayList<>();
 | 
				
			||||||
 | 
					    private final List<StructIdentity> identities = new ArrayList<>();
 | 
				
			||||||
    private DbusReceiveMessageHandler dbusMessageHandler;
 | 
					    private DbusReceiveMessageHandler dbusMessageHandler;
 | 
				
			||||||
    private int subscriberCount;
 | 
					    private int subscriberCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -100,6 +103,7 @@ public class DbusSignalImpl implements Signal {
 | 
				
			|||||||
        updateDevices();
 | 
					        updateDevices();
 | 
				
			||||||
        updateGroups();
 | 
					        updateGroups();
 | 
				
			||||||
        updateConfiguration();
 | 
					        updateConfiguration();
 | 
				
			||||||
 | 
					        updateIdentities();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void close() {
 | 
					    public void close() {
 | 
				
			||||||
@ -114,6 +118,7 @@ public class DbusSignalImpl implements Signal {
 | 
				
			|||||||
        unExportDevices();
 | 
					        unExportDevices();
 | 
				
			||||||
        unExportGroups();
 | 
					        unExportGroups();
 | 
				
			||||||
        unExportConfiguration();
 | 
					        unExportConfiguration();
 | 
				
			||||||
 | 
					        unExportIdentities();
 | 
				
			||||||
        connection.unExportObject(this.objectPath);
 | 
					        connection.unExportObject(this.objectPath);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1029,6 +1034,109 @@ public class DbusSignalImpl implements Signal {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void updateIdentities() {
 | 
				
			||||||
 | 
					        List<org.asamk.signal.manager.api.Identity> identities;
 | 
				
			||||||
 | 
					        identities = m.getIdentities();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        unExportIdentities();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        identities.forEach(i -> {
 | 
				
			||||||
 | 
					            final var object = new DbusSignalIdentityImpl(i);
 | 
				
			||||||
 | 
					            exportObject(object);
 | 
				
			||||||
 | 
					            this.identities.add(new StructIdentity(new DBusPath(object.getObjectPath()),
 | 
				
			||||||
 | 
					                emptyIfNull(i.recipient().getIdentifier()),
 | 
				
			||||||
 | 
					                i.recipient().getLegacyIdentifier()));
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static String getIdentityObjectPath(String basePath, String id) {
 | 
				
			||||||
 | 
					        return basePath + "/Identities/" + makeValidObjectPathElement(id);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void unExportIdentities() {
 | 
				
			||||||
 | 
					        this.identities.stream().map(StructIdentity::getObjectPath).map(DBusPath::getPath).forEach(connection::unExportObject);
 | 
				
			||||||
 | 
					        this.identities.clear();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public DBusPath getIdentity(String number) throws Error.Failure {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final var found = identities.stream()
 | 
				
			||||||
 | 
					                            .filter(identity -> identity.getName().equals(number))
 | 
				
			||||||
 | 
					                            .findFirst();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (found.isEmpty()) {
 | 
				
			||||||
 | 
					            throw new Error.Failure("Identity for " + number + " unkown");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return found.get().getObjectPath();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public List<StructIdentity> listIdentities() {
 | 
				
			||||||
 | 
					        updateIdentities();
 | 
				
			||||||
 | 
					        return this.identities;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class DbusSignalIdentityImpl extends DbusProperties implements Signal.Identity {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private final org.asamk.signal.manager.api.Identity identity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public DbusSignalIdentityImpl(final org.asamk.signal.manager.api.Identity identity) {
 | 
				
			||||||
 | 
					            this.identity=identity;
 | 
				
			||||||
 | 
					            super.addPropertiesHandler(new DbusInterfacePropertiesHandler("org.asamk.Signal.Identity",
 | 
				
			||||||
 | 
					                    List.of(new DbusProperty<>("Number", () -> identity.recipient().number().orElse("")),
 | 
				
			||||||
 | 
					                            new DbusProperty<>("Uuid", () -> identity.recipient().uuid().map(UUID::toString).orElse("")),
 | 
				
			||||||
 | 
					                            new DbusProperty<>("Fingerprint", () -> identity.getFingerprint()),
 | 
				
			||||||
 | 
					                            new DbusProperty<>("SafetyNumber", identity::safetyNumber),
 | 
				
			||||||
 | 
					                            new DbusProperty<>("ScannableSafetyNumber", identity::scannableSafetyNumber),
 | 
				
			||||||
 | 
					                            new DbusProperty<>("TrustLevel", identity::trustLevel),
 | 
				
			||||||
 | 
					                            new DbusProperty<>("AddedDate", identity::dateAddedTimestamp)
 | 
				
			||||||
 | 
					                            )));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public String getObjectPath() {
 | 
				
			||||||
 | 
					            return getIdentityObjectPath(objectPath, identity.recipient().getLegacyIdentifier());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void trust() throws Error.Failure  {
 | 
				
			||||||
 | 
					            var recipient=RecipientIdentifier.Single.fromAddress(identity.recipient());
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                m.trustIdentityAllKeys(recipient);
 | 
				
			||||||
 | 
					            } catch (UnregisteredRecipientException e) {
 | 
				
			||||||
 | 
					                throw new Error.Failure("The user " + e.getSender().getIdentifier() + " is not registered.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void trustVerified(String safetyNumber) throws Error.Failure {
 | 
				
			||||||
 | 
					             var recipient = RecipientIdentifier.Single.fromAddress(identity.recipient());
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					            if (safetyNumber == null) {
 | 
				
			||||||
 | 
					                throw new Error.Failure(
 | 
				
			||||||
 | 
					                    "You need to specify a fingerprint/safety number");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            final IdentityVerificationCode verificationCode;
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                verificationCode = IdentityVerificationCode.parse(safetyNumber);
 | 
				
			||||||
 | 
					            } catch (Exception e) {
 | 
				
			||||||
 | 
					                throw new Error.Failure(
 | 
				
			||||||
 | 
					                        "Safety number has invalid format, either specify the old hex fingerprint or the new safety number");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                final var res = m.trustIdentityVerified(recipient, verificationCode);
 | 
				
			||||||
 | 
					                if (!res) {
 | 
				
			||||||
 | 
					                    throw new Error.Failure(
 | 
				
			||||||
 | 
					                            "Failed to set the trust for this number, make sure the number and the fingerprint/safety number are correct.");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } catch (UnregisteredRecipientException e) {
 | 
				
			||||||
 | 
					                throw new Error.Failure("The user " + e.getSender().getIdentifier() + " is not registered.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class DbusSignalDeviceImpl extends DbusProperties implements Signal.Device {
 | 
					    public class DbusSignalDeviceImpl extends DbusProperties implements Signal.Device {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private final org.asamk.signal.manager.api.Device device;
 | 
					        private final org.asamk.signal.manager.api.Device device;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user