Compare commits
8 Commits
json-featu
...
0.3.0
Author | SHA1 | Date | |
---|---|---|---|
02c62b7ba6 | |||
8e85ceebaf | |||
aa80bc0cc7 | |||
fe1334d97f | |||
808c6a526c | |||
982452cb5b | |||
888fd3a8bd | |||
51856d1108 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
.vscode/
|
.vscode/
|
||||||
config.json
|
config.json
|
||||||
Cargo.lock
|
.idea/
|
||||||
|
1459
Cargo.lock
generated
Normal file
1459
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "gt"
|
name = "gt"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
authors = ["Wyatt J. Miller <wjmiller2016@gmail.com>"]
|
authors = ["Wyatt J. Miller <wjmiller2016@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "A Gitea CLI client"
|
description = "A Gitea CLI client"
|
||||||
@ -11,6 +11,7 @@ license-file = "LICENSE"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
base64 = "0.22.1"
|
||||||
clap = "2.33.1"
|
clap = "2.33.1"
|
||||||
colored = "2.0.0"
|
colored = "2.0.0"
|
||||||
config = "0.11.0"
|
config = "0.11.0"
|
||||||
|
61
flake.lock
generated
Normal file
61
flake.lock
generated
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-schemas": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1721999734,
|
||||||
|
"narHash": "sha256-G5CxYeJVm4lcEtaO87LKzOsVnWeTcHGKbKxNamNWgOw=",
|
||||||
|
"rev": "0a5c42297d870156d9c57d8f99e476b738dcd982",
|
||||||
|
"revCount": 75,
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/flake-schemas/0.1.5/0190ef2f-61e0-794b-ba14-e82f225e55e6/source.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://flakehub.com/f/DeterminateSystems/flake-schemas/%2A.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1722372011,
|
||||||
|
"narHash": "sha256-B2xRiC3NEJy/82ugtareBkRqEkPGpMyjaLxaR8LBxNs=",
|
||||||
|
"rev": "cf05eeada35e122770c5c14add958790fcfcbef5",
|
||||||
|
"revCount": 633614,
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2405.633614%2Brev-cf05eeada35e122770c5c14add958790fcfcbef5/01910e77-e048-77f4-b2d4-a69cacb697db/source.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://flakehub.com/f/NixOS/nixpkgs/%2A.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-schemas": "flake-schemas",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"rust-overlay": "rust-overlay"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1722548948,
|
||||||
|
"narHash": "sha256-ddR/6wbOzRXijcOAEgeaIlbskky51eJdZhYPwoErs3s=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "0b973d3e54e497e518515c05a6e99ec6c03be2ce",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
61
flake.nix
Normal file
61
flake.nix
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# This flake was initially generated by fh, the CLI for FlakeHub (version 0.1.10)
|
||||||
|
{
|
||||||
|
# A helpful description of your flake
|
||||||
|
description = "A Gitea command line application";
|
||||||
|
|
||||||
|
# Flake inputs
|
||||||
|
inputs = {
|
||||||
|
flake-schemas.url = "https://flakehub.com/f/DeterminateSystems/flake-schemas/*.tar.gz";
|
||||||
|
|
||||||
|
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/*.tar.gz";
|
||||||
|
|
||||||
|
rust-overlay = {
|
||||||
|
url = "github:oxalica/rust-overlay";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Flake outputs that other flakes can use
|
||||||
|
outputs = { self, flake-schemas, nixpkgs, rust-overlay }:
|
||||||
|
let
|
||||||
|
# Nixpkgs overlays
|
||||||
|
overlays = [
|
||||||
|
rust-overlay.overlays.default
|
||||||
|
(final: prev: {
|
||||||
|
rustToolchain = final.rust-bin.stable.latest.default.override { extensions = [ "rust-src"]; };
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
# Helpers for producing system-specific outputs
|
||||||
|
supportedSystems = [ "x86_64-linux" "aarch64-darwin" "x86_64-darwin" "aarch64-linux" ];
|
||||||
|
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
|
||||||
|
pkgs = import nixpkgs { inherit overlays system; };
|
||||||
|
});
|
||||||
|
in {
|
||||||
|
# Schemas tell Nix about the structure of your flake's outputs
|
||||||
|
schemas = flake-schemas.schemas;
|
||||||
|
|
||||||
|
# Development environments
|
||||||
|
devShells = forEachSupportedSystem ({ pkgs }: {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
# Pinned packages available in the environment
|
||||||
|
packages = with pkgs; [
|
||||||
|
rustToolchain
|
||||||
|
rust-analyzer
|
||||||
|
curl
|
||||||
|
git
|
||||||
|
jq
|
||||||
|
wget
|
||||||
|
nixpkgs-fmt
|
||||||
|
openssl
|
||||||
|
];
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
env = {
|
||||||
|
RUST_BACKTRACE = "1";
|
||||||
|
RUST_SRC_PATH = "${pkgs.rustToolchain}/lib/rustlib/src/rust/library";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
7
rust-analyzer.json
Normal file
7
rust-analyzer.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"rust-analyzer": {
|
||||||
|
"files": {
|
||||||
|
"excludeDirs": [".direnv"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,6 @@ pub fn get_args() -> ArgMatches<'static> {
|
|||||||
.version("0.0.2")
|
.version("0.0.2")
|
||||||
.author("Wyatt J. Miller <wjmiller2016@gmail.com>")
|
.author("Wyatt J. Miller <wjmiller2016@gmail.com>")
|
||||||
.about("It's a Gitea CLI client!")
|
.about("It's a Gitea CLI client!")
|
||||||
.arg(Arg::with_name("--json").help("Print out results in JSON"))
|
|
||||||
.subcommand(SubCommand::with_name("repo")
|
.subcommand(SubCommand::with_name("repo")
|
||||||
.about("Create, delete, list, search, or fork a repository")
|
.about("Create, delete, list, search, or fork a repository")
|
||||||
.arg(Arg::with_name("create")
|
.arg(Arg::with_name("create")
|
||||||
|
43
src/error.rs
Normal file
43
src/error.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ErrorKind {
|
||||||
|
BadRequest(String),
|
||||||
|
Conflict(String),
|
||||||
|
ForbiddenRequest(String),
|
||||||
|
NotFound(String),
|
||||||
|
UnprocessiableRequest(String),
|
||||||
|
JsonError(String),
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ErrorKind {}
|
||||||
|
|
||||||
|
impl fmt::Display for ErrorKind {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
ErrorKind::BadRequest(message) => {
|
||||||
|
write!(f, "Client error - please try again! {}", message)
|
||||||
|
}
|
||||||
|
ErrorKind::Conflict(message) => {
|
||||||
|
write!(f, "Client error - task is already underway! {}", message)
|
||||||
|
}
|
||||||
|
ErrorKind::ForbiddenRequest(message) => write!(
|
||||||
|
f,
|
||||||
|
"Client error - unauthorized. Please try again! {}",
|
||||||
|
message
|
||||||
|
),
|
||||||
|
ErrorKind::NotFound(message) => write!(f, "Client error - not found! {}", message),
|
||||||
|
ErrorKind::UnprocessiableRequest(message) => write!(
|
||||||
|
f,
|
||||||
|
"Client error - the request can't be processed. Please try again! {}",
|
||||||
|
message
|
||||||
|
),
|
||||||
|
ErrorKind::JsonError(message) => {
|
||||||
|
write!(f, "Client error - can't parse command! {}", message)
|
||||||
|
}
|
||||||
|
ErrorKind::Other => write!(f, "Other error that I did not anticipate"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
83
src/issue.rs
83
src/issue.rs
@ -2,11 +2,12 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use colored::*;
|
use colored::*;
|
||||||
use reqwest::blocking::Client;
|
use reqwest::blocking::Client;
|
||||||
use reqwest::{StatusCode, Response};
|
use reqwest::{Response, StatusCode};
|
||||||
use serde_derive::{Serialize, Deserialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::request::{Request, Authentication, AuthenticationType};
|
use crate::error;
|
||||||
|
use crate::request::{AuthenticationType, Request};
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
|
||||||
pub struct Issue;
|
pub struct Issue;
|
||||||
@ -44,6 +45,12 @@ pub struct IssueResponse {
|
|||||||
pub repository: Repository,
|
pub repository: Repository,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct IssueErrorResponse {
|
||||||
|
pub message: String,
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
@ -67,24 +74,12 @@ pub struct Repository {
|
|||||||
pub full_name: String,
|
pub full_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// trait IssueRequest {
|
|
||||||
// fn client() -> &'static Client;
|
|
||||||
// fn url_request_decision() -> String;
|
|
||||||
// fn arg_value_decision() -> Vec<&'static str>;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl IssueRequest for Issue {
|
|
||||||
// fn client() -> &'static Client {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl Issue {
|
impl Issue {
|
||||||
pub fn new() -> Issue {
|
pub fn new() -> Issue {
|
||||||
Issue {}
|
Issue {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_issue(&self, request: &Request) {
|
pub fn create_issue(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
let issue_title: String;
|
let issue_title: String;
|
||||||
let issue_description: String;
|
let issue_description: String;
|
||||||
let _issue_assignee: Option<String>;
|
let _issue_assignee: Option<String>;
|
||||||
@ -119,51 +114,60 @@ impl Issue {
|
|||||||
let response = client.post(&url).json(&map).send();
|
let response = client.post(&url).json(&map).send();
|
||||||
|
|
||||||
match response {
|
match response {
|
||||||
Ok(repo) => {
|
Ok(repo) => match repo.status() {
|
||||||
match repo.status() {
|
StatusCode::CREATED => println!("{}", "Issue successfully created!".green()),
|
||||||
StatusCode::CREATED => println!("{}", "Issue successfully created!".green()),
|
StatusCode::FORBIDDEN => println!("{}", "Issue creation forbidden!".red()),
|
||||||
StatusCode::FORBIDDEN => println!("{}", "Issue creation forbidden!".red()),
|
StatusCode::UNPROCESSABLE_ENTITY => {
|
||||||
StatusCode::UNPROCESSABLE_ENTITY => println!("{}", "Issue input validation failed!".red()),
|
println!("{}", "Issue input validation failed!".red())
|
||||||
_ => println!(),
|
|
||||||
}
|
}
|
||||||
|
_ => println!(),
|
||||||
},
|
},
|
||||||
Err(e) => panic!("{}", e),
|
Err(e) => panic!("{}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_issue(&self, request: &Request) {
|
pub fn list_issue(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
let client = &request.client;
|
let client = &request.client;
|
||||||
let url = self.url_request_decision(&request);
|
let url = self.url_request_decision(&request);
|
||||||
let response = client.get(&url).send();
|
let response = client.get(&url).send();
|
||||||
|
|
||||||
// TODO: fix this to match context
|
// TODO: fix this to match context
|
||||||
match response {
|
match response {
|
||||||
Ok(repo) => {
|
Ok(repo) => match repo.status() {
|
||||||
match repo.status() {
|
StatusCode::CREATED => {
|
||||||
StatusCode::CREATED => println!("{}", "Issue successfully created!".green()),
|
println!("{}", "Issue successfully created!".green());
|
||||||
StatusCode::FORBIDDEN => println!("{}", "Issue creation forbidden!".red()),
|
Ok(())
|
||||||
StatusCode::UNPROCESSABLE_ENTITY => println!("{}", "Issue input validation failed!".red()),
|
|
||||||
_ => println!(),
|
|
||||||
}
|
}
|
||||||
|
StatusCode::FORBIDDEN => {
|
||||||
|
let deserialized = repo.json().unwrap();
|
||||||
|
Err(error::ErrorKind::ForbiddenRequest(deserialized.message))
|
||||||
|
}
|
||||||
|
StatusCode::UNPROCESSABLE_ENTITY => {
|
||||||
|
let deserialized = repo.json().unwrap();
|
||||||
|
Err(error::ErrorKind::UnprocessiableRequest(
|
||||||
|
deserialized.message,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => Err(error::ErrorKind::Other),
|
||||||
},
|
},
|
||||||
Err(e) => panic!("{}", e),
|
Err(e) => panic!("{}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search_issue(&self, request: &Request) {
|
pub fn search_issue(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
let client = &request.client;
|
let client = &request.client;
|
||||||
let url = self.url_request_decision(&request);
|
let url = self.url_request_decision(&request);
|
||||||
let response = client.get(&url).send();
|
let response = client.get(&url).send();
|
||||||
|
|
||||||
// TODO: fix this to match context
|
// TODO: fix this to match context
|
||||||
match response {
|
match response {
|
||||||
Ok(repo) => {
|
Ok(repo) => match repo.status() {
|
||||||
match repo.status() {
|
StatusCode::CREATED => println!("{}", "Issue successfully created!".green()),
|
||||||
StatusCode::CREATED => println!("{}", "Issue successfully created!".green()),
|
StatusCode::FORBIDDEN => println!("{}", "Issue creation forbidden!".red()),
|
||||||
StatusCode::FORBIDDEN => println!("{}", "Issue creation forbidden!".red()),
|
StatusCode::UNPROCESSABLE_ENTITY => {
|
||||||
StatusCode::UNPROCESSABLE_ENTITY => println!("{}", "Issue input validation failed!".red()),
|
println!("{}", "Issue input validation failed!".red())
|
||||||
_ => println!(),
|
|
||||||
}
|
}
|
||||||
|
_ => println!(),
|
||||||
},
|
},
|
||||||
Err(e) => panic!("{}", e),
|
Err(e) => panic!("{}", e),
|
||||||
}
|
}
|
||||||
@ -190,7 +194,7 @@ impl Issue {
|
|||||||
repo = arg_value[1],
|
repo = arg_value[1],
|
||||||
api_token = request.authentication.credentials.1.as_ref().unwrap()
|
api_token = request.authentication.credentials.1.as_ref().unwrap()
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
AuthenticationType::BasicAuth => {
|
AuthenticationType::BasicAuth => {
|
||||||
format!(
|
format!(
|
||||||
"{request}/repos/{owner}/{repo}/issues?token={api_token}",
|
"{request}/repos/{owner}/{repo}/issues?token={api_token}",
|
||||||
@ -199,10 +203,9 @@ impl Issue {
|
|||||||
repo = arg_value[1],
|
repo = arg_value[1],
|
||||||
api_token = request.authentication.credentials.1.as_ref().unwrap()
|
api_token = request.authentication.credentials.1.as_ref().unwrap()
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
// this case _shouldn't_ happen but ya know
|
// this case _shouldn't_ happen but ya know
|
||||||
AuthenticationType::None => panic!("idk what happened man you wrote the code 🤷")
|
AuthenticationType::None => panic!("idk what happened man you wrote the code 🤷"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
23
src/main.rs
23
src/main.rs
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
mod arg;
|
mod arg;
|
||||||
mod config;
|
mod config;
|
||||||
|
mod error;
|
||||||
mod generate;
|
mod generate;
|
||||||
mod issue;
|
mod issue;
|
||||||
mod pr;
|
mod pr;
|
||||||
@ -28,7 +29,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let auth = request::Authentication::new(&config);
|
let auth = request::Authentication::new(&config);
|
||||||
let request = auth.request_chooser(config.clone(), matches);
|
let request = auth.request_chooser(config.clone(), &matches); // TODO: get rid of the clone
|
||||||
|
|
||||||
match request.arg_value.subcommand() {
|
match request.arg_value.subcommand() {
|
||||||
("", None) => println!("No subcommand was given!"),
|
("", None) => println!("No subcommand was given!"),
|
||||||
@ -76,6 +77,26 @@ fn main() {
|
|||||||
issue.create_issue(&request);
|
issue.create_issue(&request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
("user", Some(user_matches)) => {
|
||||||
|
let user = user::User::new();
|
||||||
|
|
||||||
|
// TODO: match expression should be here
|
||||||
|
if user_matches.is_present("create") {
|
||||||
|
user.create_user(&request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if user_matches.is_present("list") {
|
||||||
|
user.list_user(&request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if user_matches.is_present("search") {
|
||||||
|
user.search_user(&request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if user_matches.is_present("delete") {
|
||||||
|
user.delete_user(&request);
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => println!("Huh?"),
|
_ => println!("Huh?"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
92
src/repo.rs
92
src/repo.rs
@ -1,18 +1,16 @@
|
|||||||
use std::{
|
use std::{collections::HashMap, path::Path};
|
||||||
collections::HashMap,
|
|
||||||
file,
|
|
||||||
path::{self, Path},
|
|
||||||
};
|
|
||||||
|
|
||||||
use colored::*;
|
use colored::*;
|
||||||
use git2::{
|
use git2::{build::RepoBuilder, Cred, CredentialType, RemoteCallbacks};
|
||||||
build::RepoBuilder, Cred, CredentialType, Credentials, FetchOptions, RemoteCallbacks,
|
|
||||||
Repository as Repo,
|
|
||||||
};
|
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{config::Configuration, request::Request};
|
use crate::{
|
||||||
|
config::Configuration,
|
||||||
|
error,
|
||||||
|
request::Request,
|
||||||
|
util::{self, ErrorKind},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Repository;
|
pub struct Repository;
|
||||||
|
|
||||||
@ -65,6 +63,12 @@ pub struct RepositoryResponse {
|
|||||||
pub website: String,
|
pub website: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct RepositoryErrorResponse {
|
||||||
|
pub message: String,
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct ExternalTracker {
|
pub struct ExternalTracker {
|
||||||
pub external_tracker_format: String,
|
pub external_tracker_format: String,
|
||||||
@ -109,7 +113,7 @@ impl Repository {
|
|||||||
Repository {}
|
Repository {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_repo(&self, request: &Request) {
|
pub fn create_repo(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
let client = &request.client;
|
let client = &request.client;
|
||||||
let arg_value = request
|
let arg_value = request
|
||||||
.arg_value
|
.arg_value
|
||||||
@ -124,7 +128,6 @@ impl Repository {
|
|||||||
request = request.url.as_ref().unwrap(),
|
request = request.url.as_ref().unwrap(),
|
||||||
api_token = request.authentication.credentials.1.as_ref().unwrap()
|
api_token = request.authentication.credentials.1.as_ref().unwrap()
|
||||||
);
|
);
|
||||||
let is_json = request.is_json;
|
|
||||||
|
|
||||||
map.insert("name", arg_value);
|
map.insert("name", arg_value);
|
||||||
map.insert("readme", arg_value);
|
map.insert("readme", arg_value);
|
||||||
@ -135,30 +138,34 @@ impl Repository {
|
|||||||
match response {
|
match response {
|
||||||
Ok(repo) => match repo.status() {
|
Ok(repo) => match repo.status() {
|
||||||
StatusCode::CREATED => {
|
StatusCode::CREATED => {
|
||||||
if is_json {
|
// TODO: implement error handling for the deserialization
|
||||||
println!("{}", repo)
|
|
||||||
}
|
|
||||||
let deserialized: RepositoryResponse = repo.json().unwrap();
|
let deserialized: RepositoryResponse = repo.json().unwrap();
|
||||||
println!("{}", "Repository successfully created!".green());
|
println!("{}", "Repository successfully created!".green());
|
||||||
println!("\tRepository name: {:0}\n\tRepository owner: {:1}\n\tRepository description: {:2}", deserialized.name, deserialized.owner.unwrap().full_name, deserialized.description);
|
println!("\tRepository name: {:0}\n\tRepository owner: {:1}\n\tRepository description: {:2}", deserialized.name, deserialized.owner.unwrap().full_name, deserialized.description);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
StatusCode::BAD_REQUEST => {
|
||||||
|
// TODO: implement error handling for the deserialization
|
||||||
|
let deserialized: RepositoryErrorResponse = repo.json().unwrap();
|
||||||
|
Err(error::ErrorKind::BadRequest(deserialized.message))
|
||||||
|
}
|
||||||
|
StatusCode::CONFLICT => {
|
||||||
|
let deserialized: RepositoryErrorResponse = repo.json().unwrap();
|
||||||
|
Err(error::ErrorKind::Conflict(deserialized.message))
|
||||||
}
|
}
|
||||||
StatusCode::CONFLICT => println!("{}", "Repository already exists!".red()),
|
|
||||||
StatusCode::UNPROCESSABLE_ENTITY => {
|
StatusCode::UNPROCESSABLE_ENTITY => {
|
||||||
println!("{}", "Repository input validation failed!".red())
|
let deserialized: RepositoryErrorResponse = repo.json().unwrap();
|
||||||
|
Err(error::ErrorKind::UnprocessiableRequest(
|
||||||
|
deserialized.message,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
_ => println!(
|
_ => Err(error::ErrorKind::Other),
|
||||||
"Repository creation failed! HTTP status code: {}",
|
|
||||||
repo.status().as_str()
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
Err(e) => panic!("{}", e),
|
Err(_e) => Err(error::ErrorKind::Other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_repo(&self, request: &Request) {
|
pub fn delete_repo(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
if (request.is_json) {
|
|
||||||
println!("uh oh json"); // TODO: fix me, replace line with util::bad_response_message
|
|
||||||
}
|
|
||||||
let client = &request.client;
|
let client = &request.client;
|
||||||
let arg_value: Vec<&str> = request
|
let arg_value: Vec<&str> = request
|
||||||
.arg_value
|
.arg_value
|
||||||
@ -183,7 +190,10 @@ impl Repository {
|
|||||||
StatusCode::NO_CONTENT => {
|
StatusCode::NO_CONTENT => {
|
||||||
println!("{}", "Respository successfully deleted!".green())
|
println!("{}", "Respository successfully deleted!".green())
|
||||||
}
|
}
|
||||||
StatusCode::FORBIDDEN => println!("{}", "Repository deletion forbidden!".red()),
|
StatusCode::FORBIDDEN => println!(
|
||||||
|
"{}",
|
||||||
|
"Unable to authorize deletion. Please report this to the webmaster!".red()
|
||||||
|
),
|
||||||
_ => println!(
|
_ => println!(
|
||||||
"Repository deletion failed! Does the repository exist? HTTP status code: {}",
|
"Repository deletion failed! Does the repository exist? HTTP status code: {}",
|
||||||
repo.status().as_str()
|
repo.status().as_str()
|
||||||
@ -193,7 +203,7 @@ impl Repository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fork_repo(&self, request: &Request) {
|
pub fn fork_repo(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
let client = &request.client;
|
let client = &request.client;
|
||||||
let arg_item: Vec<&str> = request
|
let arg_item: Vec<&str> = request
|
||||||
.arg_value
|
.arg_value
|
||||||
@ -207,6 +217,7 @@ impl Repository {
|
|||||||
let mut map: HashMap<&str, &str> = HashMap::new();
|
let mut map: HashMap<&str, &str> = HashMap::new();
|
||||||
let user = request.authentication.credentials.0.as_ref().unwrap();
|
let user = request.authentication.credentials.0.as_ref().unwrap();
|
||||||
|
|
||||||
|
// TODO: use new url formatter
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{request}/repos/{owner}/{repo}/forks?token={api_token}",
|
"{request}/repos/{owner}/{repo}/forks?token={api_token}",
|
||||||
request = request.url.as_ref().unwrap(),
|
request = request.url.as_ref().unwrap(),
|
||||||
@ -222,9 +233,6 @@ impl Repository {
|
|||||||
match response {
|
match response {
|
||||||
Ok(repo) => match repo.status() {
|
Ok(repo) => match repo.status() {
|
||||||
StatusCode::ACCEPTED => {
|
StatusCode::ACCEPTED => {
|
||||||
if (request.is_json) {
|
|
||||||
println!("{}", repo)
|
|
||||||
}
|
|
||||||
let deserialized: RepositoryResponse = repo.json().unwrap();
|
let deserialized: RepositoryResponse = repo.json().unwrap();
|
||||||
println!("{}", "Repository forked successfully".green());
|
println!("{}", "Repository forked successfully".green());
|
||||||
println!("\tOriginal repository name: {:0?}\n\tOriginal repository owner: {:1?}\n\tForked repository name: {:2?}\n\tForked repository owner: {:3?}", deserialized.name, arg_item[0], deserialized.name, deserialized.owner.unwrap().full_name);
|
println!("\tOriginal repository name: {:0?}\n\tOriginal repository owner: {:1?}\n\tForked repository name: {:2?}\n\tForked repository owner: {:3?}", deserialized.name, arg_item[0], deserialized.name, deserialized.owner.unwrap().full_name);
|
||||||
@ -232,7 +240,10 @@ impl Repository {
|
|||||||
StatusCode::INTERNAL_SERVER_ERROR => {
|
StatusCode::INTERNAL_SERVER_ERROR => {
|
||||||
println!("{}", "Repository already forked!".red())
|
println!("{}", "Repository already forked!".red())
|
||||||
}
|
}
|
||||||
StatusCode::FORBIDDEN => println!("{}", "Repository fork forbidden!".red()),
|
StatusCode::FORBIDDEN => println!(
|
||||||
|
"{}",
|
||||||
|
"Unable to authorize fork. Please report this to the webmaster!".red()
|
||||||
|
),
|
||||||
StatusCode::UNPROCESSABLE_ENTITY => {
|
StatusCode::UNPROCESSABLE_ENTITY => {
|
||||||
println!("{}", "Repository fork input validation failed!".red())
|
println!("{}", "Repository fork input validation failed!".red())
|
||||||
}
|
}
|
||||||
@ -246,7 +257,7 @@ impl Repository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search_repo(&self, request: &Request) {
|
pub fn search_repo(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
let client = &request.client;
|
let client = &request.client;
|
||||||
let arg_value = request
|
let arg_value = request
|
||||||
.arg_value
|
.arg_value
|
||||||
@ -255,6 +266,7 @@ impl Repository {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.value_of("search")
|
.value_of("search")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
// TODO: use new url formatter
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{request}/repos/search?q={query}&token={api_token}",
|
"{request}/repos/search?q={query}&token={api_token}",
|
||||||
request = request.url.as_ref().unwrap(),
|
request = request.url.as_ref().unwrap(),
|
||||||
@ -267,9 +279,6 @@ impl Repository {
|
|||||||
match response {
|
match response {
|
||||||
Ok(repo) => match repo.status() {
|
Ok(repo) => match repo.status() {
|
||||||
StatusCode::OK => {
|
StatusCode::OK => {
|
||||||
if (request.is_json) {
|
|
||||||
println!("{}", repo)
|
|
||||||
}
|
|
||||||
let deserialized: MultipleRepositories = repo.json().unwrap();
|
let deserialized: MultipleRepositories = repo.json().unwrap();
|
||||||
|
|
||||||
match deserialized.data.len() != 0 {
|
match deserialized.data.len() != 0 {
|
||||||
@ -301,7 +310,7 @@ impl Repository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_repo(&self, request: &Request) {
|
pub fn list_repo(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
let client = &request.client;
|
let client = &request.client;
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{request}/repos/search?token={api_token}",
|
"{request}/repos/search?token={api_token}",
|
||||||
@ -314,9 +323,6 @@ impl Repository {
|
|||||||
match response {
|
match response {
|
||||||
Ok(repo) => match repo.status() {
|
Ok(repo) => match repo.status() {
|
||||||
StatusCode::OK => {
|
StatusCode::OK => {
|
||||||
if (request.is_json) {
|
|
||||||
println!("{}", repo)
|
|
||||||
}
|
|
||||||
let deserialized: MultipleRepositories = repo.json().unwrap();
|
let deserialized: MultipleRepositories = repo.json().unwrap();
|
||||||
|
|
||||||
match deserialized.data.len() != 0 {
|
match deserialized.data.len() != 0 {
|
||||||
@ -415,3 +421,9 @@ impl Repository {
|
|||||||
|
|
||||||
pub fn create_commit(&self, request: &Request, config: Configuration) {}
|
pub fn create_commit(&self, request: &Request, config: Configuration) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Repository {
|
||||||
|
fn default() -> Self {
|
||||||
|
Repository::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,9 +1,18 @@
|
|||||||
use std::{collections::HashMap, process};
|
use std::{collections::HashMap, process, string::String};
|
||||||
|
|
||||||
|
use base64::{engine::general_purpose::URL_SAFE, Engine as _};
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use reqwest::blocking::Client;
|
use reqwest::blocking::Client;
|
||||||
|
|
||||||
use crate::config::Configuration;
|
use crate::config::Configuration;
|
||||||
|
use crate::util;
|
||||||
|
|
||||||
|
pub enum RequestType {
|
||||||
|
Repository,
|
||||||
|
Issue,
|
||||||
|
PullRequest,
|
||||||
|
User,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum AuthenticationType {
|
pub enum AuthenticationType {
|
||||||
BasicAuth,
|
BasicAuth,
|
||||||
@ -11,13 +20,14 @@ pub enum AuthenticationType {
|
|||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive()]
|
||||||
pub struct Request<'a> {
|
pub struct Request<'a> {
|
||||||
pub client: Client,
|
pub client: Client,
|
||||||
pub arg_value: ArgMatches<'a>,
|
pub arg_value: &'a ArgMatches<'a>,
|
||||||
pub map: HashMap<String, String>,
|
pub map: HashMap<String, String>,
|
||||||
pub url: Option<String>,
|
pub url: Option<String>,
|
||||||
pub authentication: Authentication,
|
pub authentication: Authentication,
|
||||||
pub is_json: bool,
|
pub request_type: RequestType,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Authentication {
|
pub struct Authentication {
|
||||||
@ -31,34 +41,49 @@ impl<'a> Request<'a> {
|
|||||||
/// Public constructor for a request with a simple username and password
|
/// Public constructor for a request with a simple username and password
|
||||||
pub fn with_basic_request(
|
pub fn with_basic_request(
|
||||||
config: Configuration,
|
config: Configuration,
|
||||||
arg: ArgMatches,
|
arg: &'a ArgMatches,
|
||||||
auth: Authentication,
|
auth: Authentication,
|
||||||
) -> Request {
|
) -> Request<'a> {
|
||||||
Request {
|
Request {
|
||||||
client: Client::new(),
|
client: Client::new(),
|
||||||
arg_value: arg,
|
arg_value: &arg,
|
||||||
map: HashMap::new(),
|
map: HashMap::new(),
|
||||||
url: Some(format!("{}{}", config.base_url, config.base_api)),
|
url: Some(format!("{}{}", config.base_url, config.base_api)),
|
||||||
authentication: auth,
|
authentication: auth,
|
||||||
is_json: arg.is_present("--json"),
|
request_type: util::get_request_type(&arg).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Public constructor for a request with an API token
|
/// Public constructor for a request with an API token
|
||||||
pub fn with_api_request(
|
pub fn with_api_request(
|
||||||
config: Configuration,
|
config: Configuration,
|
||||||
arg: ArgMatches,
|
arg: &'a ArgMatches,
|
||||||
auth: Authentication,
|
auth: Authentication,
|
||||||
) -> Request {
|
) -> Request<'a> {
|
||||||
Request {
|
Request {
|
||||||
client: Client::new(),
|
client: Client::new(),
|
||||||
arg_value: arg,
|
arg_value: &arg,
|
||||||
map: HashMap::new(),
|
map: HashMap::new(),
|
||||||
url: Some(format!("{}{}", config.base_url, config.base_api)),
|
url: Some(format!("{}{}", config.base_url, config.base_api)),
|
||||||
authentication: auth,
|
authentication: auth,
|
||||||
is_json: arg.is_present("--json"),
|
request_type: util::get_request_type(&arg).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn auth_type(&self) -> String {
|
||||||
|
let key: &String = self.authentication.credentials.1.as_ref().unwrap();
|
||||||
|
match self.authentication.auth_type {
|
||||||
|
AuthenticationType::BasicAuth => URL_SAFE.encode(key),
|
||||||
|
AuthenticationType::ApiToken => key.to_string(),
|
||||||
|
AuthenticationType::None => {
|
||||||
|
// TODO: make a custom error and error here instead of panicing
|
||||||
|
// this shouldn't happen, ever
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn url_builder(&self) -> String {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Authentication {
|
impl Authentication {
|
||||||
@ -117,14 +142,22 @@ impl Authentication {
|
|||||||
/// Public method that based on the what kind of authentication is being used, it can
|
/// Public method that based on the what kind of authentication is being used, it can
|
||||||
/// determine what kind of requesting method is going to be used. See the Request
|
/// determine what kind of requesting method is going to be used. See the Request
|
||||||
/// structure for more details.
|
/// structure for more details.
|
||||||
pub fn request_chooser(self, config: Configuration, arg: ArgMatches<'static>) -> Request {
|
pub fn request_chooser<'a>(
|
||||||
|
self,
|
||||||
|
config: Configuration,
|
||||||
|
arg: &'a ArgMatches<'static>,
|
||||||
|
) -> Request<'a> {
|
||||||
if let true = self.api_token {
|
if let true = self.api_token {
|
||||||
Request::with_api_request(config, arg.to_owned(), self)
|
Request::with_api_request(config, &arg, self)
|
||||||
} else {
|
} else {
|
||||||
match self.basic {
|
match self.basic {
|
||||||
true => Request::with_basic_request(config, arg.to_owned(), self),
|
true => Request::with_basic_request(config, &arg, self),
|
||||||
false => panic!(),
|
false => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Authentication {
|
||||||
|
fn default() -> Self {}
|
||||||
|
}
|
||||||
|
184
src/user.rs
184
src/user.rs
@ -1,11 +1,18 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{request::Request, util};
|
use crate::{
|
||||||
|
error,
|
||||||
|
request::Request,
|
||||||
|
util::{self, ErrorKind},
|
||||||
|
};
|
||||||
|
use colored::*;
|
||||||
|
use reqwest::StatusCode;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub struct User;
|
pub struct User;
|
||||||
|
|
||||||
pub struct MutlipleUsers {
|
#[derive(Deserialize)]
|
||||||
|
pub struct MultipleUsers {
|
||||||
pub data: Vec<UserResponse>,
|
pub data: Vec<UserResponse>,
|
||||||
pub ok: bool,
|
pub ok: bool,
|
||||||
}
|
}
|
||||||
@ -29,33 +36,180 @@ pub struct UserResponse {
|
|||||||
pub restricted: bool,
|
pub restricted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct UserErrorResponse {
|
||||||
|
pub message: String,
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
pub fn new() -> User {
|
pub fn new() -> User {
|
||||||
User {}
|
User {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_user(request: &Request) {
|
pub fn create_user(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
let client = &request.client;
|
let client = &request.client;
|
||||||
let arg_value = &request
|
let mut user_create_input: HashMap<String, String> = HashMap::new();
|
||||||
|
let url = format!(
|
||||||
|
"{request}/admin/users?token={api_token}",
|
||||||
|
request = request.url.as_ref().unwrap(),
|
||||||
|
api_token = request.authentication.credentials.1.as_ref().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let username = util::get_input(String::from("Please enter a username:"));
|
||||||
|
let email = util::get_input(String::from("Please enter a email address:"));
|
||||||
|
let password = util::get_input(String::from("Please enter a password:"));
|
||||||
|
|
||||||
|
user_create_input.insert("login".to_string(), username);
|
||||||
|
user_create_input.insert("email".to_string(), email);
|
||||||
|
user_create_input.insert("password".to_string(), password);
|
||||||
|
|
||||||
|
let response = client.post(url.as_str()).json(&user_create_input).send();
|
||||||
|
// TODO: match return type
|
||||||
|
match response {
|
||||||
|
Ok(repo) => match repo.status() {
|
||||||
|
StatusCode::CREATED => {
|
||||||
|
let deserialized: UserResponse = repo.json().unwrap();
|
||||||
|
println!("{}", "User successfully created!".green());
|
||||||
|
println!(
|
||||||
|
"\tFull Name: {:0}\n\tUsername: {:1}\n\tEmail: {:2}\n",
|
||||||
|
deserialized.full_name, deserialized.login, deserialized.email
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
StatusCode::BAD_REQUEST => {
|
||||||
|
let deserialized: UserErrorResponse = repo.json().unwrap();
|
||||||
|
Err(error::ErrorKind::BadRequest(deserialized.message))
|
||||||
|
}
|
||||||
|
StatusCode::FORBIDDEN => {
|
||||||
|
let deserialized: UserErrorResponse = repo.json().unwrap();
|
||||||
|
Err(error::ErrorKind::ForbiddenRequest(deserialized.message))
|
||||||
|
}
|
||||||
|
_ => Err(error::ErrorKind::Other),
|
||||||
|
},
|
||||||
|
Err(_e) => Err(error::ErrorKind::Other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_user(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
|
let client = &request.client;
|
||||||
|
|
||||||
|
let url = format!(
|
||||||
|
"{request}/users?token={api_token}",
|
||||||
|
request = request.url.as_ref().unwrap(),
|
||||||
|
api_token = request.authentication.credentials.1.as_ref().unwrap(),
|
||||||
|
);
|
||||||
|
let response = client.get(url).send();
|
||||||
|
match response {
|
||||||
|
Ok(repo) => {
|
||||||
|
match repo.status() {
|
||||||
|
StatusCode::OK => {
|
||||||
|
let deserialized: MultipleUsers = repo.json().unwrap();
|
||||||
|
|
||||||
|
match deserialized.data.len() != 0 {
|
||||||
|
true => {
|
||||||
|
println!("{}", "List of users found:");
|
||||||
|
|
||||||
|
for (i, data) in deserialized.data.iter().enumerate() {
|
||||||
|
println!("{}.\nUsername: {:1}\n\tEmail address: {:2}\n\tAdmin?: {:3}", i + 1, data.login, data.email, data.is_admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Total number of users indexed: {}",
|
||||||
|
deserialized.data.len()
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
println!("{}", "No users found :(");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StatusCode::BAD_REQUEST => {
|
||||||
|
let deserialized: UserErrorResponse = repo.json().unwrap(); // TODO: handle
|
||||||
|
Err(error::ErrorKind::BadRequest(deserialized.message))
|
||||||
|
}
|
||||||
|
StatusCode::FORBIDDEN => {
|
||||||
|
let deserialzed: UserErrorResponse = repo.json().unwrap(); // TODO: handle errs
|
||||||
|
Err(error::ErrorKind::ForbiddenRequest(deserialzed.message))
|
||||||
|
}
|
||||||
|
_ => Err(error::ErrorKind::Other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_e) => Err(error::ErrorKind::Other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn search_user(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
|
let client = &request.client;
|
||||||
|
let arg_value = request
|
||||||
.arg_value
|
.arg_value
|
||||||
.subcommand()
|
.subcommand()
|
||||||
.1
|
.1
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.value_of("create")
|
.value_of("search")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut user_create_input: HashMap<String, String> = HashMap::new();
|
let url = format!(
|
||||||
let username = util::get_input(String::from("Please enter a username:"));
|
"{request}/users?q={query}&token={api_token}",
|
||||||
let email = util::get_input(String::from("Please enter a email address:"));
|
request = request.url.as_ref().unwrap(),
|
||||||
let password = util::get_input(String::from("Please enter a password:"));
|
query = arg_value,
|
||||||
user_create_input.insert("login".to_string(), username);
|
api_token = request.authentication.credentials.1.as_ref().unwrap(),
|
||||||
user_create_input.insert("email".to_string(), email);
|
);
|
||||||
user_create_input.insert("password".to_string(), password);
|
|
||||||
|
let response = client.get(url.as_str()).send();
|
||||||
|
|
||||||
|
match response {
|
||||||
|
Ok(repo) => match repo.status() {
|
||||||
|
StatusCode::OK => Ok(()),
|
||||||
|
_ => Err(error::ErrorKind::Other),
|
||||||
|
},
|
||||||
|
Err(_e) => Err(error::ErrorKind::Other),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_user() {}
|
pub fn delete_user(&self, request: &Request) -> Result<(), error::ErrorKind> {
|
||||||
|
let client = &request.client;
|
||||||
|
let arg_value = request
|
||||||
|
.arg_value
|
||||||
|
.subcommand()
|
||||||
|
.1
|
||||||
|
.unwrap()
|
||||||
|
.value_of("search")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
pub fn search_user() {}
|
let url = format!(
|
||||||
|
"{request}/admin/users/{username}",
|
||||||
|
request = request.url.as_ref().unwrap(),
|
||||||
|
username = arg_value,
|
||||||
|
);
|
||||||
|
let response = client.delete(url.as_str()).send();
|
||||||
|
|
||||||
pub fn delete_user() {}
|
match response {
|
||||||
|
Ok(repo) => match repo.status() {
|
||||||
|
StatusCode::NO_CONTENT => {
|
||||||
|
println!("User successfully deleted!");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
StatusCode::FORBIDDEN => {
|
||||||
|
let deserialized: UserErrorResponse = repo.json().unwrap();
|
||||||
|
Err(error::ErrorKind::ForbiddenRequest(deserialized.message))
|
||||||
|
}
|
||||||
|
_ => Err(error::ErrorKind::Other),
|
||||||
|
},
|
||||||
|
Err(_e) => Err(error::ErrorKind::Other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn authed_user(&self, request: &Request) {
|
||||||
|
let client = &request.client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for User {
|
||||||
|
fn default() -> Self {
|
||||||
|
User::new()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
63
src/util.rs
63
src/util.rs
@ -1,5 +1,17 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
|
use clap::{ArgMatches, Error};
|
||||||
|
|
||||||
|
use crate::request::RequestType;
|
||||||
|
|
||||||
|
pub enum ErrorKind {
|
||||||
|
BadRequest,
|
||||||
|
ForbiddenRequest,
|
||||||
|
NotFound,
|
||||||
|
UnprocessiableRequest,
|
||||||
|
JsonError,
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Can't get this function to properly work
|
// TODO: Can't get this function to properly work
|
||||||
// Currently, I'm grabbing input and have the server tell me whether or
|
// Currently, I'm grabbing input and have the server tell me whether or
|
||||||
// not input was validated. What I want to have happen is if there's
|
// not input was validated. What I want to have happen is if there's
|
||||||
@ -24,3 +36,54 @@ pub fn get_input(question: String) -> String {
|
|||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// When you get a bad response from your Gitea server (any HTTP response that has
|
||||||
|
/// a status code not 2xx), and given the kind of response a user receives, the
|
||||||
|
/// appropriate message should be returned
|
||||||
|
pub fn bad_response_message(message: &String, error_kind: ErrorKind) -> String {
|
||||||
|
let final_message: String;
|
||||||
|
match error_kind {
|
||||||
|
ErrorKind::BadRequest => {
|
||||||
|
final_message = format!(
|
||||||
|
"Client error - please try again!\nError message: {}",
|
||||||
|
message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ErrorKind::ForbiddenRequest => {
|
||||||
|
final_message = format!(
|
||||||
|
"Client error - unauthorized. Please try again!\nError message: {}",
|
||||||
|
message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ErrorKind::NotFound => {
|
||||||
|
final_message = format!("Client error - not found!\nError message: {}", message);
|
||||||
|
}
|
||||||
|
ErrorKind::UnprocessiableRequest => {
|
||||||
|
final_message = format!("Client error - the request can't be processed. Please try again!\nError message: {}", message);
|
||||||
|
}
|
||||||
|
ErrorKind::JsonError => {
|
||||||
|
final_message = format!(
|
||||||
|
"Client error - can't parse command!\nError message: {}",
|
||||||
|
message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String::from(final_message)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Based on a subcommand that is passed, return the appropriate request
|
||||||
|
/// type
|
||||||
|
pub fn get_request_type(args: &ArgMatches) -> Result<RequestType, clap::Error> {
|
||||||
|
let request_type: &str = args.subcommand().0;
|
||||||
|
match request_type {
|
||||||
|
"repo" => Ok(RequestType::Repository),
|
||||||
|
"issue" => Ok(RequestType::Issue),
|
||||||
|
"pr" => Ok(RequestType::PullRequest),
|
||||||
|
"user" => Ok(RequestType::User),
|
||||||
|
_ => Err(clap::Error::with_description(
|
||||||
|
"Unknown or invalid command",
|
||||||
|
clap::ErrorKind::InvalidSubcommand,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user