delegate certificate init to ggemini wrapper, add structs for some, tuple entities, move match_priority to gemini impl area

This commit is contained in:
yggverse 2024-11-27 21:40:44 +02:00
parent 36f07aa773
commit 053c078e11
6 changed files with 53 additions and 29 deletions

View File

@ -23,7 +23,7 @@ use crate::Profile;
use gtk::{ use gtk::{
gdk::Texture, gdk::Texture,
gdk_pixbuf::Pixbuf, gdk_pixbuf::Pixbuf,
gio::{Cancellable, SocketClientEvent, TlsCertificate}, gio::{Cancellable, SocketClientEvent},
glib::{ glib::{
gformat, GString, Priority, Regex, RegexCompileFlags, RegexMatchFlags, Uri, UriFlags, gformat, GString, Priority, Regex, RegexCompileFlags, RegexMatchFlags, Uri, UriFlags,
UriHideFlags, UriHideFlags,
@ -417,17 +417,19 @@ impl Page {
let input = self.input.clone(); let input = self.input.clone();
let meta = self.meta.clone(); let meta = self.meta.clone();
// Return PEM string match request // Find identity match request
let certificate = match self let certificate = match self
.profile .profile
.identity .identity
.gemini(&self.navigation.request().widget().gobject().text()) .gemini
.match_priority(&self.navigation.request().widget().gobject().text())
{ {
// @TODO delegate to client Some(identity) => {
Some(pem) => match TlsCertificate::from_pem(&pem) { match gemini::client::Certificate::from_pem(&identity.pem, &identity.scope) {
Ok(certificate) => Some(certificate), Ok(certificate) => Some(certificate),
Err(reason) => todo!("{reason}"), Err(reason) => todo!("{reason}"),
}, }
}
None => None, None => None,
}; };

View File

@ -47,19 +47,6 @@ impl Identity {
gemini, gemini,
}) })
} }
/// Get `pem` record match `request`
/// * [Client certificates specification](https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates)
/// * this function work with memory cache collected (not database)
pub fn gemini(&self, request: &str) -> Option<String> {
if let Some(id) = self.gemini.auth.memory.match_priority(request) {
match self.gemini.memory.get(id) {
Ok(pem) => return Some(pem),
Err(reason) => todo!("{:?}", reason.to_string()),
}
}
None
}
} }
// Tools // Tools

View File

@ -2,11 +2,13 @@ mod auth;
mod certificate; mod certificate;
mod database; mod database;
mod error; mod error;
mod identity;
mod memory; mod memory;
use auth::Auth; use auth::Auth;
use database::Database; use database::Database;
pub use error::Error; pub use error::Error;
use identity::Identity;
use memory::Memory; use memory::Memory;
@ -106,6 +108,24 @@ impl Gemini {
Ok(()) Ok(())
} }
/// Get `pem` record match `request`
/// * [Client certificates specification](https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates)
/// * this function work with memory cache collected (not database)
pub fn match_priority(&self, request: &str) -> Option<Identity> {
if let Some(auth) = self.auth.memory.match_priority(request) {
match self.memory.get(auth.profile_identity_gemini_id) {
Ok(pem) => {
return Some(Identity {
scope: auth.scope,
pem,
})
}
Err(reason) => todo!("{:?}", reason.to_string()),
}
}
None
}
} }
// Tools // Tools

View File

@ -1,4 +1,7 @@
pub mod auth;
pub mod error; pub mod error;
pub use auth::Auth;
pub use error::Error; pub use error::Error;
use std::{cell::RefCell, collections::HashMap}; use std::{cell::RefCell, collections::HashMap};
@ -49,23 +52,26 @@ impl Memory {
} }
} }
/// Get `profile_identity_gemini_id` vector match given `request` /// Get identity match `request`
/// * [Client certificates specification](https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates) /// * [Client certificates specification](https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates)
/// * contain unspecified length priority implementation @TODO /// * contain unspecified length priority implementation @TODO
pub fn match_priority(&self, request: &str) -> Option<i64> { pub fn match_priority(&self, request: &str) -> Option<Auth> {
let mut result = Vec::new(); let mut result = Vec::new();
// Get all records starts with URL cached, collect length for priority // Get all records starts with URL cached, collect length for priority
for (url, &profile_identity_gemini_id) in self.index.borrow().iter() { for (scope, &profile_identity_gemini_id) in self.index.borrow().iter() {
if request.starts_with(url) { if request.starts_with(scope) {
result.push((profile_identity_gemini_id, url.len())) result.push(Auth {
profile_identity_gemini_id,
scope: scope.clone(),
})
} }
} }
// Sort by length desc @TODO // Sort by length desc @TODO
result.sort_by(|a, b| b.1.cmp(&a.1)); result.sort_by(|a, b| b.scope.len().cmp(&a.scope.len()));
// Get first match ID // Get first copy
result.first().map(|value| value.0) result.first().cloned()
} }
} }

View File

@ -0,0 +1,5 @@
#[derive(Clone)]
pub struct Auth {
pub profile_identity_gemini_id: i64,
pub scope: String,
}

View File

@ -0,0 +1,4 @@
pub struct Identity {
pub pem: String,
pub scope: String,
}