added some functions to switch between managing
personal projects and managing work projects as well as the ability to separate your current project list into work and personal.
This commit is contained in:
@@ -1,11 +1,16 @@
|
|||||||
|
use std::fs::read_to_string;
|
||||||
|
use std::fs::OpenOptions;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
use std::io::Write;
|
||||||
use std::thread::JoinHandle;
|
use std::thread::JoinHandle;
|
||||||
use chrono::Datelike;
|
use chrono::Datelike;
|
||||||
use clearscreen::clear;
|
use clearscreen::clear;
|
||||||
use clearscreen;
|
use clearscreen;
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use crate::print_error;
|
||||||
|
use crate::print_informational;
|
||||||
use crate::Project;
|
use crate::Project;
|
||||||
use crate::project_controls;
|
use crate::project_controls;
|
||||||
use crate::box_controls;
|
use crate::box_controls;
|
||||||
@@ -64,6 +69,9 @@ fn help(command: Option<String>){
|
|||||||
"brute force subdomains"| "bsd" | "gobuster dns" | "gd" => lines.push("brute force subdomains||bsd,gobuster dns, gd||this command will run gobuster in the project's distrobox and save the results to your notes.".to_owned()),
|
"brute force subdomains"| "bsd" | "gobuster dns" | "gd" => lines.push("brute force subdomains||bsd,gobuster dns, gd||this command will run gobuster in the project's distrobox and save the results to your notes.".to_owned()),
|
||||||
"dns enumeration" | "de" | "all dns stuff" | "ads" | "dns stuff" | "ds" => lines.push("dns enumeration||de, all dns stuff, ads, dns stuff, de||This command will perform both dns record enumeration with dnsrecon, and subdomain enumeration using gobster inside of your distrobox and save the output to your notes.".to_owned()),
|
"dns enumeration" | "de" | "all dns stuff" | "ads" | "dns stuff" | "ds" => lines.push("dns enumeration||de, all dns stuff, ads, dns stuff, de||This command will perform both dns record enumeration with dnsrecon, and subdomain enumeration using gobster inside of your distrobox and save the output to your notes.".to_owned()),
|
||||||
"modify tool config" | "mtc" => lines.push("modify tool config|| mtc||This command lets you modify the tool's configuration.".to_owned()),
|
"modify tool config" | "mtc" => lines.push("modify tool config|| mtc||This command lets you modify the tool's configuration.".to_owned()),
|
||||||
|
"separate work and personal projects" | "swpp" | "separate projects" | "seppro" => lines.push("separate work and personal||swpp, separate projects, seppro||This command lets you separate work and personal projects into separate config files. This allows you to load personal and work projects separately!".to_owned()),
|
||||||
|
"switch to personal projects" | "switch personal" => lines.push("switch to personal projects||switch personal||This command lets you switch which config file is loaded to the personal config file.".to_owned()),
|
||||||
|
"switch to work projects" | "switch work" => lines.push("switch to work projects||switch work||This command lets you switch to load the work projects.".to_owned()),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
tableize(lines);
|
tableize(lines);
|
||||||
@@ -108,6 +116,9 @@ fn help(command: Option<String>){
|
|||||||
"brute force subdomain||bsd, gobuster dns, gd".to_owned(),
|
"brute force subdomain||bsd, gobuster dns, gd".to_owned(),
|
||||||
"dns enumeration||de, all dns stuff, ads, dns stuff, ds".to_owned(),
|
"dns enumeration||de, all dns stuff, ads, dns stuff, ds".to_owned(),
|
||||||
"modify tool config||mtc".to_owned(),
|
"modify tool config||mtc".to_owned(),
|
||||||
|
"separate work and personal projects||swpp, separate projects, seppro".to_owned(),
|
||||||
|
"switch to personal projects||switch personal".to_owned(),
|
||||||
|
"switch to work projects||switch work".to_owned(),
|
||||||
"help||?, -h".to_owned()];
|
"help||?, -h".to_owned()];
|
||||||
println!("available commands:");
|
println!("available commands:");
|
||||||
tableize(lines);
|
tableize(lines);
|
||||||
@@ -243,6 +254,9 @@ pub fn run_command(cmd: String,
|
|||||||
"dns squatting scan" | "dnstwist" | "dss" => {let twist_handle = enumeration::dns_squatting(&active_project, None, true); return twist_handle},
|
"dns squatting scan" | "dnstwist" | "dss" => {let twist_handle = enumeration::dns_squatting(&active_project, None, true); return twist_handle},
|
||||||
"print report information" | "pri" => {info_controls::print_report_information(&active_project); return None;},
|
"print report information" | "pri" => {info_controls::print_report_information(&active_project); return None;},
|
||||||
"modify tool config" | "mtc" => {configuration::generate_tool_config(&config_path); return None;},
|
"modify tool config" | "mtc" => {configuration::generate_tool_config(&config_path); return None;},
|
||||||
|
"separate work and personal projects" | "swpp" | "separate projects" | "seppro" => {project_controls::separate_personal_work_projects(&config_path); return None;}
|
||||||
|
"switch to personal projects" | "switch personal" => {let mut project_load_res = project_controls::swith_to_personal(&config_path); if project_load_res.is_some(){projects.clear();for project in project_load_res.unwrap(){projects.push(project);}}; return None;},
|
||||||
|
"switch to work projects" | "switch work" => {let mut project_load_res = project_controls::swith_to_work(&config_path); if project_load_res.is_some(){projects.clear();for project in project_load_res.unwrap(){projects.push(project);}}; return None;}
|
||||||
_ => {help(None); println!("\n\n unknown command."); return None;}
|
_ => {help(None); println!("\n\n unknown command."); return None;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,7 +280,7 @@ pub fn cli(interactive: bool,
|
|||||||
upcoming_notes: &PathBuf,
|
upcoming_notes: &PathBuf,
|
||||||
password_spray_file: &PathBuf,
|
password_spray_file: &PathBuf,
|
||||||
fingerprint: bool,
|
fingerprint: bool,
|
||||||
vault_name: String) {
|
vault_name: String,) {
|
||||||
let mut threads = Vec::new();
|
let mut threads = Vec::new();
|
||||||
if interactive{
|
if interactive{
|
||||||
let mut loopize = true;
|
let mut loopize = true;
|
||||||
@@ -339,6 +353,7 @@ for help enter help or ?. for information about a specific command enter help (c
|
|||||||
|
|
||||||
|
|
||||||
", active_project.customer.green(), active_project.project_name.green(), active_project.stage.green(), active_project.files_folder.display().to_string().green(), active_project.notes_folder.display().to_string().green(), active_project.boxname.green(), "coming soon".red());
|
", active_project.customer.green(), active_project.project_name.green(), active_project.stage.green(), active_project.files_folder.display().to_string().green(), active_project.notes_folder.display().to_string().green(), active_project.boxname.green(), "coming soon".red());
|
||||||
|
println!("{}", config_path.display());
|
||||||
let prompt = format!("\n{}:{}\nCommand?", active_project.customer.custom_color((255,165,0)), active_project.project_name.custom_color((255,165,0)));
|
let prompt = format!("\n{}:{}\nCommand?", active_project.customer.custom_color((255,165,0)), active_project.project_name.custom_color((255,165,0)));
|
||||||
let command = get_user_input(&prompt);
|
let command = get_user_input(&prompt);
|
||||||
match command.as_str(){
|
match command.as_str(){
|
||||||
@@ -357,6 +372,36 @@ for help enter help or ?. for information about a specific command enter help (c
|
|||||||
box_controls::stop_all_boxes(&projects);
|
box_controls::stop_all_boxes(&projects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
print_informational("saving workspace projects...");
|
||||||
|
let mut workspace_config_path = config_path.clone();
|
||||||
|
workspace_config_path.pop();
|
||||||
|
let mut project_conf_path = config_path.clone();
|
||||||
|
project_conf_path.pop();
|
||||||
|
project_conf_path.push("projects.conf");
|
||||||
|
if get_user_input("are your work projects currently loaded? (not yoru personal projects...)").to_lowercase().contains("y"){
|
||||||
|
workspace_config_path.push("projects.work");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
workspace_config_path.push("projects.personal");
|
||||||
|
}
|
||||||
|
let open_res = OpenOptions::new().create(true).write(true).open(workspace_config_path);
|
||||||
|
if open_res.is_err(){
|
||||||
|
print_error("error opeing workspace config file!", open_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let mut workspace_config_file = open_res.unwrap();
|
||||||
|
let projects_read_res = read_to_string(project_conf_path);
|
||||||
|
if projects_read_res.is_ok(){
|
||||||
|
let project_string = projects_read_res.unwrap();
|
||||||
|
let write_res = write!(workspace_config_file, "{}", project_string);
|
||||||
|
if write_res.is_err(){
|
||||||
|
print_error("error writing workspace config file!", write_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
print_error("error reading projects config file!", projects_read_res.err().unwrap().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
if threads.len() > 0{
|
if threads.len() > 0{
|
||||||
println!("closing threads...");
|
println!("closing threads...");
|
||||||
println!("note this will hang until all threads have completed");
|
println!("note this will hang until all threads have completed");
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ vault_name:{}"
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
let mut project_conf_file = project_conf_res.unwrap();
|
let mut project_conf_file = project_conf_res.unwrap();
|
||||||
let project_write_res = write!(project_conf_file, "customer:name:notes:files:active:time:box_name:stage\ndefault:default:{}:{}:yes:{}:current", ¤t_notes.display(), ¤t_projects.display(), &template_box_name);
|
let project_write_res = write!(project_conf_file, "Projects Config File");
|
||||||
if project_write_res.is_err(){
|
if project_write_res.is_err(){
|
||||||
println!("error writing project config file.");
|
println!("error writing project config file.");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
use std::collections::btree_set::Difference;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::{io::stdin, path::PathBuf, process::Command};
|
use std::{io::stdin, path::PathBuf, process::Command};
|
||||||
use chrono::format;
|
|
||||||
use directories::UserDirs;
|
use directories::UserDirs;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use term_size::dimensions;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Project{
|
pub struct Project{
|
||||||
@@ -128,7 +125,7 @@ pub fn tableize(given_lines: Vec<String>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_overwrite(path: &PathBuf) -> Option<File>{
|
pub fn open_overwrite(path: &PathBuf) -> Option<File>{
|
||||||
let file_create_res = fs::OpenOptions::new().create(true).write(true).open(path);
|
let file_create_res = fs::OpenOptions::new().create(true).write(true).truncate(true).open(path);
|
||||||
if file_create_res.is_err(){
|
if file_create_res.is_err(){
|
||||||
let error = file_create_res.err().unwrap();
|
let error = file_create_res.err().unwrap();
|
||||||
println!("{} {} {}","error opening".red(), path.display().to_string().red(), " file".red());
|
println!("{} {} {}","error opening".red(), path.display().to_string().red(), " file".red());
|
||||||
@@ -269,6 +266,6 @@ fn main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let projects = projects_res.unwrap();
|
let projects = projects_res.unwrap();
|
||||||
let _continue = get_user_input("press enter to load command line interface.");
|
let _continue = get_user_input("press enter to load Command Line Interface");
|
||||||
cli::cli(true, projects, config_path, &project_base_folder, &project_base_notes, &tools_folder, box_template, terminal_command, cracking_rig, rockyou, rule, &upcoming_files, &upcoming_notes, &pass_spray_file, fingerprint, vault_name);
|
cli::cli(true, projects, config_path, &project_base_folder, &project_base_notes, &tools_folder, box_template, terminal_command, cracking_rig, rockyou, rule, &upcoming_files, &upcoming_notes, &pass_spray_file, fingerprint, vault_name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::fs::read_to_string;
|
||||||
use std::io::stdin;
|
use std::io::stdin;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -11,12 +12,12 @@ use std::str::FromStr;
|
|||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
|
||||||
use crate::get_user_input;
|
use crate::get_user_input;
|
||||||
|
use crate::open_overwrite;
|
||||||
use crate::tableize;
|
use crate::tableize;
|
||||||
use crate::Project;
|
use crate::Project;
|
||||||
use crate::box_controls::make_box;
|
use crate::box_controls::make_box;
|
||||||
use crate::print_success;
|
use crate::print_success;
|
||||||
use crate::print_error;
|
use crate::print_error;
|
||||||
use crate::print_informational;
|
|
||||||
|
|
||||||
pub fn
|
pub fn
|
||||||
switch_project(projects: &mut Vec<Project>){
|
switch_project(projects: &mut Vec<Project>){
|
||||||
@@ -62,7 +63,7 @@ pub fn save_projects(projects: &Vec<Project>, config_path: &PathBuf){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut save_file = save_file_res.unwrap();
|
let mut save_file = save_file_res.unwrap();
|
||||||
save_file.write_all(b"customer:name:notes:files:active:time:box_name:stage\n").expect("error writing first line to file");
|
save_file.write_all(b"Current Loaded Projects Config File\n").expect("error writing first line to file");
|
||||||
for project in projects{
|
for project in projects{
|
||||||
let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()};
|
let default = format!{"{}:{}:{}:{}:", project.customer, project.project_name, project.notes_folder.display(), project.files_folder.display()};
|
||||||
let mut _outline = String::new();
|
let mut _outline = String::new();
|
||||||
@@ -335,10 +336,12 @@ pub fn get_projects(config_path: &PathBuf, show: bool) -> Option<Vec<Project>>{
|
|||||||
let mut first = 0;
|
let mut first = 0;
|
||||||
let mut already_active = false;
|
let mut already_active = false;
|
||||||
for line in project_lines{
|
for line in project_lines{
|
||||||
|
//println!("{}", line);
|
||||||
first = first + 1;
|
first = first + 1;
|
||||||
if first != 1{
|
if first != 1{
|
||||||
if line.len() > 1{
|
if line.len() > 1{
|
||||||
let settings: Vec<&str> = line.split(":").collect();
|
let settings: Vec<&str> = line.split(":").collect();
|
||||||
|
if settings.len() > 5{
|
||||||
// debug config file...
|
// debug config file...
|
||||||
/*let mut count = 0;
|
/*let mut count = 0;
|
||||||
for settin in &settings{
|
for settin in &settings{
|
||||||
@@ -369,6 +372,7 @@ pub fn get_projects(config_path: &PathBuf, show: bool) -> Option<Vec<Project>>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return Some(projects)
|
return Some(projects)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,3 +500,132 @@ pub fn list_projects(projects: &Vec<Project>){
|
|||||||
tableize(lines);
|
tableize(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn separate_personal_work_projects(config_path: &PathBuf){
|
||||||
|
let mut projects_conf_path = config_path.clone();
|
||||||
|
projects_conf_path.pop();
|
||||||
|
projects_conf_path.push("projects.conf");
|
||||||
|
let mut working_conf_path = config_path.clone();
|
||||||
|
working_conf_path.pop();
|
||||||
|
working_conf_path.push("projects.work");
|
||||||
|
let mut personal_conf_path = config_path.clone();
|
||||||
|
personal_conf_path.pop();
|
||||||
|
personal_conf_path.push("projects.personal");
|
||||||
|
println!("{}", projects_conf_path.display());
|
||||||
|
let project_read_res = read_to_string(&projects_conf_path);
|
||||||
|
if project_read_res.is_err(){
|
||||||
|
print_error("error reading current projects config file!", project_read_res.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let project_string = project_read_res.unwrap();
|
||||||
|
let project_lines: Vec<&str> = project_string.split("\n").collect();
|
||||||
|
let mut personal_projects = Vec::new();
|
||||||
|
let mut work_projects = Vec::new();
|
||||||
|
let mut default = String::new();
|
||||||
|
for line in project_lines{
|
||||||
|
let words: Vec<&str> = line.split(":").collect();
|
||||||
|
if words.len() > 3{
|
||||||
|
if words[0].contains("default"){
|
||||||
|
default = line.to_owned();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
println!("{} {}", words[0], words[1]);
|
||||||
|
if get_user_input("should this project be added to your personal projects config files?").to_lowercase().contains("y"){
|
||||||
|
personal_projects.push(line.to_owned());
|
||||||
|
print_success(format!("{}:{} {}",words[0], words[1], "successfully added to personal config!"));
|
||||||
|
if get_user_input("Do you also want to keep it in your work projects config?").to_lowercase().contains("y"){
|
||||||
|
work_projects.push(line.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
work_projects.push(line.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let work_config_open_res = fs::OpenOptions::new().create(true).write(true).open(working_conf_path);
|
||||||
|
if work_config_open_res.is_err(){
|
||||||
|
print_error("error opening work projects config file!", work_config_open_res.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let person_config_open_res = fs::OpenOptions::new().create(true).write(true).open(personal_conf_path);
|
||||||
|
if person_config_open_res.is_err(){
|
||||||
|
print_error("error opening personal config file!", person_config_open_res.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut work_config_file = work_config_open_res.unwrap();
|
||||||
|
let mut personal_config_file = person_config_open_res.unwrap();
|
||||||
|
let work_write_success = write!(work_config_file, "Work Config File\n");
|
||||||
|
let personal_write_success = write!(personal_config_file, "Personal Config File\n");
|
||||||
|
if work_write_success.is_err(){
|
||||||
|
print_error("error writing to work config file!", work_write_success.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
work_write_success.unwrap();
|
||||||
|
}
|
||||||
|
if personal_write_success.is_err(){
|
||||||
|
print_error("error writing personal config file!", personal_write_success.err().unwrap().to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
personal_write_success.unwrap();
|
||||||
|
}
|
||||||
|
write!(personal_config_file, "{}\n", default).unwrap();
|
||||||
|
write!(work_config_file, "{}\n", default).unwrap();
|
||||||
|
for project in work_projects{
|
||||||
|
write!(work_config_file, "{}\n", project).unwrap();
|
||||||
|
}
|
||||||
|
for project in personal_projects{
|
||||||
|
write!(personal_config_file, "{}\n", project).unwrap();
|
||||||
|
}
|
||||||
|
print_success("projects separated successfully!");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn swith_to_personal(config: &PathBuf) -> Option<Vec<Project>>{
|
||||||
|
let mut projects_path = config.clone();
|
||||||
|
projects_path.pop();
|
||||||
|
let mut personal_projects = config.clone();
|
||||||
|
personal_projects.pop();
|
||||||
|
projects_path.push("projects.conf");
|
||||||
|
personal_projects.push("projects.personal");
|
||||||
|
let personal_projects_read_res = read_to_string(&personal_projects);
|
||||||
|
if personal_projects_read_res.is_err(){
|
||||||
|
print_error("error reading personal projects!", personal_projects_read_res.err().unwrap().to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let person_projects_string = personal_projects_read_res.unwrap();
|
||||||
|
let open_res = open_overwrite(&projects_path);
|
||||||
|
if open_res.is_none(){
|
||||||
|
print_error("error opening projects.conf file!", "".to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut project_conf = open_res.unwrap();
|
||||||
|
write!(project_conf, "{}", person_projects_string).unwrap();
|
||||||
|
let new_projects = get_projects(config, true);
|
||||||
|
return new_projects;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn swith_to_work(config: &PathBuf) -> Option<Vec<Project>>{
|
||||||
|
let mut projects_path = config.clone();
|
||||||
|
projects_path.pop();
|
||||||
|
let mut work_projects = config.clone();
|
||||||
|
work_projects.pop();
|
||||||
|
projects_path.push("projects.conf");
|
||||||
|
work_projects.push("projects.work");
|
||||||
|
let work_projects_read_res = read_to_string(work_projects);
|
||||||
|
if work_projects_read_res.is_err(){
|
||||||
|
print_error("error reading personal projects!", work_projects_read_res.err().unwrap().to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let work_projects_string = work_projects_read_res.unwrap();
|
||||||
|
let open_res = open_overwrite(&projects_path);
|
||||||
|
if open_res.is_none(){
|
||||||
|
print_error("", "error opening projects.conf file!".to_string());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut project_conf = open_res.unwrap();
|
||||||
|
write!(project_conf, "{}", work_projects_string).unwrap();
|
||||||
|
let new_projects = get_projects(config, true);
|
||||||
|
return new_projects;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user