mirror of
https://github.com/YGGverse/Yoda.git
synced 2025-01-30 13:04:13 +00:00
move item property components to separated mods
This commit is contained in:
parent
2799ce37fe
commit
a7e809bb39
@ -3,15 +3,9 @@ use widget::{form::list::item::value::Value, Widget};
|
|||||||
|
|
||||||
use crate::app::browser::window::Action;
|
use crate::app::browser::window::Action;
|
||||||
use crate::profile::Profile;
|
use crate::profile::Profile;
|
||||||
use gtk::{
|
use gtk::{glib::Uri, prelude::IsA};
|
||||||
gio::{prelude::TlsCertificateExt, TlsCertificate},
|
|
||||||
glib::{gformat, Uri},
|
|
||||||
prelude::IsA,
|
|
||||||
};
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
const DATE_FORMAT: &str = "%Y.%m.%d";
|
|
||||||
|
|
||||||
pub struct Gemini {
|
pub struct Gemini {
|
||||||
// profile: Rc<Profile>,
|
// profile: Rc<Profile>,
|
||||||
widget: Rc<Widget>,
|
widget: Rc<Widget>,
|
||||||
@ -20,136 +14,13 @@ pub struct Gemini {
|
|||||||
impl Gemini {
|
impl Gemini {
|
||||||
// Construct
|
// Construct
|
||||||
|
|
||||||
/// Create new `Self` for given Profile
|
/// Create new `Self` for given `Profile`
|
||||||
pub fn new(profile: Rc<Profile>, action: Rc<Action>, auth_uri: Uri) -> Self {
|
pub fn new(profile: Rc<Profile>, action: Rc<Action>, auth_uri: Uri) -> Self {
|
||||||
// Init widget
|
|
||||||
let widget = Rc::new(Widget::new(profile.clone()));
|
|
||||||
|
|
||||||
// Init shared URL string from URI
|
// Init shared URL string from URI
|
||||||
let url = auth_uri.to_string();
|
let auth_url = auth_uri.to_string();
|
||||||
|
|
||||||
// Add guest option
|
// Init widget
|
||||||
widget.form.list.append(
|
let widget = Rc::new(Widget::new(profile.clone(), &auth_url));
|
||||||
Value::UseGuestSession,
|
|
||||||
"Guest session",
|
|
||||||
"No identity for this request",
|
|
||||||
None,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add new identity option
|
|
||||||
widget.form.list.append(
|
|
||||||
Value::GenerateNewAuth,
|
|
||||||
"Create new",
|
|
||||||
"Generate long-term certificate",
|
|
||||||
None,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add import existing identity option
|
|
||||||
widget.form.list.append(
|
|
||||||
Value::ImportPem,
|
|
||||||
"Import identity",
|
|
||||||
"Use existing certificate",
|
|
||||||
None,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Collect identities as options from profile database
|
|
||||||
// * memory cache synced also and could be faster @TODO
|
|
||||||
match profile.identity.gemini.database.records() {
|
|
||||||
Ok(identities) => {
|
|
||||||
for identity in identities {
|
|
||||||
// Get certificate details
|
|
||||||
let certificate = match TlsCertificate::from_pem(&identity.pem) {
|
|
||||||
Ok(certificate) => certificate,
|
|
||||||
Err(reason) => todo!("{reason}"),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Init tooltip components
|
|
||||||
let mut tooltip = "<b>Certificate</b>\n".to_string();
|
|
||||||
|
|
||||||
if let Some(subject_name) = certificate.subject_name() {
|
|
||||||
tooltip
|
|
||||||
.push_str(&format!("\n<small><b>subject</b>\n{subject_name}</small>"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(issuer_name) = certificate.issuer_name() {
|
|
||||||
tooltip.push_str(&format!("\n<small><b>issuer</b>\n{issuer_name}</small>"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(not_valid_before) = certificate.not_valid_before() {
|
|
||||||
if let Ok(timestamp) = not_valid_before.format_iso8601() {
|
|
||||||
tooltip.push_str(&format!(
|
|
||||||
"\n<small><b>valid after</b>\n{timestamp}</small>"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(not_valid_after) = certificate.not_valid_after() {
|
|
||||||
if let Ok(timestamp) = not_valid_after.format_iso8601() {
|
|
||||||
tooltip.push_str(&format!(
|
|
||||||
"\n<small><b>valid before</b>\n{timestamp}</small>"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect scope info
|
|
||||||
let mut scope = Vec::new();
|
|
||||||
|
|
||||||
for auth in profile
|
|
||||||
.identity
|
|
||||||
.gemini
|
|
||||||
.auth
|
|
||||||
.database
|
|
||||||
.records_scope(None)
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.filter(|this| this.profile_identity_gemini_id == identity.id)
|
|
||||||
{
|
|
||||||
scope.push(format!("<small>{}</small>", auth.scope.clone()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !scope.is_empty() {
|
|
||||||
tooltip.push_str(&format!("\n\n<b>Scope</b>\n\n{}", scope.join("\n")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append record option
|
|
||||||
widget.form.list.append(
|
|
||||||
Value::ProfileIdentityGeminiId(identity.id),
|
|
||||||
// title
|
|
||||||
&certificate
|
|
||||||
.subject_name()
|
|
||||||
.unwrap_or(gformat!("Unknown"))
|
|
||||||
.replace("CN=", ""), // trim prefix
|
|
||||||
// subtitle
|
|
||||||
&format!(
|
|
||||||
"{} - {} | scope: {}",
|
|
||||||
certificate
|
|
||||||
.not_valid_before()
|
|
||||||
.unwrap() // @TODO
|
|
||||||
.format(DATE_FORMAT)
|
|
||||||
.unwrap(),
|
|
||||||
certificate
|
|
||||||
.not_valid_after()
|
|
||||||
.unwrap() // @TODO
|
|
||||||
.format(DATE_FORMAT)
|
|
||||||
.unwrap(),
|
|
||||||
scope.len(),
|
|
||||||
),
|
|
||||||
Some(&tooltip),
|
|
||||||
profile
|
|
||||||
.identity
|
|
||||||
.gemini
|
|
||||||
.auth
|
|
||||||
.memory
|
|
||||||
.match_scope(&url)
|
|
||||||
.is_some_and(|auth| auth.profile_identity_gemini_id == identity.id), // is selected
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => todo!("{e}"),
|
|
||||||
} // @TODO separate markup
|
|
||||||
|
|
||||||
// Init events
|
// Init events
|
||||||
widget.on_apply({
|
widget.on_apply({
|
||||||
@ -158,8 +29,8 @@ impl Gemini {
|
|||||||
// Get option match user choice
|
// Get option match user choice
|
||||||
let option = match response {
|
let option = match response {
|
||||||
Value::ProfileIdentityGeminiId(value) => Some(value),
|
Value::ProfileIdentityGeminiId(value) => Some(value),
|
||||||
Value::UseGuestSession => None,
|
Value::GuestSession => None,
|
||||||
Value::GenerateNewAuth => Some(
|
Value::GeneratePem => Some(
|
||||||
match profile
|
match profile
|
||||||
.identity
|
.identity
|
||||||
.gemini
|
.gemini
|
||||||
@ -189,14 +60,14 @@ impl Gemini {
|
|||||||
.identity
|
.identity
|
||||||
.gemini
|
.gemini
|
||||||
.auth
|
.auth
|
||||||
.apply(profile_identity_gemini_id, &url)
|
.apply(profile_identity_gemini_id, &auth_url)
|
||||||
{
|
{
|
||||||
todo!("{}", reason.to_string())
|
todo!("{}", reason.to_string())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Remove all identity auths for `auth_uri`
|
// Remove all identity auths for `auth_uri`
|
||||||
None => {
|
None => {
|
||||||
if let Err(reason) = profile.identity.gemini.auth.remove_scope(&url) {
|
if let Err(reason) = profile.identity.gemini.auth.remove_scope(&auth_url) {
|
||||||
todo!("{}", reason.to_string())
|
todo!("{}", reason.to_string())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -33,12 +33,12 @@ impl Widget {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new(profile: Rc<Profile>) -> Self {
|
pub fn new(profile: Rc<Profile>, auth_url: &str) -> Self {
|
||||||
// Init actions
|
// Init actions
|
||||||
let action = Rc::new(Action::new());
|
let action = Rc::new(Action::new());
|
||||||
|
|
||||||
// Init child container
|
// Init child container
|
||||||
let form = Rc::new(Form::new(profile, action.clone()));
|
let form = Rc::new(Form::new(profile, action.clone(), auth_url));
|
||||||
|
|
||||||
// Init main widget
|
// Init main widget
|
||||||
let alert_dialog = AlertDialog::builder()
|
let alert_dialog = AlertDialog::builder()
|
||||||
|
@ -32,10 +32,10 @@ impl Form {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new(profile: Rc<Profile>, action: Rc<Action>) -> Self {
|
pub fn new(profile: Rc<Profile>, action: Rc<Action>, auth_url: &str) -> Self {
|
||||||
// Init components
|
// Init components
|
||||||
let file = Rc::new(File::new(action.clone()));
|
let file = Rc::new(File::new(action.clone()));
|
||||||
let list = Rc::new(List::new());
|
let list = Rc::new(List::new(profile.clone(), auth_url));
|
||||||
let name = Rc::new(Name::new(action.clone()));
|
let name = Rc::new(Name::new(action.clone()));
|
||||||
let save = Rc::new(Save::new(profile.clone()));
|
let save = Rc::new(Save::new(profile.clone()));
|
||||||
let drop = Rc::new(Drop::new(profile.clone(), action.clone(), list.clone()));
|
let drop = Rc::new(Drop::new(profile.clone(), action.clone(), list.clone()));
|
||||||
@ -61,7 +61,7 @@ impl Form {
|
|||||||
let update = action.update.clone();
|
let update = action.update.clone();
|
||||||
move |item| {
|
move |item| {
|
||||||
// Change name entry visibility
|
// Change name entry visibility
|
||||||
name.update(matches!(item, Value::GenerateNewAuth));
|
name.update(matches!(item, Value::GeneratePem));
|
||||||
|
|
||||||
// Change file choose button visibility
|
// Change file choose button visibility
|
||||||
file.update(matches!(item, Value::ImportPem));
|
file.update(matches!(item, Value::ImportPem));
|
||||||
@ -103,7 +103,7 @@ impl Form {
|
|||||||
/// Validate `Self` components match current selection
|
/// Validate `Self` components match current selection
|
||||||
pub fn is_applicable(&self) -> bool {
|
pub fn is_applicable(&self) -> bool {
|
||||||
match self.list.selected_item().value_enum() {
|
match self.list.selected_item().value_enum() {
|
||||||
Value::GenerateNewAuth => self.name.is_valid(),
|
Value::GeneratePem => self.name.is_valid(),
|
||||||
Value::ImportPem => self.file.is_valid(),
|
Value::ImportPem => self.file.is_valid(),
|
||||||
Value::ProfileIdentityGeminiId(_) => !self.list.selected_item().is_active(),
|
Value::ProfileIdentityGeminiId(_) => !self.list.selected_item().is_active(),
|
||||||
_ => true,
|
_ => true,
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
pub mod item;
|
pub mod item;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use item::{value::Value, Item};
|
use item::{value::Value, Item};
|
||||||
|
|
||||||
|
use crate::profile::Profile;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gdk::Cursor,
|
gdk::Cursor,
|
||||||
gio::{
|
gio::{
|
||||||
@ -20,10 +23,33 @@ impl List {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn new() -> Self {
|
pub fn new(profile: Rc<Profile>, auth_url: &str) -> Self {
|
||||||
// Init `ListStore` with custom `DropDown` properties
|
// Init model
|
||||||
let list_store = ListStore::new::<Item>();
|
let list_store = ListStore::new::<Item>();
|
||||||
|
|
||||||
|
list_store.append(&Item::new_guest_session());
|
||||||
|
list_store.append(&Item::new_generate_pem());
|
||||||
|
list_store.append(&Item::new_import_pem());
|
||||||
|
|
||||||
|
// Append identities from profile database
|
||||||
|
// * memory cache synced also and could be faster @TODO
|
||||||
|
match profile.identity.gemini.database.records() {
|
||||||
|
Ok(identities) => {
|
||||||
|
for identity in identities {
|
||||||
|
match Item::new_profile_identity_gemini_id(
|
||||||
|
profile.clone(),
|
||||||
|
identity.id,
|
||||||
|
&identity.pem,
|
||||||
|
auth_url,
|
||||||
|
) {
|
||||||
|
Ok(item) => list_store.append(&item),
|
||||||
|
Err(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => todo!(),
|
||||||
|
}
|
||||||
|
|
||||||
// Setup item factory
|
// Setup item factory
|
||||||
// * wanted only to append items after `DropDown` init
|
// * wanted only to append items after `DropDown` init
|
||||||
let factory = SignalListItemFactory::new();
|
let factory = SignalListItemFactory::new();
|
||||||
@ -99,6 +125,13 @@ impl List {
|
|||||||
.factory(&factory)
|
.factory(&factory)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
// Select active record
|
||||||
|
dropdown.set_selected(
|
||||||
|
list_store
|
||||||
|
.find_with_equal_func(|item| item.dynamic_cast_ref::<Item>().unwrap().is_active())
|
||||||
|
.unwrap(),
|
||||||
|
); // @TODO panic or handle?
|
||||||
|
|
||||||
// Return activated `Self`
|
// Return activated `Self`
|
||||||
Self {
|
Self {
|
||||||
list_store,
|
list_store,
|
||||||
@ -108,25 +141,6 @@ impl List {
|
|||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/// Append new item
|
|
||||||
pub fn append(
|
|
||||||
&self,
|
|
||||||
value: Value,
|
|
||||||
title: &str,
|
|
||||||
subtitle: &str,
|
|
||||||
tooltip: Option<&str>,
|
|
||||||
is_active: bool,
|
|
||||||
) {
|
|
||||||
let item = Item::new(value, title, subtitle, tooltip, is_active);
|
|
||||||
|
|
||||||
self.list_store.append(&item);
|
|
||||||
|
|
||||||
if is_active {
|
|
||||||
self.dropdown
|
|
||||||
.set_selected(self.list_store.find(&item).unwrap()); // @TODO panic or handle?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find list item by `value` (stores ID)
|
/// Find list item by `value` (stores ID)
|
||||||
/// * return `position` found
|
/// * return `position` found
|
||||||
pub fn find(&self, value: i64) -> Option<u32> {
|
pub fn find(&self, value: i64) -> Option<u32> {
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
|
mod error;
|
||||||
mod imp;
|
mod imp;
|
||||||
|
mod is_active;
|
||||||
|
mod subtitle;
|
||||||
|
mod title;
|
||||||
|
mod tooltip;
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
use gtk::glib::{self, Object};
|
use std::rc::Rc;
|
||||||
use value::Value;
|
|
||||||
|
pub use error::Error;
|
||||||
|
pub use value::Value;
|
||||||
|
|
||||||
|
use crate::profile::Profile;
|
||||||
|
use gtk::{
|
||||||
|
gio::TlsCertificate,
|
||||||
|
glib::{self, Object},
|
||||||
|
};
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct Item(ObjectSubclass<imp::Item>);
|
pub struct Item(ObjectSubclass<imp::Item>);
|
||||||
@ -10,47 +23,105 @@ glib::wrapper! {
|
|||||||
|
|
||||||
// C-type property `value` conversion for `Item`
|
// C-type property `value` conversion for `Item`
|
||||||
// * values > 0 reserved for `profile_identity_gemini_id`
|
// * values > 0 reserved for `profile_identity_gemini_id`
|
||||||
const G_VALUE_GENERATE_NEW_AUTH: i64 = 0;
|
const G_VALUE_GENERATE_PEM: i64 = 0;
|
||||||
const G_VALUE_IMPORT_PEM: i64 = -1;
|
const G_VALUE_IMPORT_PEM: i64 = -1;
|
||||||
const G_VALUE_USE_GUEST_SESSION: i64 = -2;
|
const G_VALUE_GUEST_SESSION: i64 = -2;
|
||||||
|
|
||||||
impl Item {
|
impl Item {
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `GObject`
|
pub fn new_guest_session() -> Self {
|
||||||
pub fn new(
|
|
||||||
value: Value,
|
|
||||||
title: &str,
|
|
||||||
subtitle: &str,
|
|
||||||
tooltip: Option<&str>,
|
|
||||||
is_active: bool,
|
|
||||||
) -> Self {
|
|
||||||
Object::builder()
|
Object::builder()
|
||||||
.property(
|
.property("value", G_VALUE_GUEST_SESSION)
|
||||||
"value",
|
.property("title", "Guest session")
|
||||||
match value {
|
.property("subtitle", "No identity for this request")
|
||||||
Value::GenerateNewAuth => G_VALUE_GENERATE_NEW_AUTH,
|
|
||||||
Value::ImportPem => G_VALUE_IMPORT_PEM,
|
|
||||||
Value::UseGuestSession => G_VALUE_USE_GUEST_SESSION,
|
|
||||||
Value::ProfileIdentityGeminiId(value) => value,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.property("title", title)
|
|
||||||
.property("subtitle", subtitle)
|
|
||||||
.property("tooltip", tooltip.unwrap_or_default())
|
|
||||||
.property("is_active", is_active)
|
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_generate_pem() -> Self {
|
||||||
|
Object::builder()
|
||||||
|
.property("value", G_VALUE_GENERATE_PEM)
|
||||||
|
.property("title", "Create new")
|
||||||
|
.property("subtitle", "Generate long-term certificate")
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_import_pem() -> Self {
|
||||||
|
Object::builder()
|
||||||
|
.property("value", G_VALUE_IMPORT_PEM)
|
||||||
|
.property("title", "Import identity")
|
||||||
|
.property("subtitle", "Use existing certificate")
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_profile_identity_gemini_id(
|
||||||
|
profile: Rc<Profile>,
|
||||||
|
profile_identity_gemini_id: i64,
|
||||||
|
pem: &str,
|
||||||
|
auth_url: &str,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
match TlsCertificate::from_pem(pem) {
|
||||||
|
Ok(certificate) => {
|
||||||
|
// Collect shared certificate scope
|
||||||
|
let scope = scope(profile.clone(), profile_identity_gemini_id);
|
||||||
|
|
||||||
|
// Build GObject
|
||||||
|
Ok(Object::builder()
|
||||||
|
.property("value", profile_identity_gemini_id)
|
||||||
|
.property(
|
||||||
|
"title",
|
||||||
|
title::new_for_profile_identity_gemini_id(&certificate),
|
||||||
|
)
|
||||||
|
.property(
|
||||||
|
"subtitle",
|
||||||
|
subtitle::new_for_profile_identity_gemini_id(&certificate, &scope),
|
||||||
|
)
|
||||||
|
.property(
|
||||||
|
"tooltip",
|
||||||
|
tooltip::new_for_profile_identity_gemini_id(&certificate, &scope),
|
||||||
|
)
|
||||||
|
.property(
|
||||||
|
"is_active",
|
||||||
|
is_active::new_for_profile_identity_gemini_id(
|
||||||
|
profile,
|
||||||
|
profile_identity_gemini_id,
|
||||||
|
auth_url,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.build())
|
||||||
|
}
|
||||||
|
Err(e) => Err(Error::TlsCertificate(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
|
|
||||||
/// Get `value` as enum `Value`
|
/// Get `Self` C-value as `Value`
|
||||||
pub fn value_enum(&self) -> Value {
|
pub fn value_enum(&self) -> Value {
|
||||||
match self.value() {
|
match self.value() {
|
||||||
G_VALUE_GENERATE_NEW_AUTH => Value::GenerateNewAuth,
|
G_VALUE_GENERATE_PEM => Value::GeneratePem,
|
||||||
|
G_VALUE_GUEST_SESSION => Value::GuestSession,
|
||||||
G_VALUE_IMPORT_PEM => Value::ImportPem,
|
G_VALUE_IMPORT_PEM => Value::ImportPem,
|
||||||
G_VALUE_USE_GUEST_SESSION => Value::UseGuestSession,
|
|
||||||
value => Value::ProfileIdentityGeminiId(value),
|
value => Value::ProfileIdentityGeminiId(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tools
|
||||||
|
|
||||||
|
fn scope(profile: Rc<Profile>, profile_identity_gemini_id: i64) -> Vec<String> {
|
||||||
|
let mut scope = Vec::new();
|
||||||
|
for auth in profile
|
||||||
|
.identity
|
||||||
|
.gemini
|
||||||
|
.auth
|
||||||
|
.database
|
||||||
|
.records_scope(None)
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.filter(|this| this.profile_identity_gemini_id == profile_identity_gemini_id)
|
||||||
|
{
|
||||||
|
scope.push(auth.scope.clone())
|
||||||
|
}
|
||||||
|
scope
|
||||||
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
use std::fmt::{Display, Formatter, Result};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
TlsCertificate(gtk::glib::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Error {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||||
|
match self {
|
||||||
|
Self::TlsCertificate(e) => {
|
||||||
|
write!(f, "TLS certificate error `{e}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
use crate::profile::Profile;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub fn new_for_profile_identity_gemini_id(
|
||||||
|
profile: Rc<Profile>,
|
||||||
|
profile_identity_gemini_id: i64,
|
||||||
|
auth_url: &str,
|
||||||
|
) -> bool {
|
||||||
|
profile
|
||||||
|
.identity
|
||||||
|
.gemini
|
||||||
|
.auth
|
||||||
|
.memory
|
||||||
|
.match_scope(&auth_url)
|
||||||
|
.is_some_and(|auth| auth.profile_identity_gemini_id == profile_identity_gemini_id)
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
use gtk::{gio::TlsCertificate, prelude::TlsCertificateExt};
|
||||||
|
|
||||||
|
const DATE_FORMAT: &str = "%Y.%m.%d";
|
||||||
|
|
||||||
|
pub fn new_for_profile_identity_gemini_id(
|
||||||
|
certificate: &TlsCertificate,
|
||||||
|
scope: &[String],
|
||||||
|
) -> String {
|
||||||
|
format!(
|
||||||
|
"{} - {} | scope: {}",
|
||||||
|
certificate
|
||||||
|
.not_valid_before()
|
||||||
|
.unwrap() // @TODO
|
||||||
|
.format(DATE_FORMAT)
|
||||||
|
.unwrap(),
|
||||||
|
certificate
|
||||||
|
.not_valid_after()
|
||||||
|
.unwrap() // @TODO
|
||||||
|
.format(DATE_FORMAT)
|
||||||
|
.unwrap(),
|
||||||
|
scope.len(),
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
use gtk::{gio::TlsCertificate, glib::gformat, prelude::TlsCertificateExt};
|
||||||
|
|
||||||
|
pub fn new_for_profile_identity_gemini_id(certificate: &TlsCertificate) -> String {
|
||||||
|
certificate
|
||||||
|
.subject_name()
|
||||||
|
.unwrap_or(gformat!("Unknown"))
|
||||||
|
.replace("CN=", "")
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
use gtk::{gio::TlsCertificate, prelude::TlsCertificateExt};
|
||||||
|
|
||||||
|
pub fn new_for_profile_identity_gemini_id(
|
||||||
|
certificate: &TlsCertificate,
|
||||||
|
scope: &Vec<String>,
|
||||||
|
) -> String {
|
||||||
|
let mut tooltip = "<b>Certificate</b>\n".to_string();
|
||||||
|
|
||||||
|
if let Some(subject_name) = certificate.subject_name() {
|
||||||
|
tooltip.push_str(&format!("\n<small><b>subject</b>\n{subject_name}</small>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(issuer_name) = certificate.issuer_name() {
|
||||||
|
tooltip.push_str(&format!("\n<small><b>issuer</b>\n{issuer_name}</small>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(not_valid_before) = certificate.not_valid_before() {
|
||||||
|
if let Ok(timestamp) = not_valid_before.format_iso8601() {
|
||||||
|
tooltip.push_str(&format!("\n<small><b>valid after</b>\n{timestamp}</small>"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(not_valid_after) = certificate.not_valid_after() {
|
||||||
|
if let Ok(timestamp) = not_valid_after.format_iso8601() {
|
||||||
|
tooltip.push_str(&format!(
|
||||||
|
"\n<small><b>valid before</b>\n{timestamp}</small>"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !scope.is_empty() {
|
||||||
|
tooltip.push_str("\n\n<b>Scope</b>\n");
|
||||||
|
|
||||||
|
for path in scope {
|
||||||
|
tooltip.push_str(&format!("\n{}", path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
GenerateNewAuth,
|
GeneratePem,
|
||||||
|
GuestSession,
|
||||||
ImportPem,
|
ImportPem,
|
||||||
ProfileIdentityGeminiId(i64),
|
ProfileIdentityGeminiId(i64),
|
||||||
UseGuestSession,
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user