forked from kemitix/git-next
feat: wrap API Token in a secrect::Secret and avoid logging
Closes kemitix/git-next#30
This commit is contained in:
parent
e8d174ee84
commit
cedaf16acf
5 changed files with 40 additions and 17 deletions
|
@ -30,6 +30,9 @@ tempfile = "3.10"
|
|||
serde = { version = "1.0", features = ["derive"] }
|
||||
toml = "0.8"
|
||||
|
||||
# Secrets and Password
|
||||
secrecy = "0.8"
|
||||
|
||||
# error handling
|
||||
terrors = "0.3"
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::fmt::Display;
|
|||
use actix::prelude::*;
|
||||
|
||||
use kxio::network;
|
||||
use secrecy::ExposeSecret;
|
||||
use tracing::{error, info, warn};
|
||||
|
||||
use crate::server::{
|
||||
|
@ -179,7 +180,7 @@ pub async fn advance_main(
|
|||
};
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GitRef(pub String);
|
||||
impl From<forge::Commit> for GitRef {
|
||||
fn from(value: forge::Commit) -> Self {
|
||||
|
@ -197,10 +198,16 @@ impl Display for GitRef {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ResetForce {
|
||||
None,
|
||||
Force(GitRef),
|
||||
}
|
||||
impl Display for ResetForce {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
pub fn reset(
|
||||
branch: &BranchName,
|
||||
gitref: impl Into<GitRef>,
|
||||
|
@ -209,16 +216,19 @@ pub fn reset(
|
|||
) -> Result<(), std::io::Error> {
|
||||
let gitref: GitRef = gitref.into();
|
||||
let user = &repo_details.forge.user;
|
||||
let token = &repo_details.forge.token;
|
||||
|
||||
let hostname = &repo_details.forge.hostname;
|
||||
let path = &repo_details.repo;
|
||||
let token = &repo_details.forge.token.expose_secret();
|
||||
let origin = format!("https://{user}:{token}@{hostname}/{path}.git");
|
||||
let force = match reset_force {
|
||||
ResetForce::None => "".to_string(),
|
||||
ResetForce::Force(old_ref) => format!("--force-with-lease={branch}:{old_ref}"),
|
||||
};
|
||||
// INFO: never log the command as it contains the API token
|
||||
let command = format!("/usr/bin/git push {origin} {gitref}:{branch} {force}");
|
||||
info!("Running command: {}", command);
|
||||
drop(origin);
|
||||
info!("Resetting {branch} to {gitref}");
|
||||
match gix::command::prepare(command)
|
||||
.with_shell_allow_argument_splitting()
|
||||
.stdout(std::process::Stdio::null())
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::{
|
|||
fmt::{Display, Formatter},
|
||||
};
|
||||
|
||||
use secrecy::ExposeSecret;
|
||||
use serde::Deserialize;
|
||||
use terrors::OneOf;
|
||||
|
||||
|
@ -94,7 +95,7 @@ impl Forge {
|
|||
}
|
||||
|
||||
pub fn token(&self) -> ApiToken {
|
||||
ApiToken(self.token.clone())
|
||||
ApiToken(self.token.clone().into())
|
||||
}
|
||||
|
||||
pub fn repos(&self) -> impl Iterator<Item = (RepoName, &Repo)> {
|
||||
|
@ -157,14 +158,19 @@ impl Display for User {
|
|||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ApiToken(pub String);
|
||||
impl Display for ApiToken {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ApiToken(pub secrecy::Secret<String>);
|
||||
impl From<String> for ApiToken {
|
||||
fn from(value: String) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
impl ExposeSecret<String> for ApiToken {
|
||||
fn expose_secret(&self) -> &String {
|
||||
self.0.expose_secret()
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ForgeDetails {
|
||||
pub name: ForgeName,
|
||||
pub forge_type: ForgeType,
|
||||
|
@ -206,7 +212,7 @@ impl Display for BranchName {
|
|||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RepoDetails {
|
||||
pub name: RepoName,
|
||||
pub repo: RepoPath,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use base64::Engine;
|
||||
use kxio::network::{self, Network};
|
||||
use secrecy::ExposeSecret;
|
||||
use terrors::OneOf;
|
||||
use tracing::{error, info};
|
||||
|
||||
|
@ -33,7 +34,7 @@ pub async fn load(
|
|||
let path = &details.repo;
|
||||
let filepath = ".git-next.toml";
|
||||
let branch = &details.branch;
|
||||
let token = &details.forge.token;
|
||||
let token = details.forge.token.expose_secret();
|
||||
let url = network::NetUrl::new(format!(
|
||||
"https://{hostname}/api/v1/repos/{path}/contents/{filepath}?ref={branch}&token={token}"
|
||||
));
|
||||
|
@ -127,7 +128,7 @@ pub async fn validate(
|
|||
) -> Result<RepoConfig, OneOf<RepoConfigValidateErrors>> {
|
||||
let hostname = &details.forge.hostname;
|
||||
let path = &details.repo;
|
||||
let token = &details.forge.token;
|
||||
let token = details.forge.token.expose_secret();
|
||||
let url = network::NetUrl::new(format!(
|
||||
"https://{hostname}/api/v1/repos/{path}/branches?token={token}"
|
||||
));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use kxio::network;
|
||||
use secrecy::ExposeSecret;
|
||||
use tracing::{error, info, warn};
|
||||
|
||||
use crate::server;
|
||||
|
@ -49,16 +50,18 @@ async fn get_commit_history(
|
|||
) -> Result<Vec<forge::Commit>, network::NetworkError> {
|
||||
let hostname = &repo_details.forge.hostname;
|
||||
let path = &repo_details.repo;
|
||||
let token = &repo_details.forge.token;
|
||||
|
||||
let mut page = 1;
|
||||
let limit = match find_commits.is_empty() {
|
||||
true => 1,
|
||||
false => 50,
|
||||
};
|
||||
let options = "stat=false&verification=false&files=false";
|
||||
let mut all_commits = Vec::new();
|
||||
loop {
|
||||
let token = repo_details.forge.token.expose_secret();
|
||||
let url = network::NetUrl::new(format!(
|
||||
"https://{hostname}/api/v1/repos/{path}/commits?sha={branch_name}&stat=false&verification=false&files=false&token={token}&page={page}&limit={limit}"
|
||||
"https://{hostname}/api/v1/repos/{path}/commits?sha={branch_name}&{options}&token={token}&page={page}&limit={limit}"
|
||||
));
|
||||
|
||||
info!(%url, "Fetching commits");
|
||||
|
@ -109,7 +112,7 @@ pub async fn get_commit_status(
|
|||
) -> Status {
|
||||
let hostname = &repo_details.forge.hostname;
|
||||
let path = &repo_details.repo;
|
||||
let token = &repo_details.forge.token;
|
||||
let token = repo_details.forge.token.expose_secret();
|
||||
let url = network::NetUrl::new(format!(
|
||||
"https://{hostname}/api/v1/repos/{path}/commits/{next}/status?token={token}"
|
||||
));
|
||||
|
|
Loading…
Reference in a new issue