Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verification suport #56

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,216 changes: 857 additions & 359 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,27 @@ default = []
clap = "2.33.3"
chrono = "0.4.19"
dashmap = "4.0.2"
futures = "0.3.14"
futures = "0.3.15"
indoc = "1.0.3"
url = "2.2.1"
url = "2.2.2"
serde_json = "1.0.64"
strum = "0.20.0"
strum_macros = "0.20.1"
syntect = "4.5.0"
tokio = { version = "1.5.0", features = [ "rt-multi-thread", "sync" ] }
tracing = "0.1.25"
tracing-subscriber = "0.2.17"
tokio = { version = "1.7.1", features = [ "rt-multi-thread", "sync" ] }
tracing = "0.1.26"
tracing-subscriber = "0.2.19"
uuid = { version = "0.8.2", features = ["v4"] }
unicode-segmentation = "1.7.1"
qrcode = { version = "0.12.0", default-features = false }
image = "0.23.14"

[dependencies.weechat]
git = "https://github.com/poljar/rust-weechat"
rev = "8209460a4313bdcaef161ec423ae8de97a6ee412"
features = ["async", "config_macro"]

[dependencies.matrix-sdk]
git = "https://github.com/matrix-org/matrix-rust-sdk"
git = "https://github.com/matrix-org/matrix-rust-sdk/"
rev = "e919a82b2c8ea881e00982c5ce26521ec91894cf"
features = ["markdown"]
6 changes: 2 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
WEECHAT_HOME ?= $(HOME)/.weechat
PREFIX ?= $(WEECHAT_HOME)

SOURCES := $(wildcard src/*.rs src/commands/*.rs)
.PHONY: install install-dir lint target/debug/libmatrix.so

.PHONY: install install-dir lint

target/debug/libmatrix.so: $(SOURCES)
target/debug/libmatrix.so:
cargo build

install: install-dir target/debug/libmatrix.so
Expand Down
3 changes: 2 additions & 1 deletion src/bar_items/buffer_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ impl BarItemCallback for BufferName {
)
}

BufferOwner::Room(server, _) => {
BufferOwner::Room(server, _)
| BufferOwner::Verification(server, _) => {
let color = if server.is_connection_secure() {
"status_name_ssl"
} else {
Expand Down
4 changes: 3 additions & 1 deletion src/bar_items/buffer_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ impl BufferPlugin {
impl BarItemCallback for BufferPlugin {
fn callback(&mut self, _: &Weechat, buffer: &Buffer) -> String {
match self.servers.buffer_owner(buffer) {
BufferOwner::Server(s) | BufferOwner::Room(s, _) => {
BufferOwner::Server(s)
| BufferOwner::Room(s, _)
| BufferOwner::Verification(s, _) => {
format!(
"{plugin_name}{del_color}/{color}{name}",
plugin_name = PLUGIN_NAME,
Expand Down
14 changes: 9 additions & 5 deletions src/commands/devices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use clap::{
App as Argparse, AppSettings as ArgParseSettings, Arg, ArgMatches,
SubCommand,
};
use matrix_sdk::identifiers::DeviceIdBox;
use matrix_sdk::ruma::identifiers::DeviceIdBox;

use weechat::{
buffer::Buffer,
Expand All @@ -21,6 +21,13 @@ impl DevicesCommand {
pub const DESCRIPTION: &'static str =
"List, delete or rename Matrix devices";

pub const SETTINGS: &'static [ArgParseSettings] = &[
ArgParseSettings::DisableHelpFlags,
ArgParseSettings::DisableVersion,
ArgParseSettings::VersionlessSubcommands,
ArgParseSettings::SubcommandRequiredElseHelp,
];

pub fn create(servers: &Servers) -> Result<Command, ()> {
let settings = CommandSettings::new("devices")
.description(Self::DESCRIPTION)
Expand Down Expand Up @@ -115,10 +122,7 @@ impl CommandCallback for DevicesCommand {
fn callback(&mut self, _: &Weechat, buffer: &Buffer, arguments: Args) {
let argparse = Argparse::new("devices")
.about(Self::DESCRIPTION)
.global_setting(ArgParseSettings::DisableHelpFlags)
.global_setting(ArgParseSettings::DisableVersion)
.global_setting(ArgParseSettings::VersionlessSubcommands)
.setting(ArgParseSettings::SubcommandRequiredElseHelp)
.settings(Self::SETTINGS)
.subcommands(Self::subcommands());

parse_and_run(argparse, arguments, |matches| {
Expand Down
11 changes: 7 additions & 4 deletions src/commands/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ pub struct KeysCommand {
impl KeysCommand {
pub const DESCRIPTION: &'static str = "Import or export E2EE keys.";
pub const COMPLETION: &'static str = "import|export %(filename)";
pub const SETTINGS: &'static [ArgParseSettings] = &[
ArgParseSettings::DisableHelpFlags,
ArgParseSettings::DisableVersion,
ArgParseSettings::VersionlessSubcommands,
ArgParseSettings::SubcommandRequiredElseHelp,
];

pub fn create(servers: &Servers) -> Result<Command, ()> {
let settings = CommandSettings::new("keys")
Expand Down Expand Up @@ -116,10 +122,7 @@ impl CommandCallback for KeysCommand {
fn callback(&mut self, _: &Weechat, buffer: &Buffer, arguments: Args) {
let argparse = Argparse::new("keys")
.about(Self::DESCRIPTION)
.global_setting(ArgParseSettings::DisableHelpFlags)
.global_setting(ArgParseSettings::DisableVersion)
.global_setting(ArgParseSettings::VersionlessSubcommands)
.setting(ArgParseSettings::SubcommandRequiredElseHelp)
.settings(Self::SETTINGS)
.subcommands(Self::subcommands());

parse_and_run(argparse, arguments, |matches| {
Expand Down
41 changes: 31 additions & 10 deletions src/commands/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use weechat::{

use super::parse_and_run;
use crate::{
commands::{DevicesCommand, KeysCommand},
commands::{
verification::VerificationCommand, DevicesCommand, KeysCommand,
},
config::ConfigHandle,
MatrixServer, Servers, PLUGIN_NAME,
};
Expand All @@ -38,20 +40,26 @@ impl MatrixCommand {
.add_argument("reconnect <server-name>")
.add_argument("help <matrix-command> [<matrix-subcommand>]")
.arguments_description(&format!(
" server: List, add, or remove Matrix servers.
connect: Connect to Matrix servers.
disconnect: Disconnect from one or all Matrix servers.
reconnect: Reconnect to server(s).
devices: {}
keys: {}
" server: List, add, or remove Matrix servers.
connect: Connect to Matrix servers.
disconnect: Disconnect from one or all Matrix servers.
reconnect: Reconnect to server(s).
devices: {}
keys: {}
verification: {}
help: Show detailed command help.\n
Use /matrix [command] help to find out more.\n",
DevicesCommand::DESCRIPTION,
KeysCommand::DESCRIPTION,
VerificationCommand::DESCRIPTION,
))
.add_completion("server |add|delete|list|listfull")
.add_completion("devices |list|delete|set-name")
.add_completion(&format!("keys {}", KeysCommand::COMPLETION))
.add_completion(&format!(
"verification {}",
VerificationCommand::COMPLETION
))
.add_completion("connect %(matrix_servers)")
.add_completion("disconnect %(matrix_servers)")
.add_completion("reconnect %(matrix_servers)")
Expand Down Expand Up @@ -224,6 +232,9 @@ Use /matrix [command] help to find out more.\n",
("keys", Some(subargs)) => {
KeysCommand::run(buffer, &self.servers, subargs)
}
("verification", Some(subargs)) => {
VerificationCommand::run(buffer, &self.servers, subargs)
}
_ => unreachable!(),
}
}
Expand Down Expand Up @@ -272,21 +283,31 @@ impl CommandCallback for MatrixCommand {

let argparse = Argparse::new("matrix")
.about("Matrix chat protocol command.")
.global_setting(ArgParseSettings::DisableHelpFlags)
.global_setting(ArgParseSettings::DisableVersion)
.global_setting(ArgParseSettings::VersionlessSubcommands)
.global_settings(&[
ArgParseSettings::DisableHelpFlags,
ArgParseSettings::DisableVersion,
ArgParseSettings::VersionlessSubcommands,
])
.setting(ArgParseSettings::SubcommandRequiredElseHelp)
.subcommand(server_command)
.subcommand(
SubCommand::with_name("devices")
.about(DevicesCommand::DESCRIPTION)
.settings(DevicesCommand::SETTINGS)
.subcommands(DevicesCommand::subcommands()),
)
.subcommand(
SubCommand::with_name("keys")
.about(KeysCommand::DESCRIPTION)
.settings(KeysCommand::SETTINGS)
.subcommands(KeysCommand::subcommands()),
)
.subcommand(
SubCommand::with_name("verification")
.about(VerificationCommand::DESCRIPTION)
.settings(VerificationCommand::SETTINGS)
.subcommands(VerificationCommand::subcommands()),
)
.subcommand(
SubCommand::with_name("connect")
.about("Connect to Matrix servers.")
Expand Down
4 changes: 4 additions & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,21 @@ mod devices;
mod keys;
mod matrix;
mod page_up;
mod verification;

use buffer_clear::BufferClearCommand;
use devices::DevicesCommand;
use keys::KeysCommand;
use matrix::MatrixCommand;
use page_up::PageUpCommand;
use verification::VerificationCommand;

pub struct Commands {
_matrix: Command,
_keys: Command,
_devices: Command,
_page_up: CommandRun,
_verification: Command,
_buffer_clear: CommandRun,
}

Expand All @@ -36,6 +39,7 @@ impl Commands {
_devices: DevicesCommand::create(servers)?,
_keys: KeysCommand::create(servers)?,
_page_up: PageUpCommand::create(servers)?,
_verification: VerificationCommand::create(servers)?,
_buffer_clear: BufferClearCommand::create(servers)?,
})
}
Expand Down
133 changes: 133 additions & 0 deletions src/commands/verification.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use clap::{
App as Argparse, AppSettings as ArgParseSettings, ArgMatches, SubCommand,
};

use weechat::{
buffer::Buffer,
hooks::{Command, CommandCallback, CommandSettings},
Args, Weechat,
};

use super::parse_and_run;
use crate::{BufferOwner, Servers};

pub struct VerificationCommand {
servers: Servers,
}

enum CommandType {
Accept,
Confirm,
UseEmoji,
Cancel,
}

impl VerificationCommand {
pub const DESCRIPTION: &'static str =
"Control interactive verification flows";

pub const COMPLETION: &'static str = "accept|confirm|cancel|use-emoji";

pub const SETTINGS: &'static [ArgParseSettings] = &[
ArgParseSettings::DisableHelpFlags,
ArgParseSettings::DisableVersion,
ArgParseSettings::VersionlessSubcommands,
ArgParseSettings::SubcommandRequiredElseHelp,
];

pub fn create(servers: &Servers) -> Result<Command, ()> {
let settings = CommandSettings::new("verification")
.description(Self::DESCRIPTION)
.add_argument("verification accept|confirm|cancel|use-emoji")
.arguments_description(
"accept: accept the verification request
use-emoji: switch to emoji verification QR code verification \
isn't possible
confirm: confirm that the emojis match on both sides or \
confirm that the other side has scanned our QR code
cancel: cancel the verification flow or request",
)
.add_completion(Self::COMPLETION)
.add_completion("help accept|confirm|cancel");

Command::new(
settings,
VerificationCommand {
servers: servers.clone(),
},
)
}

fn verification(servers: &Servers, buffer: &Buffer, command: CommandType) {
let buffer_owner = servers.buffer_owner(buffer);

match buffer_owner {
BufferOwner::Room(_, b) => match command {
CommandType::Accept => b.accept_verification(),
CommandType::Confirm => b.confirm_verification(),
CommandType::Cancel => b.cancel_verification(),
CommandType::UseEmoji => Weechat::print(
"The 'use-emoji' command can only be used for self verifications"
),
},
BufferOwner::Verification(_, b) => match command {
CommandType::Accept => b.accept(),
CommandType::Confirm => b.confirm(),
CommandType::Cancel => b.cancel(),
CommandType::UseEmoji => b.start_sas(),
},
BufferOwner::Server(_) | BufferOwner::None => {
Weechat::print(
"The verification command needs to be executed in a room or \
verification buffer",
);
}
}
}

pub fn run(buffer: &Buffer, servers: &Servers, args: &ArgMatches) {
match args.subcommand() {
("accept", _) => {
Self::verification(servers, buffer, CommandType::Accept)
}
("confirm", _) => {
Self::verification(servers, buffer, CommandType::Confirm)
}
("use-emoji", _) => {
Self::verification(servers, buffer, CommandType::UseEmoji)
}
("cancel", _) => {
Self::verification(servers, buffer, CommandType::Cancel)
}
_ => unreachable!(),
}
}

pub fn subcommands() -> Vec<Argparse<'static, 'static>> {
vec![
SubCommand::with_name("accept")
.about("Accept a verification request"),
SubCommand::with_name("use-emoji")
.about("Switch to emoji verification"),
SubCommand::with_name("confirm").about(
"Confirm that the emoji matches or that the other side has \
scanned our QR code",
),
SubCommand::with_name("cancel")
.about("Cancel the verification flow"),
]
}
}

impl CommandCallback for VerificationCommand {
fn callback(&mut self, _: &Weechat, buffer: &Buffer, arguments: Args) {
let argparse = Argparse::new("verification")
.about(Self::DESCRIPTION)
.settings(Self::SETTINGS)
.subcommands(Self::subcommands());

parse_and_run(argparse, arguments, |matches| {
Self::run(buffer, &self.servers, &matches)
});
}
}
Loading