tangled
alpha
login
or
join now
vielle.dev
/
tangled-on-commit
5
fork
atom
Listen to git commits for a specific repo and run a shell command
5
fork
atom
overview
issues
pulls
pipelines
Add helpful error messages
vielle.dev
6 months ago
bcbb66b8
46e72bb1
verified
This commit was signed with the committer's
known signature
.
vielle.dev
SSH Key Fingerprint:
SHA256:/4bvxqoEh9iMdjAPgcgAgXKZZQTROL3ULiPt6nH9RSs=
+55
-18
3 changed files
expand all
collapse all
unified
split
src
args.rs
did.rs
main.rs
+1
src/args.rs
···
92
if val.contains("/") {
93
let entries: Vec<_> = val.split("/").collect();
94
if entries.len() != 2 {
0
95
return Err(());
96
}
97
handle = Some(entries[0][1..].to_string());
···
92
if val.contains("/") {
93
let entries: Vec<_> = val.split("/").collect();
94
if entries.len() != 2 {
95
+
println!("Invalid argument: `{}` is malformed", val);
96
return Err(());
97
}
98
handle = Some(entries[0][1..].to_string());
+52
-10
src/did.rs
···
12
// create a txt resolver
13
let resolver = match Resolver::new(ResolverConfig::default(), ResolverOpts::default()) {
14
Ok(val) => val,
15
-
Err(_) => return Err(()),
0
0
0
16
};
17
18
// resolve _atproto.handle to a TXT record
19
let txt_res = match resolver.txt_lookup("_atproto.".to_owned() + &handle) {
20
Ok(val) => val,
21
-
Err(_) => return Err(()), // collect all entries and convert to strings
0
0
0
22
}
23
.into_iter()
24
.map(|x| x.to_string())
···
32
// only 1 did= can exist
33
// https://atproto.com/specs/handle#:~:text=If%20multiple%20valid%20records%20with%20different%20DIDs%20are%20present,%20resolution%20should%20fail.
34
if did_res.len() != 1 {
0
35
return Err(());
36
}
37
···
39
}
40
41
fn get_http_did(handle: &String) -> Result<String, ()> {
42
-
println!(" Trying https for https://{}/.well-known/atproto-did", handle);
0
0
0
43
let res =
44
match reqwest::blocking::get("https://".to_owned() + handle + "/.well-known/atproto-did") {
45
Ok(val) => val,
46
-
Err(_) => return Err(()),
0
0
0
47
};
48
49
// as per spec, non 2xx code means failure
50
if !res.status().is_success() {
0
0
0
0
51
return Err(());
52
}
53
54
let did_unparsed = match res.text() {
55
Ok(val) => val,
56
-
Err(_) => return Err(()),
0
0
0
57
};
58
59
let did = did_unparsed.trim();
60
61
if !did.starts_with("did:") {
0
62
return Err(());
63
};
64
return Ok(String::from(did));
···
67
fn parse_doc(did: String, text: String) -> Result<DidDoc, ()> {
68
let text_json = match json::parse(&text) {
69
Ok(val) => val,
70
-
Err(_) => return Err(()),
0
0
0
71
};
72
73
for service in text_json["service"].members() {
···
86
}
87
}
88
0
89
return Err(());
90
}
91
92
fn get_plc_doc(plc: &str) -> Result<DidDoc, ()> {
93
let res = match reqwest::blocking::get("https://plc.directory/did:plc:".to_owned() + plc) {
94
Ok(val) => val,
95
-
Err(_) => return Err(()),
0
0
0
96
};
97
98
if !res.status().is_success() {
0
0
99
return Err(());
100
}
101
···
103
"did:plc:".to_owned() + plc,
104
match res.text() {
105
Ok(val) => val,
106
-
Err(_) => return Err(()),
0
0
0
107
},
108
);
109
}
···
111
fn get_web_doc(web: &str) -> Result<DidDoc, ()> {
112
let res = match reqwest::blocking::get("https://".to_owned() + web + "/.well-known/did.json") {
113
Ok(val) => val,
114
-
Err(_) => return Err(()),
0
0
0
115
};
116
117
if !res.status().is_success() {
0
118
return Err(());
119
}
120
···
122
"did:web:".to_owned() + web,
123
match res.text() {
124
Ok(val) => val,
125
-
Err(_) => return Err(()),
0
0
0
126
},
127
);
128
}
···
135
if let Ok(did) = get_http_did(&handle) {
136
did
137
} else {
0
138
return Err(());
139
}
140
};
···
145
} else if did.starts_with("did:web:") {
146
get_web_doc(&did[8..])
147
} else {
0
148
Err(())
149
};
150
···
12
// create a txt resolver
13
let resolver = match Resolver::new(ResolverConfig::default(), ResolverOpts::default()) {
14
Ok(val) => val,
15
+
Err(_) => {
16
+
println!(" Couldn't create a DNS resolver");
17
+
return Err(());
18
+
}
19
};
20
21
// resolve _atproto.handle to a TXT record
22
let txt_res = match resolver.txt_lookup("_atproto.".to_owned() + &handle) {
23
Ok(val) => val,
24
+
Err(_) => {
25
+
println!(" Couldn't resolve to a TXT record");
26
+
return Err(());
27
+
} // collect all entries and convert to strings
28
}
29
.into_iter()
30
.map(|x| x.to_string())
···
38
// only 1 did= can exist
39
// https://atproto.com/specs/handle#:~:text=If%20multiple%20valid%20records%20with%20different%20DIDs%20are%20present,%20resolution%20should%20fail.
40
if did_res.len() != 1 {
41
+
println!(" Found too many DIDs for this handle");
42
return Err(());
43
}
44
···
46
}
47
48
fn get_http_did(handle: &String) -> Result<String, ()> {
49
+
println!(
50
+
" Trying https for https://{}/.well-known/atproto-did",
51
+
handle
52
+
);
53
let res =
54
match reqwest::blocking::get("https://".to_owned() + handle + "/.well-known/atproto-did") {
55
Ok(val) => val,
56
+
Err(_) => {
57
+
println!(" GET request failed");
58
+
return Err(());
59
+
}
60
};
61
62
// as per spec, non 2xx code means failure
63
if !res.status().is_success() {
64
+
println!(
65
+
" Got non 2xx status code: {}",
66
+
res.status().as_str()
67
+
);
68
return Err(());
69
}
70
71
let did_unparsed = match res.text() {
72
Ok(val) => val,
73
+
Err(_) => {
74
+
println!(" Missing or malformed body response");
75
+
return Err(());
76
+
}
77
};
78
79
let did = did_unparsed.trim();
80
81
if !did.starts_with("did:") {
82
+
println!(" Did not find a DID");
83
return Err(());
84
};
85
return Ok(String::from(did));
···
88
fn parse_doc(did: String, text: String) -> Result<DidDoc, ()> {
89
let text_json = match json::parse(&text) {
90
Ok(val) => val,
91
+
Err(_) => {
92
+
println!(" Malformed DID document");
93
+
return Err(());
94
+
}
95
};
96
97
for service in text_json["service"].members() {
···
110
}
111
}
112
113
+
println!(" Missing fields from DID document");
114
return Err(());
115
}
116
117
fn get_plc_doc(plc: &str) -> Result<DidDoc, ()> {
118
let res = match reqwest::blocking::get("https://plc.directory/did:plc:".to_owned() + plc) {
119
Ok(val) => val,
120
+
Err(_) => {
121
+
println!(" GET request failed");
122
+
return Err(());
123
+
}
124
};
125
126
if !res.status().is_success() {
127
+
println!(" Got non 2xx status code: {}", res.status().as_str());
128
+
129
return Err(());
130
}
131
···
133
"did:plc:".to_owned() + plc,
134
match res.text() {
135
Ok(val) => val,
136
+
Err(_) => {
137
+
println!(" Missing or malformed body response");
138
+
return Err(());
139
+
}
140
},
141
);
142
}
···
144
fn get_web_doc(web: &str) -> Result<DidDoc, ()> {
145
let res = match reqwest::blocking::get("https://".to_owned() + web + "/.well-known/did.json") {
146
Ok(val) => val,
147
+
Err(_) => {
148
+
println!(" GET request failed");
149
+
return Err(());
150
+
}
151
};
152
153
if !res.status().is_success() {
154
+
println!(" Got non 2xx status code: {}", res.status().as_str());
155
return Err(());
156
}
157
···
159
"did:web:".to_owned() + web,
160
match res.text() {
161
Ok(val) => val,
162
+
Err(_) => {
163
+
println!(" Missing or malformed body response");
164
+
return Err(());
165
+
}
166
},
167
);
168
}
···
175
if let Ok(did) = get_http_did(&handle) {
176
did
177
} else {
178
+
println!(" Could not get a DID");
179
return Err(());
180
}
181
};
···
186
} else if did.starts_with("did:web:") {
187
get_web_doc(&did[8..])
188
} else {
189
+
println!(" Could not get a DID document");
190
Err(())
191
};
192
+2
-8
src/main.rs
···
5
// load configuration
6
let config = match args::load_config() {
7
Ok(res) => res,
8
-
Err(_) => {
9
-
// q
10
-
return Err(());
11
-
}
12
};
13
14
// resolve handle to did
15
println!("Resolving {}", config.handle);
16
let did_doc = match did::get_did(config.handle) {
17
Ok(res) => res,
18
-
Err(_) => {
19
-
// q
20
-
return Err(());
21
-
}
22
};
23
// resolve did+repoName to knotserver
24
···
5
// load configuration
6
let config = match args::load_config() {
7
Ok(res) => res,
8
+
Err(_) => return Err(()),
0
0
0
9
};
10
11
// resolve handle to did
12
println!("Resolving {}", config.handle);
13
let did_doc = match did::get_did(config.handle) {
14
Ok(res) => res,
15
+
Err(_) => return Err(()),
0
0
0
16
};
17
// resolve did+repoName to knotserver
18