Page MenuHomePhabricator

D10797.id36246.diff
No OneTemporary

D10797.id36246.diff

diff --git a/services/identity/src/database.rs b/services/identity/src/database.rs
--- a/services/identity/src/database.rs
+++ b/services/identity/src/database.rs
@@ -57,7 +57,7 @@
pub use grpc_clients::identity::DeviceType;
mod device_list;
-pub use device_list::{DeviceListRow, DeviceRow};
+pub use device_list::{DeviceListRow, DeviceListUpdate, DeviceRow};
use self::device_list::Prekey;
diff --git a/services/identity/src/database/device_list.rs b/services/identity/src/database/device_list.rs
--- a/services/identity/src/database/device_list.rs
+++ b/services/identity/src/database/device_list.rs
@@ -64,6 +64,13 @@
pub prekey_signature: String,
}
+/// A struct representing device list update request
+/// payload; issued by the primary device
+#[derive(serde::Deserialize)]
+pub struct DeviceListUpdate {
+ devices: Vec<String>,
+}
+
impl DeviceRow {
pub fn from_device_key_upload(
user_id: impl Into<String>,
diff --git a/services/identity/src/grpc_services/authenticated.rs b/services/identity/src/grpc_services/authenticated.rs
--- a/services/identity/src/grpc_services/authenticated.rs
+++ b/services/identity/src/grpc_services/authenticated.rs
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use crate::config::CONFIG;
-use crate::database::DeviceListRow;
+use crate::database::{DeviceListRow, DeviceListUpdate};
use crate::ddb_utils::Identifier;
use crate::{
client_service::{
@@ -26,6 +26,7 @@
InboundKeyInfo, InboundKeysForUserRequest, InboundKeysForUserResponse,
KeyserverKeysResponse, OutboundKeyInfo, OutboundKeysForUserRequest,
OutboundKeysForUserResponse, RefreshUserPrekeysRequest,
+ UpdateDeviceListRequest, UpdateDeviceListResponse,
UpdateUserPasswordFinishRequest, UpdateUserPasswordStartRequest,
UpdateUserPasswordStartResponse, UploadOneTimeKeysRequest,
};
@@ -412,6 +413,13 @@
device_list_updates: stringified_updates,
}))
}
+
+ async fn update_device_list_for_user(
+ &self,
+ _request: tonic::Request<UpdateDeviceListRequest>,
+ ) -> Result<Response<UpdateDeviceListResponse>, tonic::Status> {
+ Err(tonic::Status::unimplemented("not implemented"))
+ }
}
// raw device list that can be serialized to JSON (and then signed in the future)
@@ -451,6 +459,31 @@
}
}
+impl TryFrom<UpdateDeviceListRequest> for DeviceListUpdate {
+ type Error = tonic::Status;
+ fn try_from(request: UpdateDeviceListRequest) -> Result<Self, Self::Error> {
+ serde_json::from_str(&request.new_device_list).map_err(|err| {
+ error!("Failed to deserialize device list update: {}", err);
+ tonic::Status::failed_precondition("unexpected error")
+ })
+ }
+}
+
+impl TryFrom<SignedDeviceList> for UpdateDeviceListResponse {
+ type Error = tonic::Status;
+ fn try_from(signed_list: SignedDeviceList) -> Result<Self, Self::Error> {
+ let stringified_response_payload = serde_json::to_string(&signed_list)
+ .map_err(|err| {
+ error!("Failed to serialize device list response: {}", err);
+ tonic::Status::failed_precondition("unexpected error")
+ })?;
+ let response = UpdateDeviceListResponse {
+ signed_device_list: stringified_response_payload,
+ };
+ Ok(response)
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/shared/protos/identity_auth.proto b/shared/protos/identity_auth.proto
--- a/shared/protos/identity_auth.proto
+++ b/shared/protos/identity_auth.proto
@@ -57,6 +57,9 @@
// Returns device list history
rpc GetDeviceListForUser(GetDeviceListRequest) returns
(GetDeviceListResponse) {}
+
+ rpc UpdateDeviceListForUser(UpdateDeviceListRequest) returns
+ (UpdateDeviceListResponse) {}
}
// Helper types
@@ -197,3 +200,24 @@
// }
repeated string device_list_updates = 1;
}
+
+// UpdateDeviceListForUser
+
+message UpdateDeviceListRequest {
+ // A stringified JSON object of the following format:
+ // {
+ // "devices": [<device_id: string>, ...]
+ // }
+ string new_device_list = 1;
+}
+
+message UpdateDeviceListResponse {
+ // A stringified JSON object of the following format:
+ // {
+ // "rawDeviceList": JSON.stringify({
+ // "devices": [<device_id: string>, ...]
+ // "timestamp": <UTC timestamp in milliseconds: int>,
+ // })
+ // }
+ string signed_device_list = 1;
+}
diff --git a/web/protobufs/identity-auth-client.cjs b/web/protobufs/identity-auth-client.cjs
--- a/web/protobufs/identity-auth-client.cjs
+++ b/web/protobufs/identity-auth-client.cjs
@@ -749,5 +749,66 @@
};
+/**
+ * @const
+ * @type {!grpc.web.MethodDescriptor<
+ * !proto.identity.auth.UpdateDeviceListRequest,
+ * !proto.identity.auth.UpdateDeviceListResponse>}
+ */
+const methodDescriptor_IdentityClientService_UpdateDeviceListForUser = new grpc.web.MethodDescriptor(
+ '/identity.auth.IdentityClientService/UpdateDeviceListForUser',
+ grpc.web.MethodType.UNARY,
+ proto.identity.auth.UpdateDeviceListRequest,
+ proto.identity.auth.UpdateDeviceListResponse,
+ /**
+ * @param {!proto.identity.auth.UpdateDeviceListRequest} request
+ * @return {!Uint8Array}
+ */
+ function(request) {
+ return request.serializeBinary();
+ },
+ proto.identity.auth.UpdateDeviceListResponse.deserializeBinary
+);
+
+
+/**
+ * @param {!proto.identity.auth.UpdateDeviceListRequest} request The
+ * request proto
+ * @param {?Object<string, string>} metadata User defined
+ * call metadata
+ * @param {function(?grpc.web.RpcError, ?proto.identity.auth.UpdateDeviceListResponse)}
+ * callback The callback function(error, response)
+ * @return {!grpc.web.ClientReadableStream<!proto.identity.auth.UpdateDeviceListResponse>|undefined}
+ * The XHR Node Readable Stream
+ */
+proto.identity.auth.IdentityClientServiceClient.prototype.updateDeviceListForUser =
+ function(request, metadata, callback) {
+ return this.client_.rpcCall(this.hostname_ +
+ '/identity.auth.IdentityClientService/UpdateDeviceListForUser',
+ request,
+ metadata || {},
+ methodDescriptor_IdentityClientService_UpdateDeviceListForUser,
+ callback);
+};
+
+
+/**
+ * @param {!proto.identity.auth.UpdateDeviceListRequest} request The
+ * request proto
+ * @param {?Object<string, string>=} metadata User defined
+ * call metadata
+ * @return {!Promise<!proto.identity.auth.UpdateDeviceListResponse>}
+ * Promise that resolves to the response
+ */
+proto.identity.auth.IdentityClientServicePromiseClient.prototype.updateDeviceListForUser =
+ function(request, metadata) {
+ return this.client_.unaryCall(this.hostname_ +
+ '/identity.auth.IdentityClientService/UpdateDeviceListForUser',
+ request,
+ metadata || {},
+ methodDescriptor_IdentityClientService_UpdateDeviceListForUser);
+};
+
+
module.exports = proto.identity.auth;
diff --git a/web/protobufs/identity-auth-client.cjs.flow b/web/protobufs/identity-auth-client.cjs.flow
--- a/web/protobufs/identity-auth-client.cjs.flow
+++ b/web/protobufs/identity-auth-client.cjs.flow
@@ -87,6 +87,13 @@
callback: (err: grpcWeb.RpcError,
response: identityAuthStructs.GetDeviceListResponse) => void
): grpcWeb.ClientReadableStream<identityAuthStructs.GetDeviceListResponse>;
+
+ updateDeviceListForUser(
+ request: identityAuthStructs.UpdateDeviceListRequest,
+ metadata: grpcWeb.Metadata | void,
+ callback: (err: grpcWeb.RpcError,
+ response: identityAuthStructs.UpdateDeviceListResponse) => void
+ ): grpcWeb.ClientReadableStream<identityAuthStructs.UpdateDeviceListResponse>;
}
declare export class IdentityClientServicePromiseClient {
@@ -148,4 +155,9 @@
request: identityAuthStructs.GetDeviceListRequest,
metadata?: grpcWeb.Metadata
): Promise<identityAuthStructs.GetDeviceListResponse>;
+
+ updateDeviceListForUser(
+ request: identityAuthStructs.UpdateDeviceListRequest,
+ metadata?: grpcWeb.Metadata
+ ): Promise<identityAuthStructs.UpdateDeviceListResponse>;
}
diff --git a/web/protobufs/identity-auth-structs.cjs b/web/protobufs/identity-auth-structs.cjs
--- a/web/protobufs/identity-auth-structs.cjs
+++ b/web/protobufs/identity-auth-structs.cjs
@@ -40,6 +40,8 @@
goog.exportSymbol('proto.identity.auth.OutboundKeysForUserRequest', null, global);
goog.exportSymbol('proto.identity.auth.OutboundKeysForUserResponse', null, global);
goog.exportSymbol('proto.identity.auth.RefreshUserPrekeysRequest', null, global);
+goog.exportSymbol('proto.identity.auth.UpdateDeviceListRequest', null, global);
+goog.exportSymbol('proto.identity.auth.UpdateDeviceListResponse', null, global);
goog.exportSymbol('proto.identity.auth.UpdateUserPasswordFinishRequest', null, global);
goog.exportSymbol('proto.identity.auth.UpdateUserPasswordStartRequest', null, global);
goog.exportSymbol('proto.identity.auth.UpdateUserPasswordStartResponse', null, global);
@@ -422,6 +424,48 @@
*/
proto.identity.auth.GetDeviceListResponse.displayName = 'proto.identity.auth.GetDeviceListResponse';
}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.identity.auth.UpdateDeviceListRequest = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.identity.auth.UpdateDeviceListRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ /**
+ * @public
+ * @override
+ */
+ proto.identity.auth.UpdateDeviceListRequest.displayName = 'proto.identity.auth.UpdateDeviceListRequest';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.identity.auth.UpdateDeviceListResponse = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.identity.auth.UpdateDeviceListResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ /**
+ * @public
+ * @override
+ */
+ proto.identity.auth.UpdateDeviceListResponse.displayName = 'proto.identity.auth.UpdateDeviceListResponse';
+}
@@ -3853,4 +3897,264 @@
};
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ * JSPB instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.identity.auth.UpdateDeviceListRequest.prototype.toObject = function(opt_includeInstance) {
+ return proto.identity.auth.UpdateDeviceListRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ * the JSPB instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.identity.auth.UpdateDeviceListRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.identity.auth.UpdateDeviceListRequest.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ newDeviceList: jspb.Message.getFieldWithDefault(msg, 1, "")
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg;
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.identity.auth.UpdateDeviceListRequest}
+ */
+proto.identity.auth.UpdateDeviceListRequest.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.identity.auth.UpdateDeviceListRequest;
+ return proto.identity.auth.UpdateDeviceListRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.identity.auth.UpdateDeviceListRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.identity.auth.UpdateDeviceListRequest}
+ */
+proto.identity.auth.UpdateDeviceListRequest.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {string} */ (reader.readString());
+ msg.setNewDeviceList(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.identity.auth.UpdateDeviceListRequest.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ proto.identity.auth.UpdateDeviceListRequest.serializeBinaryToWriter(this, writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.identity.auth.UpdateDeviceListRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.identity.auth.UpdateDeviceListRequest.serializeBinaryToWriter = function(message, writer) {
+ var f = undefined;
+ f = message.getNewDeviceList();
+ if (f.length > 0) {
+ writer.writeString(
+ 1,
+ f
+ );
+ }
+};
+
+
+/**
+ * optional string new_device_list = 1;
+ * @return {string}
+ */
+proto.identity.auth.UpdateDeviceListRequest.prototype.getNewDeviceList = function() {
+ return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.identity.auth.UpdateDeviceListRequest} returns this
+ */
+proto.identity.auth.UpdateDeviceListRequest.prototype.setNewDeviceList = function(value) {
+ return jspb.Message.setProto3StringField(this, 1, value);
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ * JSPB instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.identity.auth.UpdateDeviceListResponse.prototype.toObject = function(opt_includeInstance) {
+ return proto.identity.auth.UpdateDeviceListResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ * the JSPB instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.identity.auth.UpdateDeviceListResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.identity.auth.UpdateDeviceListResponse.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ signedDeviceList: jspb.Message.getFieldWithDefault(msg, 1, "")
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg;
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.identity.auth.UpdateDeviceListResponse}
+ */
+proto.identity.auth.UpdateDeviceListResponse.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.identity.auth.UpdateDeviceListResponse;
+ return proto.identity.auth.UpdateDeviceListResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.identity.auth.UpdateDeviceListResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.identity.auth.UpdateDeviceListResponse}
+ */
+proto.identity.auth.UpdateDeviceListResponse.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {string} */ (reader.readString());
+ msg.setSignedDeviceList(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.identity.auth.UpdateDeviceListResponse.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ proto.identity.auth.UpdateDeviceListResponse.serializeBinaryToWriter(this, writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.identity.auth.UpdateDeviceListResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.identity.auth.UpdateDeviceListResponse.serializeBinaryToWriter = function(message, writer) {
+ var f = undefined;
+ f = message.getSignedDeviceList();
+ if (f.length > 0) {
+ writer.writeString(
+ 1,
+ f
+ );
+ }
+};
+
+
+/**
+ * optional string signed_device_list = 1;
+ * @return {string}
+ */
+proto.identity.auth.UpdateDeviceListResponse.prototype.getSignedDeviceList = function() {
+ return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.identity.auth.UpdateDeviceListResponse} returns this
+ */
+proto.identity.auth.UpdateDeviceListResponse.prototype.setSignedDeviceList = function(value) {
+ return jspb.Message.setProto3StringField(this, 1, value);
+};
+
+
goog.object.extend(exports, proto.identity.auth);
diff --git a/web/protobufs/identity-auth-structs.cjs.flow b/web/protobufs/identity-auth-structs.cjs.flow
--- a/web/protobufs/identity-auth-structs.cjs.flow
+++ b/web/protobufs/identity-auth-structs.cjs.flow
@@ -418,3 +418,35 @@
export type GetDeviceListResponseObject = {
deviceListUpdatesList: Array<string>,
}
+
+declare export class UpdateDeviceListRequest extends Message {
+ getNewDeviceList(): string;
+ setNewDeviceList(value: string): UpdateDeviceListRequest;
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): UpdateDeviceListRequestObject;
+ static toObject(includeInstance: boolean, msg: UpdateDeviceListRequest): UpdateDeviceListRequestObject;
+ static serializeBinaryToWriter(message: UpdateDeviceListRequest, writer: BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): UpdateDeviceListRequest;
+ static deserializeBinaryFromReader(message: UpdateDeviceListRequest, reader: BinaryReader): UpdateDeviceListRequest;
+}
+
+export type UpdateDeviceListRequestObject = {
+ newDeviceList: string,
+}
+
+declare export class UpdateDeviceListResponse extends Message {
+ getSignedDeviceList(): string;
+ setSignedDeviceList(value: string): UpdateDeviceListResponse;
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): UpdateDeviceListResponseObject;
+ static toObject(includeInstance: boolean, msg: UpdateDeviceListResponse): UpdateDeviceListResponseObject;
+ static serializeBinaryToWriter(message: UpdateDeviceListResponse, writer: BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): UpdateDeviceListResponse;
+ static deserializeBinaryFromReader(message: UpdateDeviceListResponse, reader: BinaryReader): UpdateDeviceListResponse;
+}
+
+export type UpdateDeviceListResponseObject = {
+ signedDeviceList: string,
+}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 10:21 AM (17 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2522250
Default Alt Text
D10797.id36246.diff (20 KB)

Event Timeline