did_common/
did_doc.rs

1use crate::lib::std::fmt;
2use crate::lib::std::str::FromStr;
3use crate::lib::std::vec::Vec;
4
5use crate::diddoc_parser;
6
7use json::JsonValue;
8
9#[derive(Clone, Debug, PartialEq)]
10pub enum PublicKeyType {
11	Rsa,
12	Ed25519,
13	EcdsaSecp256k1,
14}
15
16impl FromStr for PublicKeyType {
17	type Err = ParsePublicKeyTypeError;
18
19	fn from_str(s: &str) -> Result<Self, Self::Err> {
20		match s {
21			"RsaVerificationKey2018" => Ok(Self::Rsa),
22			"Ed25519VerificationKey2018" => Ok(Self::Ed25519),
23			"Secp256k1VerificationKey2018" => Ok(Self::EcdsaSecp256k1),
24			_ => Result::Err(ParsePublicKeyTypeError(())),
25		}
26	}
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct ParsePublicKeyTypeError(());
31
32impl fmt::Display for ParsePublicKeyTypeError {
33	fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
34		fmt.write_str("invalid DID public key type")
35	}
36}
37
38#[derive(Clone, Debug, PartialEq)]
39pub enum PublicKeyEncoded<'a> {
40	None,
41	Pem(&'a str),
42	Jwk(&'a str),
43	Hex(&'a str),
44	Base64(&'a str),
45	Base58(&'a str),
46	Multibase(&'a str),
47	EthrAddress(&'a str),
48	Unsupported,
49}
50
51const KEYPEM_PROP: &str = "publicKeyPem";
52const KEYJWK_PROP: &str = "publicKeyJwk";
53const KEYHEX_PROP: &str = "publicKeyHex";
54const KEYB58_PROP: &str = "publicKeyBase58";
55const KEYB64_PROP: &str = "publicKeyBase64";
56const KEYMUL_PROP: &str = "publicKeyMultibase";
57const KEYETH_PROP: &str = "ethereumAddress";
58pub const KEY_FORMATS: [&str; 7] = [
59	KEYPEM_PROP,
60	KEYJWK_PROP,
61	KEYHEX_PROP,
62	KEYB58_PROP,
63	KEYB64_PROP,
64	KEYMUL_PROP,
65	KEYETH_PROP,
66];
67
68impl<'a> From<(&'a str, &'a str)> for PublicKeyEncoded<'a> {
69	fn from(s: (&'a str, &'a str)) -> Self {
70		match s.0 {
71			KEYPEM_PROP => PublicKeyEncoded::Pem(s.1),
72			KEYJWK_PROP => PublicKeyEncoded::Jwk(s.1),
73			KEYHEX_PROP => PublicKeyEncoded::Hex(s.1),
74			KEYB58_PROP => PublicKeyEncoded::Base58(s.1),
75			KEYB64_PROP => PublicKeyEncoded::Base64(s.1),
76			KEYMUL_PROP => PublicKeyEncoded::Multibase(s.1),
77			KEYETH_PROP => PublicKeyEncoded::EthrAddress(s.1),
78			_ => PublicKeyEncoded::Unsupported,
79		}
80	}
81}
82
83#[derive(Clone, Debug, PartialEq)]
84pub struct PublicKey<'a> {
85	id: &'a str,
86	key_type: PublicKeyType,
87	controller: &'a str,
88	encoded_key: PublicKeyEncoded<'a>,
89}
90
91impl<'a> PublicKey<'a> {
92	pub fn id(&self) -> &'a str {
93		self.id
94	}
95
96	pub fn key_type(&self) -> &PublicKeyType {
97		&self.key_type
98	}
99
100	pub fn controller(&self) -> &'a str {
101		self.controller
102	}
103
104	pub fn encoded_key(&self) -> &PublicKeyEncoded {
105		&self.encoded_key
106	}
107}
108
109#[derive(Debug, PartialEq)]
110pub struct PublicKeyBuilder<'a> {
111	id: &'a str,
112	key_type: PublicKeyType,
113	controller: &'a str,
114	encoded_key: PublicKeyEncoded<'a>,
115}
116
117impl<'a> PublicKeyBuilder<'a> {
118	pub fn new(id: &'a str, key_type: PublicKeyType, controller: &'a str) -> Self {
119		PublicKeyBuilder {
120			id,
121			key_type,
122			controller,
123			encoded_key: PublicKeyEncoded::None,
124		}
125	}
126
127	pub fn with_encoded_key(mut self, encoded_key: PublicKeyEncoded<'a>) -> Self {
128		self.encoded_key = encoded_key;
129		self
130	}
131
132	pub fn build(self) -> PublicKey<'a> {
133		PublicKey {
134			id: self.id,
135			key_type: self.key_type,
136			controller: self.controller,
137			encoded_key: self.encoded_key,
138		}
139	}
140}
141
142#[derive(Clone, Debug, PartialEq)]
143pub enum VerificationMethod<'a> {
144	Reference(&'a str),
145	Embedded(PublicKey<'a>),
146}
147
148#[derive(Clone, Debug, PartialEq)]
149pub enum ServiceEndpoint<'a> {
150	Uri(&'a str),
151	Object(&'a str),
152}
153
154#[derive(Clone, Debug, PartialEq)]
155pub struct Service<'a> {
156	id: &'a str,
157	svc_type: &'a str,
158	endpoint: ServiceEndpoint<'a>,
159}
160
161impl<'a> Service<'a> {
162	pub fn new(id: &'a str, svc_type: &'a str, endpoint: ServiceEndpoint<'a>) -> Self {
163		Service {
164			id,
165			svc_type,
166			endpoint,
167		}
168	}
169
170	pub fn id(&self) -> &'a str {
171		self.id
172	}
173
174	pub fn svc_type(&self) -> &'a str {
175		self.svc_type
176	}
177
178	pub fn endpoint(&self) -> &ServiceEndpoint {
179		&self.endpoint
180	}
181}
182
183#[derive(Debug, Default, PartialEq)]
184pub struct DidDocument<'a> {
185	context: &'a str,
186	id: &'a str,
187	created: Option<&'a str>,
188	updated: Option<&'a str>,
189	authentication: Vec<VerificationMethod<'a>>,
190	pub_keys: Vec<PublicKey<'a>>,
191	service: Vec<Service<'a>>,
192}
193
194impl<'a> DidDocument<'a> {
195	pub fn context(&self) -> &'a str {
196		self.context
197	}
198
199	pub fn id(&self) -> &'a str {
200		self.id
201	}
202
203	pub fn created(&self) -> Option<&'a str> {
204		self.created
205	}
206
207	pub fn updated(&self) -> Option<&'a str> {
208		self.updated
209	}
210
211	pub fn authentication(&self) -> &[VerificationMethod<'a>] {
212		&self.authentication[..]
213	}
214
215	pub fn pub_keys(&self) -> &[PublicKey<'a>] {
216		&self.pub_keys[..]
217	}
218
219	pub fn service(&self) -> &[Service<'a>] {
220		&self.service[..]
221	}
222
223	pub fn parse(json: &'a JsonValue) -> Result<Self, &'a str> {
224		diddoc_parser::parse_did_doc(json)
225	}
226}
227
228#[derive(Debug, Default, PartialEq)]
229pub struct DidDocumentBuilder<'a> {
230	context: &'a str,
231	id: &'a str,
232	created: Option<&'a str>,
233	updated: Option<&'a str>,
234	authentication: Vec<VerificationMethod<'a>>,
235	pub_keys: Vec<PublicKey<'a>>,
236	service: Vec<Service<'a>>,
237}
238
239impl<'a> DidDocumentBuilder<'a> {
240	pub fn new(id: &'a str) -> Self {
241		DidDocumentBuilder {
242			context: diddoc_parser::GENERIC_DID_CTX,
243			id,
244			..Default::default()
245		}
246	}
247
248	pub fn created_on(mut self, created: &'a str) -> Self {
249		self.created = Some(created);
250		self
251	}
252
253	pub fn updated_on(mut self, updated: &'a str) -> Self {
254		self.updated = Some(updated);
255		self
256	}
257
258	pub fn with_authentication(mut self, authentication: Vec<VerificationMethod<'a>>) -> Self {
259		self.authentication = authentication;
260		self
261	}
262
263	pub fn with_pubkeys(mut self, pub_keys: Vec<PublicKey<'a>>) -> Self {
264		self.pub_keys = pub_keys;
265		self
266	}
267
268	pub fn with_services(mut self, services: Vec<Service<'a>>) -> Self {
269		self.service = services;
270		self
271	}
272
273	pub fn build(self) -> DidDocument<'a> {
274		DidDocument {
275			context: self.context,
276			id: self.id,
277			created: self.created,
278			updated: self.updated,
279			authentication: self.authentication,
280			pub_keys: self.pub_keys,
281			service: self.service,
282		}
283	}
284}
285
286#[cfg(test)]
287mod tests {
288	use super::diddoc_parser::GENERIC_DID_CTX;
289	use super::FromStr;
290	use super::{
291		DidDocument, DidDocumentBuilder, ParsePublicKeyTypeError, PublicKey, PublicKeyBuilder,
292		PublicKeyEncoded, PublicKeyType, Service, ServiceEndpoint, VerificationMethod,
293	};
294
295	const TEST_ENCODED_KEY: &str = "0x1234567890";
296
297	#[test]
298	fn public_key_type_fromstr_trait_for_rsa() {
299		assert_eq!(
300			PublicKeyType::from_str("RsaVerificationKey2018"),
301			Ok(PublicKeyType::Rsa)
302		);
303	}
304
305	#[test]
306	fn public_key_type_fromstr_trait_for_ed25519() {
307		assert_eq!(
308			PublicKeyType::from_str("Ed25519VerificationKey2018"),
309			Ok(PublicKeyType::Ed25519)
310		);
311	}
312
313	#[test]
314	fn public_key_type_fromstr_trait_for_ecdsasecp256k1() {
315		assert_eq!(
316			PublicKeyType::from_str("Secp256k1VerificationKey2018"),
317			Ok(PublicKeyType::EcdsaSecp256k1)
318		);
319	}
320
321	#[test]
322	fn public_key_type_fromstr_trait_for_invalid_case() {
323		assert_eq!(
324			PublicKeyType::from_str("rsaverificationkey2018"),
325			Err(ParsePublicKeyTypeError(()))
326		);
327		assert_eq!(
328			PublicKeyType::from_str("ed25519verificationkey2018"),
329			Err(ParsePublicKeyTypeError(()))
330		);
331		assert_eq!(
332			PublicKeyType::from_str("secp256k1verificationkey2018"),
333			Err(ParsePublicKeyTypeError(()))
334		);
335	}
336
337	#[test]
338	fn public_key_type_fromstr_trait_for_unsupported() {
339		assert_eq!(
340			PublicKeyType::from_str("azertyuiop"),
341			Err(ParsePublicKeyTypeError(()))
342		);
343	}
344
345	#[test]
346	fn public_key_type_error_display_trait() {
347		assert_eq!(
348			format!("{}", ParsePublicKeyTypeError(())),
349			"invalid DID public key type"
350		);
351	}
352
353	#[test]
354	fn public_key_encoded_from_trait_for_pem() {
355		assert_eq!(
356			PublicKeyEncoded::from((super::KEYPEM_PROP, TEST_ENCODED_KEY)),
357			PublicKeyEncoded::Pem(TEST_ENCODED_KEY)
358		)
359	}
360
361	#[test]
362	fn public_key_encoded_from_trait_for_jwk() {
363		assert_eq!(
364			PublicKeyEncoded::from((super::KEYJWK_PROP, TEST_ENCODED_KEY)),
365			PublicKeyEncoded::Jwk(TEST_ENCODED_KEY)
366		)
367	}
368
369	#[test]
370	fn public_key_encoded_from_trait_for_hex() {
371		assert_eq!(
372			PublicKeyEncoded::from((super::KEYHEX_PROP, TEST_ENCODED_KEY)),
373			PublicKeyEncoded::Hex(TEST_ENCODED_KEY)
374		)
375	}
376
377	#[test]
378	fn public_key_encoded_from_trait_for_base64() {
379		assert_eq!(
380			PublicKeyEncoded::from((super::KEYB64_PROP, TEST_ENCODED_KEY)),
381			PublicKeyEncoded::Base64(TEST_ENCODED_KEY)
382		)
383	}
384
385	#[test]
386	fn public_key_encoded_from_trait_for_base58() {
387		assert_eq!(
388			PublicKeyEncoded::from((super::KEYB58_PROP, TEST_ENCODED_KEY)),
389			PublicKeyEncoded::Base58(TEST_ENCODED_KEY)
390		)
391	}
392
393	#[test]
394	fn public_key_encoded_from_trait_for_multibase() {
395		assert_eq!(
396			PublicKeyEncoded::from((super::KEYMUL_PROP, TEST_ENCODED_KEY)),
397			PublicKeyEncoded::Multibase(TEST_ENCODED_KEY)
398		)
399	}
400
401	#[test]
402	fn public_key_encoded_from_trait_for_ethraddress() {
403		assert_eq!(
404			PublicKeyEncoded::from((super::KEYETH_PROP, TEST_ENCODED_KEY)),
405			PublicKeyEncoded::EthrAddress(TEST_ENCODED_KEY)
406		)
407	}
408
409	#[test]
410	fn public_key_encoded_from_trait_for_unsupported() {
411		assert_eq!(
412			PublicKeyEncoded::from(("azertyuiop", TEST_ENCODED_KEY)),
413			PublicKeyEncoded::Unsupported
414		)
415	}
416
417	#[test]
418	fn public_key_property_accessors() {
419		let pubkey = PublicKey {
420			id: "did:example:123456789abcdefghi#keys-1",
421			key_type: PublicKeyType::Ed25519,
422			controller: "did:example:123456789abcdefghi",
423			encoded_key: PublicKeyEncoded::Base58("H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"),
424		};
425		assert_eq!(pubkey.id(), "did:example:123456789abcdefghi#keys-1");
426		assert_eq!(pubkey.key_type(), &PublicKeyType::Ed25519);
427		assert_eq!(pubkey.controller(), "did:example:123456789abcdefghi");
428		assert_eq!(
429			pubkey.encoded_key(),
430			&PublicKeyEncoded::Base58("H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV")
431		);
432	}
433
434	#[test]
435	fn public_key_builder_for_rsa_key() {
436		assert_eq!(
437			PublicKeyBuilder::new(
438				"did:example:123456789abcdefghi#keys-1",
439				PublicKeyType::Rsa,
440				"did:example:123456789abcdefghi"
441			)
442			.with_encoded_key(PublicKeyEncoded::Pem(
443				"-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
444			))
445			.build(),
446			PublicKey {
447				id: "did:example:123456789abcdefghi#keys-1",
448				key_type: PublicKeyType::Rsa,
449				controller: "did:example:123456789abcdefghi",
450				encoded_key: PublicKeyEncoded::Pem(
451					"-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
452				),
453			}
454		)
455	}
456
457	#[test]
458	fn public_key_builder_for_ed25519_key() {
459		assert_eq!(
460			PublicKeyBuilder::new(
461				"did:example:123456789abcdefghi#keys-2",
462				PublicKeyType::Ed25519,
463				"did:example:pqrstuvwxyz0987654321"
464			)
465			.with_encoded_key(PublicKeyEncoded::Base58(
466				"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
467			))
468			.build(),
469			PublicKey {
470				id: "did:example:123456789abcdefghi#keys-2",
471				key_type: PublicKeyType::Ed25519,
472				controller: "did:example:pqrstuvwxyz0987654321",
473				encoded_key: PublicKeyEncoded::Base58(
474					"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
475				),
476			}
477		)
478	}
479
480	#[test]
481	fn public_key_builder_for_edcsasecp256k1_key() {
482		assert_eq!(
483			PublicKeyBuilder::new(
484				"did:example:123456789abcdefghi#keys-3",
485				PublicKeyType::EcdsaSecp256k1,
486				"did:example:123456789abcdefghi"
487			)
488			.with_encoded_key(PublicKeyEncoded::Hex(
489				"02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71"
490			))
491			.build(),
492			PublicKey {
493				id: "did:example:123456789abcdefghi#keys-3",
494				key_type: PublicKeyType::EcdsaSecp256k1,
495				controller: "did:example:123456789abcdefghi",
496				encoded_key: PublicKeyEncoded::Hex(
497					"02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71"
498				),
499			}
500		)
501	}
502
503	#[test]
504	fn service_property_accessors() {
505		let svc = Service::new(
506			"did:example:123456789abcdefghi#openid",
507			"OpenIdConnectVersion1.0Service",
508			ServiceEndpoint::Uri("https://openid.example.com/"),
509		);
510		assert_eq!(svc.id(), "did:example:123456789abcdefghi#openid");
511		assert_eq!(svc.svc_type(), "OpenIdConnectVersion1.0Service");
512		assert_eq!(
513			svc.endpoint(),
514			&ServiceEndpoint::Uri("https://openid.example.com/")
515		);
516	}
517
518	#[test]
519	fn did_document_property_accessors() {
520		let pubkey = PublicKey {
521			id: "did:example:123456789abcdefghi#keys-1",
522			key_type: PublicKeyType::Ed25519,
523			controller: "did:example:123456789abcdefghi",
524			encoded_key: PublicKeyEncoded::Base58("H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"),
525		};
526
527		let verif_method = VerificationMethod::Embedded(pubkey.clone());
528
529		let service = Service {
530			id: "did:example:123456789abcdefghi#openid",
531			svc_type: "OpenIdConnectVersion1.0Service",
532			endpoint: ServiceEndpoint::Uri("https://openid.example.com/"),
533		};
534
535		let did_doc = DidDocument {
536			context: "https://www.w3.org/2019/did/v1",
537			id: "did:example:123456789abcdefghi",
538			created: Some("2002-10-10T17:00:00Z"),
539			updated: Some("2002-10-10T17:00:00Z"),
540			authentication: vec![verif_method.clone()],
541			pub_keys: vec![pubkey.clone()],
542			service: vec![service.clone()],
543		};
544		assert_eq!(did_doc.context(), "https://www.w3.org/2019/did/v1");
545		assert_eq!(did_doc.id(), "did:example:123456789abcdefghi");
546		assert_eq!(did_doc.created(), Some("2002-10-10T17:00:00Z"));
547		assert_eq!(did_doc.created(), Some("2002-10-10T17:00:00Z"));
548		assert_eq!(did_doc.authentication(), &[verif_method]);
549		assert_eq!(did_doc.pub_keys(), &[pubkey]);
550		assert_eq!(did_doc.service(), &[service]);
551	}
552
553	#[test]
554	fn did_document_builder_with_pub_keys() {
555		assert_eq!(
556			DidDocumentBuilder::new("did:example:123456789abcdefghi")
557				.with_pubkeys(vec![
558					PublicKeyBuilder::new(
559						"did:example:123456789abcdefghi#keys-1",
560						PublicKeyType::Rsa,
561						"did:example:123456789abcdefghi"
562					)
563					.with_encoded_key(PublicKeyEncoded::Pem(
564						"-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
565					))
566					.build(),
567					PublicKeyBuilder::new(
568						"did:example:123456789abcdefghi#keys-2",
569						PublicKeyType::Ed25519,
570						"did:example:pqrstuvwxyz0987654321"
571					)
572					.with_encoded_key(PublicKeyEncoded::Base58(
573						"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
574					))
575					.build(),
576					PublicKeyBuilder::new(
577						"did:example:123456789abcdefghi#keys-3",
578						PublicKeyType::EcdsaSecp256k1,
579						"did:example:123456789abcdefghi"
580					)
581					.with_encoded_key(PublicKeyEncoded::Hex(
582						"02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71"
583					))
584					.build()
585				])
586				.build(),
587			DidDocument {
588				context: GENERIC_DID_CTX,
589				id: "did:example:123456789abcdefghi",
590				pub_keys: vec![
591					PublicKey {
592						id: "did:example:123456789abcdefghi#keys-1",
593						key_type: PublicKeyType::Rsa,
594						controller: "did:example:123456789abcdefghi",
595						encoded_key: PublicKeyEncoded::Pem(
596							"-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
597						),
598					},
599					PublicKey {
600						id: "did:example:123456789abcdefghi#keys-2",
601						key_type: PublicKeyType::Ed25519,
602						controller: "did:example:pqrstuvwxyz0987654321",
603						encoded_key: PublicKeyEncoded::Base58(
604							"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
605						),
606					},
607					PublicKey {
608						id: "did:example:123456789abcdefghi#keys-3",
609						key_type: PublicKeyType::EcdsaSecp256k1,
610						controller: "did:example:123456789abcdefghi",
611						encoded_key: PublicKeyEncoded::Hex(
612							"02b97c30de767f084ce3080168ee293053ba33b235d7116a3263d29f1450936b71"
613						),
614					}
615				],
616				..Default::default()
617			}
618		)
619	}
620
621	#[test]
622	fn did_document_builder_with_auth_reference_verif_method() {
623		assert_eq!(
624			DidDocumentBuilder::new("did:example:123456789abcdefghi")
625				.with_authentication(vec![VerificationMethod::Reference(
626					"did:example:123456789abcdefghi#keys-1"
627				)])
628				.with_pubkeys(vec![PublicKeyBuilder::new(
629					"did:example:123456789abcdefghi#keys-1",
630					PublicKeyType::Rsa,
631					"did:example:123456789abcdefghi"
632				)
633				.with_encoded_key(PublicKeyEncoded::Pem(
634					"-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
635				))
636				.build()])
637				.build(),
638			DidDocument {
639				context: GENERIC_DID_CTX,
640				id: "did:example:123456789abcdefghi",
641				authentication: vec![VerificationMethod::Reference(
642					"did:example:123456789abcdefghi#keys-1"
643				)],
644				pub_keys: vec![PublicKey {
645					id: "did:example:123456789abcdefghi#keys-1",
646					key_type: PublicKeyType::Rsa,
647					controller: "did:example:123456789abcdefghi",
648					encoded_key: PublicKeyEncoded::Pem(
649						"-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
650					),
651				}],
652				..Default::default()
653			}
654		)
655	}
656
657	#[test]
658	fn did_document_builder_with_auth_embedded_verif_method() {
659		assert_eq!(
660			DidDocumentBuilder::new("did:example:123456789abcdefghi")
661				.with_authentication(vec![VerificationMethod::Embedded(
662					PublicKeyBuilder::new(
663						"did:example:123456789abcdefghi#keys-2",
664						PublicKeyType::Ed25519,
665						"did:example:123456789abcdefghi"
666					)
667					.with_encoded_key(PublicKeyEncoded::Base58(
668						"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
669					))
670					.build(),
671				)])
672				.build(),
673			DidDocument {
674				context: GENERIC_DID_CTX,
675				id: "did:example:123456789abcdefghi",
676				authentication: vec![VerificationMethod::Embedded(PublicKey {
677					id: "did:example:123456789abcdefghi#keys-2",
678					key_type: PublicKeyType::Ed25519,
679					controller: "did:example:123456789abcdefghi",
680					encoded_key: PublicKeyEncoded::Base58(
681						"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
682					),
683				})],
684				..Default::default()
685			}
686		)
687	}
688
689	#[test]
690	fn did_document_builder_with_service_uri_endpoint() {
691		assert_eq!(
692			DidDocumentBuilder::new("did:example:123456789abcdefghi")
693				.with_services(vec![Service::new(
694					"did:example:123456789abcdefghi#openid",
695					"OpenIdConnectVersion1.0Service",
696					ServiceEndpoint::Uri("https://openid.example.com/")
697				)])
698				.build(),
699			DidDocument {
700				context: GENERIC_DID_CTX,
701				id: "did:example:123456789abcdefghi",
702				service: vec![Service {
703					id: "did:example:123456789abcdefghi#openid",
704					svc_type: "OpenIdConnectVersion1.0Service",
705					endpoint: ServiceEndpoint::Uri("https://openid.example.com/")
706				}],
707				..Default::default()
708			}
709		)
710	}
711
712	#[test]
713	fn did_document_builder_with_created() {
714		assert_eq!(
715			DidDocumentBuilder::new("did:example:123456789abcdefghi")
716				.created_on("2002-10-10T17:00:00Z")
717				.build(),
718			DidDocument {
719				context: GENERIC_DID_CTX,
720				id: "did:example:123456789abcdefghi",
721				created: Some("2002-10-10T17:00:00Z"),
722				..Default::default()
723			}
724		)
725	}
726
727	#[test]
728	fn did_document_builder_with_updated() {
729		assert_eq!(
730			DidDocumentBuilder::new("did:example:123456789abcdefghi")
731				.updated_on("2002-10-10T17:00:00Z")
732				.build(),
733			DidDocument {
734				context: GENERIC_DID_CTX,
735				id: "did:example:123456789abcdefghi",
736				updated: Some("2002-10-10T17:00:00Z"),
737				..Default::default()
738			}
739		)
740	}
741}