Implement AuthorizationRequestRecords
This commit is contained in:
parent
88d87bd25d
commit
9ee5156dfc
7 changed files with 187 additions and 215 deletions
|
|
@ -5,9 +5,54 @@ mod received;
|
||||||
|
|
||||||
use std::os::unix::raw::time_t;
|
use std::os::unix::raw::time_t;
|
||||||
|
|
||||||
|
use caretta_id::DoubleId;
|
||||||
use chrono::{DateTime, Local, NaiveDateTime};
|
use chrono::{DateTime, Local, NaiveDateTime};
|
||||||
use iroh::NodeId;
|
use iroh::{NodeId, PublicKey};
|
||||||
pub use sent::*;
|
pub use sent::*;
|
||||||
pub use received::*;
|
pub use received::*;
|
||||||
use rusqlite::{params, types::FromSqlError, Connection};
|
use rusqlite::{params, types::FromSqlError, Connection};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::data::local::LocalRecord;
|
||||||
|
|
||||||
|
|
||||||
|
/// Request of node authentication.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct AuthorizationRequestRecord {
|
||||||
|
id: u32,
|
||||||
|
uid: DoubleId,
|
||||||
|
peer_id: u32,
|
||||||
|
created_at: DateTime<Local>,
|
||||||
|
closed_at: Option<DateTime<Local>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LocalRecord for AuthorizationRequestRecord {
|
||||||
|
|
||||||
|
const TABLE_NAME: &str = "authorization_request";
|
||||||
|
const SELECT_COLUMNS: &[&str] = &[
|
||||||
|
"id",
|
||||||
|
"uid",
|
||||||
|
"peer_id",
|
||||||
|
"created_at",
|
||||||
|
"closed_at"
|
||||||
|
];
|
||||||
|
const INSERT_COLUMNS: &[&str] = &[
|
||||||
|
"uid",
|
||||||
|
"peer_id",
|
||||||
|
"created_at"
|
||||||
|
];
|
||||||
|
|
||||||
|
type InsertParams<'a> = (&'a DoubleId, &'a [u8;32], &'a NaiveDateTime);
|
||||||
|
|
||||||
|
fn from_row(row: &rusqlite::Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||||
|
let created_at: NaiveDateTime = row.get(3)?;
|
||||||
|
let closed_at: Option<NaiveDateTime> = row.get(4)?;
|
||||||
|
Ok(Self {
|
||||||
|
id: row.get(0)?,
|
||||||
|
uid: row.get(1)?,
|
||||||
|
peer_id: row.get(2)?,
|
||||||
|
created_at: created_at.and_utc().into(),
|
||||||
|
closed_at: closed_at.map(|x| x.and_utc().into())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,85 +6,36 @@ use crate::{data::local::LocalRecord, global::LOCAL_DATABASE_CONNECTION};
|
||||||
|
|
||||||
/// Response of node authentication.
|
/// Response of node authentication.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ReceivedAuthorizationRequest {
|
pub struct ReceivedAuthorizationRequestRecord {
|
||||||
request_id: SingleId,
|
id: u32,
|
||||||
public_key: PublicKey,
|
authorization_request_id: u32,
|
||||||
node_info: String,
|
peer_note: String,
|
||||||
created_at: DateTime<Local>,
|
|
||||||
responded_at: Option<DateTime<Local>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LocalRecord for ReceivedAuthorizationRequestRecord {
|
||||||
|
|
||||||
impl ReceivedAuthorizationRequest {
|
|
||||||
pub fn get_by_request_id(request_id: SingleId) -> Result<Self, rusqlite::Error> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
pub fn get_by_public_key(public_key: PublicKey) -> Result<Self, rusqlite::Error> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
pub fn get_by_local_peer_id(local_peer_id: DoubleId) -> Result<Self, rusqlite::Error> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LocalRecord for ReceivedAuthorizationRequest {
|
|
||||||
const TABLE_NAME: &str = "received_authorization_request";
|
const TABLE_NAME: &str = "received_authorization_request";
|
||||||
const DEFAULT_COLUMNS: &[&str] = &[
|
|
||||||
"request_id",
|
const SELECT_COLUMNS: &[&str] = &[
|
||||||
"public_key",
|
"id",
|
||||||
"node_info",
|
"authorization_request_id",
|
||||||
"created_at",
|
"peer_note"
|
||||||
"responded_at",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
type DefaultParams<'a> = (&'a SingleId, &'a [u8;32], &'a str, NaiveDateTime, Option<NaiveDateTime>)
|
const INSERT_COLUMNS: &[&str] = &[
|
||||||
where
|
"authorization_request_id",
|
||||||
Self: 'a;
|
"peer_note"
|
||||||
|
];
|
||||||
|
|
||||||
fn as_default_params<'a>(&'a self) -> Self::DefaultParams<'a> {
|
type InsertParams<'a> = (&'a u32, &'a str);
|
||||||
(&self.request_id,&self.public_key.as_bytes(), &self.node_info, self.created_at.naive_utc(), self.responded_at.map(|x| x.naive_utc()))
|
|
||||||
}
|
fn from_row(row: &rusqlite::Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||||
fn from_default_row(row: &rusqlite::Row<'_>) -> Result<Self, rusqlite::Error> {
|
|
||||||
let created_at: NaiveDateTime = row.get(3)?;
|
|
||||||
let responded_at: Option<NaiveDateTime> = row.get(4)?;
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
request_id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
public_key: PublicKey::from_bytes(&row.get(1)?).map_err(|e| rusqlite::types::FromSqlError::Other(Box::new(e)))?,
|
authorization_request_id: row.get(1)?,
|
||||||
node_info: row.get(2)?,
|
peer_note: row.get(2)?
|
||||||
created_at: DateTime::from(created_at.and_utc()),
|
|
||||||
responded_at: responded_at.map(|x| DateTime::from(x.and_utc())),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn insert(&self) -> Result<(), rusqlite::Error> {
|
|
||||||
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
|
||||||
|
|
||||||
connection.execute(
|
|
||||||
&("INSERT INTO ".to_string() + Self::TABLE_NAME + " (" + &Self::DEFAULT_COLUMNS.join(", ") + ") VALUES (?1, ?2, ?3, ?4, ?5)"),
|
|
||||||
(
|
|
||||||
&self.request_id,
|
|
||||||
&self.public_key.as_bytes(),
|
|
||||||
&self.node_info,
|
|
||||||
&self.created_at.naive_utc(),
|
|
||||||
&self.responded_at.map(|x| x.naive_utc()),
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn get_all() -> Result<Vec<Self>, rusqlite::Error> {
|
|
||||||
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
|
||||||
|
|
||||||
let mut stmt = connection.prepare(&(String::from("SELECT ") + &Self::DEFAULT_COLUMNS.join(", ") + " FROM " + Self::TABLE_NAME))?;
|
|
||||||
let rows = stmt.query_map(
|
|
||||||
[],
|
|
||||||
Self::from_default_row
|
|
||||||
)?;
|
|
||||||
let mut result= Vec::new();
|
|
||||||
for row in rows {
|
|
||||||
result.push(row?);
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -7,68 +7,33 @@ use crate::{data::local::LocalRecord, global::LOCAL_DATABASE_CONNECTION};
|
||||||
|
|
||||||
/// Request of node authentication.
|
/// Request of node authentication.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SentAuthorizationRequest {
|
pub struct SentAuthorizationRequestRecord {
|
||||||
request_id: SingleId,
|
id: u32,
|
||||||
public_key: PublicKey,
|
authorization_request_id: u32,
|
||||||
passcode: String,
|
passcode: String,
|
||||||
created_at: DateTime<Local>,
|
|
||||||
responded_at: Option<DateTime<Local>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalRecord for SentAuthorizationRequest {
|
impl LocalRecord for SentAuthorizationRequestRecord {
|
||||||
|
|
||||||
const TABLE_NAME: &str = "sent_authorization";
|
const TABLE_NAME: &str = "sent_authorization_request";
|
||||||
const DEFAULT_COLUMNS: &[&str] = &[
|
const SELECT_COLUMNS: &[&str] = &[
|
||||||
"request_id",
|
"id",
|
||||||
"public_key",
|
"authorization_request_id",
|
||||||
"passcode",
|
"passcode",
|
||||||
"created_at",
|
|
||||||
"responded_at"
|
|
||||||
];
|
];
|
||||||
type DefaultParams<'a> = (&'a SingleId, &'a [u8;32], &'a str, NaiveDateTime, Option<NaiveDateTime>)
|
const INSERT_COLUMNS: &[&str] = &[
|
||||||
where
|
"authorization_request_id",
|
||||||
Self: 'a;
|
"passcode"
|
||||||
fn from_default_row(row: &rusqlite::Row<'_>) -> Result<Self, rusqlite::Error> {
|
];
|
||||||
let created_at: NaiveDateTime = row.get(2)?;
|
|
||||||
let responded_at: Option<NaiveDateTime> = row.get(3)?;
|
type InsertParams<'a> = (&'a u32, &'a str);
|
||||||
|
|
||||||
|
fn from_row(row: &rusqlite::Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||||
Ok(Self{
|
Ok(Self{
|
||||||
request_id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
public_key: PublicKey::from_bytes(&row.get(1)?).map_err(|e| FromSqlError::Other(Box::new(e)))?,
|
authorization_request_id: row.get(0)?,
|
||||||
passcode: row.get(2)?,
|
passcode: row.get(2)?
|
||||||
created_at: DateTime::from(created_at.and_utc()),
|
|
||||||
responded_at: responded_at.map(|x| DateTime::from(x.and_utc())),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn insert(&self) -> Result<(), rusqlite::Error> {
|
|
||||||
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
|
||||||
connection.execute(
|
|
||||||
&(String::from("INSERT INTO ") + Self::TABLE_NAME + " (" + &Self::DEFAULT_COLUMNS.join(", ") + ") VALUES (?1, ?2, ?3, ?4, ?5)"),
|
|
||||||
(
|
|
||||||
&self.request_id,
|
|
||||||
&self.public_key.as_bytes(),
|
|
||||||
&self.passcode,
|
|
||||||
&self.created_at.naive_utc(),
|
|
||||||
&self.responded_at.map(|x| x.naive_utc())
|
|
||||||
),
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn get_all() -> Result<Vec<Self>, rusqlite::Error> {
|
|
||||||
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
|
||||||
|
|
||||||
let mut stmt = connection.prepare(&(String::from("SELECT ") + &Self::DEFAULT_COLUMNS.join(", ") + " FROM " + Self::TABLE_NAME))?;
|
|
||||||
let rows = stmt.query_map(
|
|
||||||
[],
|
|
||||||
Self::from_default_row
|
|
||||||
)?;
|
|
||||||
let mut result= Vec::new();
|
|
||||||
for row in rows {
|
|
||||||
result.push(row?);
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_default_params<'a>(&'a self) -> Self::DefaultParams<'a> {
|
|
||||||
(&self.request_id, &self.public_key.as_bytes(), &self.passcode, self.created_at.naive_utc(), self.responded_at.map(|x| x.naive_utc()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -6,8 +6,11 @@ use tracing::{event, Level};
|
||||||
pub fn migrate(con: &mut Connection) -> Result<(), Error>{
|
pub fn migrate(con: &mut Connection) -> Result<(), Error>{
|
||||||
let version: u32 = con.pragma_query_value(None,"user_version", |row| row.get(0)).expect("Failed to get user_version");
|
let version: u32 = con.pragma_query_value(None,"user_version", |row| row.get(0)).expect("Failed to get user_version");
|
||||||
if version < 1 {
|
if version < 1 {
|
||||||
|
let tx = con.transaction()?;
|
||||||
event!(Level::INFO, "Migrate local db to version 1");
|
event!(Level::INFO, "Migrate local db to version 1");
|
||||||
v1::migrate(con)?;
|
v1::migrate(&tx)?;
|
||||||
|
tx.pragma_update(None, "user_version", 1)?;
|
||||||
|
tx.commit()?;
|
||||||
event!(Level::INFO, "Migration done.");
|
event!(Level::INFO, "Migration done.");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,43 @@
|
||||||
use rusqlite::{Error, Connection};
|
use rusqlite::{Connection, Error, Transaction};
|
||||||
|
|
||||||
pub fn migrate(con: &mut Connection) -> Result<(), Error>{
|
pub fn migrate(tx: &Transaction) -> Result<(), Error>{
|
||||||
let tx = con.transaction()?;
|
|
||||||
tx.execute_batch(
|
tx.execute_batch(
|
||||||
"CREATE TABLE peer (
|
"CREATE TABLE peer (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
local_peer_id INTEGER NOT NULL UNIQUE,
|
uid INTEGER NOT NULL UNIQUE,
|
||||||
public_key BLOB UNIQUE NOT NULL
|
public_key BLOB UNIQUE NOT NULL
|
||||||
);
|
);
|
||||||
CREATE TABLE received_authorization_request (
|
CREATE TABLE authorization_request (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
request_id INTEGER NOT NULL UNIQUE,
|
uid INTEGER NOT NULL UNIQUE,
|
||||||
public_key BLOB NOT NULL UNIQUE,
|
peer_id INTEGER NOT NULL UNIQUE,
|
||||||
node_info TEXT,
|
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
responded_at TEXT
|
closed_at TEXT,
|
||||||
|
FOREIGN KEY(peer_id) REFERENCES peer(id)
|
||||||
|
);
|
||||||
|
CREATE TABLE received_authorization_request (
|
||||||
|
id INTEGER PRIMARY KEY
|
||||||
|
authorization_request_id INTEGER NOT NULL UNIQUE
|
||||||
|
peer_note TEXT,
|
||||||
|
FOREIGN KEY(authorization_request_id) REFERENCES authorization_request(id)
|
||||||
);
|
);
|
||||||
CREATE TABLE sent_authorization_request (
|
CREATE TABLE sent_authorization_request (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
request_id INTEGER NOT NULL UNIQUE,
|
authorization_request_id INTEGER NOT NULL UNIQUE,
|
||||||
public_key BLOB NOT NULL UNIQUE,
|
|
||||||
passcode TEXT NOT NULL,
|
passcode TEXT NOT NULL,
|
||||||
created_at TEXT NOT NULL,
|
FOREIGN KEY(authorization_request_id) REFERENCES authorization_request(id)
|
||||||
responded_at TEXT
|
|
||||||
);
|
);
|
||||||
CREATE TABLE authorized_peer (
|
CREATE TABLE authorized_peer (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
node_id BLOB NOT NULL UNIQUE,
|
uid INTEGER NOT NULL UNIQUE,
|
||||||
|
public_key BLOB NOT NULL UNIQUE,
|
||||||
|
note TEXT NOT NULL,
|
||||||
last_synced_at TEXT,
|
last_synced_at TEXT,
|
||||||
last_sent_version_vector BLOB,
|
last_sent_version_vector BLOB,
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
updated_at TEXT NOT NULL
|
updated_at TEXT NOT NULL
|
||||||
);
|
|
||||||
CREATE TABLE authorization (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
node_id BLOB UNIQUE NOT NULL,
|
|
||||||
passcode TEXT NOT NULL,
|
|
||||||
created_at TEXT NOT NULL,
|
|
||||||
updated_at TEXT NOT NULL
|
|
||||||
);",
|
);",
|
||||||
)?;
|
)?;
|
||||||
tx.pragma_update(None, "user_version", 1)?;
|
|
||||||
tx.commit()?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -15,34 +15,45 @@ pub use authorization_request::*;
|
||||||
/// use LOCAL_DATABASE_CONNECTION for database connection.
|
/// use LOCAL_DATABASE_CONNECTION for database connection.
|
||||||
pub trait LocalRecord: Sized {
|
pub trait LocalRecord: Sized {
|
||||||
const TABLE_NAME: &str;
|
const TABLE_NAME: &str;
|
||||||
const DEFAULT_COLUMNS: &[&str];
|
const SELECT_COLUMNS: &[&str];
|
||||||
|
const INSERT_COLUMNS: &[&str];
|
||||||
|
|
||||||
const DEFAULT_SELECT_STATEMENT: LazyLock<String> = LazyLock::new(|| {
|
const SELECT_STATEMENT: LazyLock<String> = LazyLock::new(|| {
|
||||||
String::from("SELECT ") + &Self::DEFAULT_COLUMNS.join(", ") + " FROM " + Self::TABLE_NAME
|
String::from("SELECT ") + &Self::SELECT_COLUMNS.join(", ") + " FROM " + Self::TABLE_NAME
|
||||||
});
|
});
|
||||||
|
|
||||||
const DEFAULT_PLACEHOLDER: LazyLock<String> = LazyLock::new(|| {
|
const SELECT_PLACEHOLDER: LazyLock<String> = LazyLock::new(|| {
|
||||||
let mut result : Vec<String> = Vec::new();
|
let mut result : Vec<String> = Vec::new();
|
||||||
for i in 0..Self::DEFAULT_COLUMNS.len() {
|
for i in 0..Self::SELECT_COLUMNS.len() {
|
||||||
|
result.push(String::from("?") + &(i+1).to_string());
|
||||||
|
}
|
||||||
|
result.join(", ")
|
||||||
|
});
|
||||||
|
const INSERT_PLACEHOLDER: LazyLock<String> = LazyLock::new(|| {
|
||||||
|
let mut result : Vec<String> = Vec::new();
|
||||||
|
for i in 0..Self::INSERT_COLUMNS.len() {
|
||||||
result.push(String::from("?") + &(i+1).to_string());
|
result.push(String::from("?") + &(i+1).to_string());
|
||||||
}
|
}
|
||||||
result.join(", ")
|
result.join(", ")
|
||||||
});
|
});
|
||||||
|
|
||||||
type DefaultParams<'a>: Params
|
type InsertParams<'a>: Params
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
|
||||||
fn as_default_params<'a>(&'a self) -> Self::DefaultParams<'a>;
|
fn insert(params: Self::InsertParams<'_>) -> Result<Self, rusqlite::Error>
|
||||||
|
{
|
||||||
fn insert(&self) -> Result<(), rusqlite::Error> {
|
|
||||||
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
||||||
|
|
||||||
connection.execute(
|
Ok(connection.query_row(
|
||||||
&("INSERT INTO ".to_owned() + Self::TABLE_NAME + " (" + &Self::DEFAULT_COLUMNS.join(", ") + ") VALUES (" + &*Self::DEFAULT_PLACEHOLDER + ")"),
|
&[
|
||||||
self.as_default_params()
|
"INSERT INTO ", Self::TABLE_NAME, "(" , &Self::INSERT_COLUMNS.join(", "), ")",
|
||||||
)?;
|
"VALUES (" , &*Self::INSERT_PLACEHOLDER , ")",
|
||||||
Ok(())
|
"RETURNING", &Self::SELECT_COLUMNS.join(", ")
|
||||||
|
].join(" "),
|
||||||
|
params,
|
||||||
|
Self::from_row
|
||||||
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_one_where<P>(where_statement: &str, params: P) -> Result<Option<Self>, rusqlite::Error>
|
fn get_one_where<P>(where_statement: &str, params: P) -> Result<Option<Self>, rusqlite::Error>
|
||||||
|
|
@ -50,26 +61,39 @@ pub trait LocalRecord: Sized {
|
||||||
{
|
{
|
||||||
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
||||||
Ok(connection.query_row(
|
Ok(connection.query_row(
|
||||||
&(String::new() + &Self::DEFAULT_SELECT_STATEMENT + " " + where_statement),
|
&(String::new() + &Self::SELECT_STATEMENT + " " + where_statement),
|
||||||
params,
|
params,
|
||||||
Self::from_default_row
|
Self::from_row
|
||||||
).optional()?)
|
).optional()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_one_by<T>(field_name: &str, field_value: T) -> Result<Option<Self>, rusqlite::Error>
|
fn get_one_by_field<T>(field_name: &str, field_value: T) -> Result<Option<Self>, rusqlite::Error>
|
||||||
where
|
where
|
||||||
T: ToSql
|
T: ToSql
|
||||||
{
|
{
|
||||||
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
||||||
Ok(Some(connection.query_row(
|
Ok(Some(connection.query_row(
|
||||||
&("SELECT ".to_string() + &Self::DEFAULT_COLUMNS.join(", ") + " FROM " + Self::TABLE_NAME + " WHERE " + field_name + "=(?1)"),
|
&("SELECT ".to_string() + &Self::SELECT_COLUMNS.join(", ") + " FROM " + Self::TABLE_NAME + " WHERE " + field_name + "= ?1"),
|
||||||
params![field_value],
|
params![field_value],
|
||||||
Self::from_default_row
|
Self::from_row
|
||||||
)?))
|
)?))
|
||||||
}
|
}
|
||||||
fn get_one_by_id(id: u32) -> Result<Option<Self>, rusqlite::Error> {
|
fn get_one_by_id(id: u32) -> Result<Option<Self>, rusqlite::Error> {
|
||||||
Self::get_one_by("id", id )
|
Self::get_one_by_field("id", id )
|
||||||
|
}
|
||||||
|
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error>;
|
||||||
|
fn get_all() -> Result<Vec<Self>, rusqlite::Error> {
|
||||||
|
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
||||||
|
let mut stmt = connection.prepare(&("SELECT ".to_string() + &Self::SELECT_COLUMNS.join(", ") + " FROM " + Self::TABLE_NAME))?;
|
||||||
|
let rows = stmt.query_map(
|
||||||
|
[],
|
||||||
|
Self::from_row
|
||||||
|
)?;
|
||||||
|
let mut result= Vec::new();
|
||||||
|
for row in rows {
|
||||||
|
result.push(row?);
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
|
||||||
}
|
}
|
||||||
fn from_default_row(row: &Row<'_>) -> Result<Self, rusqlite::Error>;
|
|
||||||
fn get_all() -> Result<Vec<Self>, rusqlite::Error>;
|
|
||||||
}
|
}
|
||||||
|
|
@ -5,14 +5,14 @@ use std::os::unix::raw::time_t;
|
||||||
use caretta_id::DoubleId;
|
use caretta_id::DoubleId;
|
||||||
use chrono::{DateTime, Local, NaiveDateTime};
|
use chrono::{DateTime, Local, NaiveDateTime};
|
||||||
use iroh::{NodeId, PublicKey};
|
use iroh::{NodeId, PublicKey};
|
||||||
use rusqlite::{params, types::FromSqlError, Connection};
|
use rusqlite::{params, types::{FromSqlError, Null}, Connection};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{data::local::{self, LocalRecord}, global::LOCAL_DATABASE_CONNECTION};
|
use crate::{data::local::{self, LocalRecord}, global::LOCAL_DATABASE_CONNECTION};
|
||||||
|
|
||||||
/// Peer information cached in local database.
|
/// Peer information cached in local database.
|
||||||
///
|
///
|
||||||
/// - Currently this only contain local id and public key (=node id) of iroh.
|
/// - Currently this only contain local uid and public key (=node id) of iroh.
|
||||||
/// - This is a junction table enable to use caretta-id to specify items in the UI, especially on the CLI.
|
/// - This is a junction table enable to use caretta-id to specify items in the UI, especially on the CLI.
|
||||||
/// - Actual peer information is managed by iroh endpoint and not contained in this model.
|
/// - Actual peer information is managed by iroh endpoint and not contained in this model.
|
||||||
/// - Once a peer is authorized, it is assigned a global (=synced) ID as authorized_peer so essentially this local id targets unauthorized peers.
|
/// - Once a peer is authorized, it is assigned a global (=synced) ID as authorized_peer so essentially this local id targets unauthorized peers.
|
||||||
|
|
@ -20,9 +20,12 @@ use crate::{data::local::{self, LocalRecord}, global::LOCAL_DATABASE_CONNECTION}
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct PeerRecord {
|
pub struct PeerRecord {
|
||||||
|
|
||||||
/// local id of peer.
|
/// primary key.
|
||||||
|
pub id: u32,
|
||||||
|
|
||||||
|
/// uid of peer.
|
||||||
/// this id is use only the node itself and not synced so another node has different local_peer_id even if its public_key is same.
|
/// this id is use only the node itself and not synced so another node has different local_peer_id even if its public_key is same.
|
||||||
pub local_peer_id: DoubleId,
|
pub uid: DoubleId,
|
||||||
pub public_key: PublicKey,
|
pub public_key: PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,17 +34,13 @@ impl PeerRecord {
|
||||||
match Self::get_by_public_key(public_key)? {
|
match Self::get_by_public_key(public_key)? {
|
||||||
Some(x) => Ok(x),
|
Some(x) => Ok(x),
|
||||||
None => {
|
None => {
|
||||||
let new = Self{
|
let new_uid: DoubleId = rand::random();
|
||||||
local_peer_id: rand::random(),
|
Ok(Self::insert((&new_uid, public_key.as_bytes()))?)
|
||||||
public_key: public_key.clone(),
|
|
||||||
};
|
|
||||||
new.insert()?;
|
|
||||||
Ok(new)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
pub fn get_by_local_id(local_id: &DoubleId) -> Result<Option<Self>, rusqlite::Error> {
|
pub fn get_by_uid(local_id: &DoubleId) -> Result<Option<Self>, rusqlite::Error> {
|
||||||
Self::get_one_where("WHERE local_peer_id = ?1", (local_id,))
|
Self::get_one_where("WHERE local_peer_id = ?1", (local_id,))
|
||||||
}
|
}
|
||||||
pub fn get_by_public_key(public_key: &PublicKey) -> Result<Option<Self>, rusqlite::Error> {
|
pub fn get_by_public_key(public_key: &PublicKey) -> Result<Option<Self>, rusqlite::Error> {
|
||||||
|
|
@ -51,36 +50,25 @@ impl PeerRecord {
|
||||||
|
|
||||||
impl LocalRecord for PeerRecord {
|
impl LocalRecord for PeerRecord {
|
||||||
const TABLE_NAME: &str = "peer";
|
const TABLE_NAME: &str = "peer";
|
||||||
const DEFAULT_COLUMNS: &[&str] = &[
|
const SELECT_COLUMNS: &[&str] = &[
|
||||||
"local_peer_id",
|
"id",
|
||||||
|
"uid",
|
||||||
"public_key"
|
"public_key"
|
||||||
];
|
];
|
||||||
type DefaultParams<'a> = (&'a DoubleId, &'a [u8;32]);
|
const INSERT_COLUMNS: &[&str] = &[
|
||||||
fn as_default_params<'a>(&'a self) -> Self::DefaultParams<'a>
|
"uid",
|
||||||
{
|
"public_key"
|
||||||
(&self.local_peer_id, &self.public_key.as_bytes())
|
];
|
||||||
}
|
type InsertParams<'a> = (&'a DoubleId, &'a [u8;32]);
|
||||||
|
|
||||||
fn from_default_row(row: &rusqlite::Row<'_>) -> Result<Self, rusqlite::Error> {
|
fn from_row(row: &rusqlite::Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
local_peer_id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
public_key: PublicKey::from_bytes(&row.get(1)?).map_err(|e| FromSqlError::Other(Box::new(e)))?
|
uid: row.get(1)?,
|
||||||
|
public_key: PublicKey::from_bytes(&row.get(2)?).map_err(|e| FromSqlError::Other(Box::new(e)))?
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_all() -> Result<Vec<Self>, rusqlite::Error> {
|
|
||||||
let connection = LOCAL_DATABASE_CONNECTION.get_unchecked();
|
|
||||||
let mut stmt = connection.prepare(&("SELECT ".to_string() + &Self::DEFAULT_COLUMNS.join(", ") + " FROM " + Self::TABLE_NAME))?;
|
|
||||||
let rows = stmt.query_map(
|
|
||||||
[],
|
|
||||||
Self::from_default_row
|
|
||||||
)?;
|
|
||||||
let mut result= Vec::new();
|
|
||||||
for row in rows {
|
|
||||||
result.push(row?);
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
@ -97,8 +85,7 @@ mod tests {
|
||||||
let key = SecretKey::generate(&mut rand::rngs::OsRng);
|
let key = SecretKey::generate(&mut rand::rngs::OsRng);
|
||||||
let pubkey = key.public();
|
let pubkey = key.public();
|
||||||
let record = PeerRecord::get_or_insert_by_public_key(&pubkey).unwrap();
|
let record = PeerRecord::get_or_insert_by_public_key(&pubkey).unwrap();
|
||||||
assert_eq!(record, PeerRecord::get_by_local_id(&record.local_peer_id).unwrap().unwrap());
|
assert_eq!(record, PeerRecord::get_by_uid(&record.uid).unwrap().unwrap());
|
||||||
assert_eq!(record, PeerRecord::get_by_public_key(&record.public_key).unwrap().unwrap());
|
assert_eq!(record, PeerRecord::get_by_public_key(&record.public_key).unwrap().unwrap());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Reference in a new issue