Compare commits
1 Commits
master
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7b5b4a1982 |
@@ -2,7 +2,7 @@
|
||||
# Copyright 2022 - Artix Linux
|
||||
FROM artixlinux/artixweb-packages-ci:latest AS build
|
||||
|
||||
LABEL Maintainer="damnwidget@artixlinux.org"
|
||||
LABEL Maintainer="nikolar@artixlinux.org"
|
||||
LABEL Name="Artix Web Packages Container"
|
||||
LABEL Version="0.1.0"
|
||||
|
||||
|
@@ -1,7 +1,10 @@
|
||||
[package]
|
||||
name = "artix-gitea"
|
||||
authors = ["Oscar Campos <damnwidget@artixlinux.org>"]
|
||||
description = "Search for packages in Artix Linux repositories"
|
||||
authors = [
|
||||
"Oscar Campos <damnwidget@artixlinux.org>",
|
||||
"Nikola Radojević <nikolar@artixlinux.org>"
|
||||
]
|
||||
exclude = [".gitignore", ".cargo/config"]
|
||||
repository = "gitea.artixlinux.org/artix/artixweb_packaes"
|
||||
homepage = "https://packages.artixlinux.org"
|
||||
@@ -15,7 +18,7 @@ name = "artix_gitea"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "4.0.1"
|
||||
serde = { version = "1.0.136", features = ["derive"] }
|
||||
awc = { version = "3.0.0", features = ["rustls"] }
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
actix-web = "4.3.1"
|
||||
serde = { version = "1.0.163", features = ["derive"] }
|
||||
awc = { version = "3.1.1", features = ["rustls"] }
|
||||
chrono = { version = "0.4.24", features = ["serde"] }
|
||||
|
@@ -1,7 +1,10 @@
|
||||
[package]
|
||||
name = "artix-pkglib"
|
||||
authors = ["Oscar Campos <damnwidget@artixlinux.org>"]
|
||||
description = "Manipulate Artix Linux packages and databases"
|
||||
authors = [
|
||||
"Oscar Campos <damnwidget@artixlinux.org>",
|
||||
"Nikola Radojević <nikolar@artixlinux.org>"
|
||||
]
|
||||
exclude = [".gitignore", ".cargo/config"]
|
||||
repository = "gitea.artixlinux.org/artix/artixweb_packages"
|
||||
homepage = "https://packages.artixlinux.org"
|
||||
@@ -16,7 +19,7 @@ path = "src/lib.rs"
|
||||
|
||||
|
||||
[dependencies]
|
||||
alpm = "2.2.1"
|
||||
alpm = "2.2.2"
|
||||
alpm-utils = "2.0.0"
|
||||
pacmanconf = "2.0.0"
|
||||
thiserror = "1.0.1"
|
||||
thiserror = "1.0.40"
|
||||
|
@@ -1,7 +1,10 @@
|
||||
[package]
|
||||
name = "artixweb_packages"
|
||||
authors = ["Oscar Campos <damnwidget@artixlinux.org>"]
|
||||
description = "Artix Linux Packages Information Website"
|
||||
authors = [
|
||||
"Oscar Campos <damnwidget@artixlinux.org>",
|
||||
"Nikola Radojević <nikolar@artixlinux.org>"
|
||||
]
|
||||
exclude = [".gitignore", ".cargo/config"]
|
||||
repository = "gitea.artixlinux.org/artix/artixweb_packages"
|
||||
keywords = ["artix", "packages"]
|
||||
@@ -18,29 +21,30 @@ bench = false
|
||||
artix-gitea = { path = "../artix-gitea", version = "=0.1.0" }
|
||||
artix-pkglib = { path = "../artix-pkglib", version = "=0.1.0" }
|
||||
|
||||
actix-files = "0.6.0"
|
||||
actix-identity = "0.4"
|
||||
argon2 = "0.4.0"
|
||||
askama = "0.11.1"
|
||||
actix-files = "0.6.2"
|
||||
actix-identity = "0.4.0"
|
||||
argon2 = "0.5.0"
|
||||
askama = "0.12.0"
|
||||
derive_more = "0.99.17"
|
||||
env_logger = "0.9.0"
|
||||
env_logger = "0.10.0"
|
||||
lazy_static = "1.4.0"
|
||||
lettre = "0.10.0-rc.4"
|
||||
log = "0.4.14"
|
||||
r2d2 = "0.8"
|
||||
time = "0.3"
|
||||
lettre = "0.10.4"
|
||||
log = "0.4.17"
|
||||
r2d2 = "0.8.10"
|
||||
time = "0.3.21"
|
||||
|
||||
actix-session = { version = "0.6.0", features = ["cookie-session"] }
|
||||
actix-web = { version = "4.0.1", features = ["rustls"] }
|
||||
clap = { version = "3.1.5", features = ["cargo", "suggestions", "env"] }
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
diesel = { version = "1.4.8", features = [
|
||||
actix-session = { version = "0.7.2", features = ["cookie-session"] }
|
||||
actix-web = { version = "4.3.1", features = ["rustls"] }
|
||||
clap = { version = "4.3.0", features = ["cargo", "suggestions", "env"] }
|
||||
chrono = { version = "0.4.24", features = ["serde"] }
|
||||
diesel = { version = "2.0.4", features = [
|
||||
"postgres",
|
||||
"uuidv07",
|
||||
"sqlite",
|
||||
"uuid",
|
||||
"r2d2",
|
||||
"chrono",
|
||||
] }
|
||||
rand_core = { version = "0.6", features = ["std"] }
|
||||
rand_core = { version = "0.6.4", features = ["std"] }
|
||||
serde = { version = "^1.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0.79" }
|
||||
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||
serde_json = { version = "1.0.96" }
|
||||
uuid = { version = "1.3.1", features = ["serde", "v4"] }
|
||||
|
@@ -3,30 +3,41 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2023 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
use std::{env, fs::File, io::Read, path::Path};
|
||||
|
||||
use argon2::{password_hash::SaltString, Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
|
||||
use argon2::{
|
||||
password_hash::SaltString, Argon2, PasswordHash, PasswordHasher,
|
||||
PasswordVerifier,
|
||||
};
|
||||
use artix_pkglib::prelude::{Alpm, SigLevel};
|
||||
use rand_core::OsRng;
|
||||
|
||||
use super::lib::errors::ServiceError;
|
||||
use super::utils::errors::ServiceError;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
/// Global constant application settings
|
||||
pub static ref SETTINGS: AppSettings = AppSettings {
|
||||
app_name: env::var("APP_NAME").unwrap_or_else(|_| String::from("ArtixWeb Packages")),
|
||||
gitea_url: env::var("GITEA_URL").unwrap_or_else(|_| String::from(artix_gitea::prelude::GITEA_URL)),
|
||||
gitea_api_url: env::var("GITEA_API_URL").unwrap_or_else(|_| String::from(artix_gitea::prelude::GITEA_API_URL)),
|
||||
gitea_token: env::var("GITEA_TOKEN").unwrap_or_else(|_| String::new()),
|
||||
databases_path: env::var("DATABASES_PATH").unwrap_or_else(|_| String::from("/var/lib/pacman")),
|
||||
api_token: env::var("API_TOKEN").unwrap_or_else(|_| generate_random_token()),
|
||||
app_name: env::var("APP_NAME")
|
||||
.unwrap_or_else(|_| String::from("ArtixWeb Packages")),
|
||||
gitea_url: env::var("GITEA_URL")
|
||||
.unwrap_or_else(|_| String::from(artix_gitea::prelude::GITEA_URL)),
|
||||
gitea_api_url: env::var("GITEA_API_URL")
|
||||
.unwrap_or_else(|_| String::from(artix_gitea::prelude::GITEA_API_URL)),
|
||||
gitea_token: env::var("GITEA_TOKEN")
|
||||
.unwrap_or_else(|_| String::new()),
|
||||
databases_path: env::var("DATABASES_PATH")
|
||||
.unwrap_or_else(|_| String::from("/var/lib/pacman")),
|
||||
api_token: env::var("API_TOKEN")
|
||||
.unwrap_or_else(|_| generate_random_token()),
|
||||
};
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref SECRET_KEY: String = std::env::var("SECRET_KEY").unwrap_or_else(|_| generate_random_token());
|
||||
pub static ref SECRET_KEY: String = std::env::var("SECRET_KEY")
|
||||
.unwrap_or_else(|_| generate_random_token());
|
||||
}
|
||||
|
||||
/// Data structure containing the site configuration
|
||||
@@ -73,7 +84,8 @@ fn generate_random_token() -> String {
|
||||
token
|
||||
}
|
||||
|
||||
const DATABASESS: [&str; 5] = ["system", "world", "galaxy", "universe", "lib32"];
|
||||
const DATABASESS: [&str; 5] =
|
||||
["system", "world", "galaxy", "universe", "lib32"];
|
||||
const MIN_PASSWORD_LENGTH: usize = 8;
|
||||
|
||||
/// Syncs the configured databases
|
||||
|
@@ -3,21 +3,24 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
use std::future::{ready, Ready};
|
||||
|
||||
use actix_identity::Identity;
|
||||
use actix_session::Session;
|
||||
use actix_web::{dev::Payload, http, web, Error, FromRequest, HttpRequest, HttpResponse};
|
||||
use actix_web::{
|
||||
dev::Payload, http, web, Error, FromRequest, HttpRequest, HttpResponse,
|
||||
};
|
||||
use askama::Template;
|
||||
use diesel::prelude::*;
|
||||
use diesel::PgConnection;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::config::verify;
|
||||
use crate::lib::errors::ServiceError;
|
||||
use crate::models::{Pool, SlimUser, User};
|
||||
use crate::utils::errors::ServiceError;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Data {
|
||||
@@ -76,7 +79,8 @@ pub async fn login(
|
||||
session: Session,
|
||||
pool: web::Data<Pool>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
let user = web::block(move || query(&auth_data.into_inner(), &pool)).await??;
|
||||
let user =
|
||||
web::block(move || query(&auth_data.into_inner(), &pool)).await??;
|
||||
let user_string = serde_json::to_string(&user).unwrap();
|
||||
id.remember(user_string);
|
||||
session.insert("user_email", user.email)?;
|
||||
@@ -94,9 +98,12 @@ pub async fn logout(id: Identity, session: Session) -> HttpResponse {
|
||||
.finish()
|
||||
}
|
||||
|
||||
fn query(auth_data: &Data, pool: &web::Data<Pool>) -> Result<SlimUser, ServiceError> {
|
||||
fn query(
|
||||
auth_data: &Data,
|
||||
pool: &web::Data<Pool>,
|
||||
) -> Result<SlimUser, ServiceError> {
|
||||
use crate::schema::users::dsl::{email, users};
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
let mut items = users
|
||||
.filter(email.eq(&auth_data.email))
|
||||
.load::<User>(conn)?;
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
#![allow(clippy::unused_async, clippy::module_name_repetitions)]
|
||||
@@ -38,11 +39,12 @@ pub async fn package_details(
|
||||
pool: web::Data<Pool>,
|
||||
) -> Result<HttpResponse> {
|
||||
let start_time = std::time::Instant::now();
|
||||
let user_email = if let Some(email) = session.get::<String>("user_email").unwrap() {
|
||||
email
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let user_email =
|
||||
if let Some(email) = session.get::<String>("user_email").unwrap() {
|
||||
email
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let s = if let Ok(details) = get_packages_details_inner(&data, pool).await {
|
||||
PackageDetailsTemplate {
|
||||
@@ -89,10 +91,12 @@ mod filters {
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn show_date(timestamp: &i64) -> ::askama::Result<NaiveDateTime> {
|
||||
Ok(NaiveDateTime::from_timestamp(*timestamp, 0))
|
||||
Ok(NaiveDateTime::from_timestamp_opt(*timestamp, 0).unwrap())
|
||||
}
|
||||
|
||||
pub(crate) fn provides_or_replaces(deps: &[Dependency]) -> ::askama::Result<String> {
|
||||
pub(crate) fn provides_or_replaces(
|
||||
deps: &[Dependency],
|
||||
) -> ::askama::Result<String> {
|
||||
let mut elements = Vec::new();
|
||||
elements.extend(
|
||||
deps.iter()
|
||||
|
@@ -3,18 +3,23 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
use actix_web::{web, HttpResponse};
|
||||
use askama::Template;
|
||||
use diesel::{prelude::*, PgConnection};
|
||||
use lettre::{transport::smtp::authentication::Credentials, Message, SmtpTransport, Transport};
|
||||
use lettre::{
|
||||
transport::smtp::authentication::Credentials, Message, SmtpTransport,
|
||||
Transport,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::utils;
|
||||
use crate::{
|
||||
config::{SmtpOptions, SETTINGS},
|
||||
lib::templates::EmailTemplate,
|
||||
models::{Invitation, Pool},
|
||||
utils::templates::EmailTemplate,
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -31,7 +36,11 @@ pub async fn post(
|
||||
if let Some(token) = req.headers().get("x-admin-token") {
|
||||
if token == &SETTINGS.api_token {
|
||||
web::block(move || {
|
||||
create_invitation(invitation_data.into_inner().email, &pool, &smtp_cfg)
|
||||
create_invitation(
|
||||
invitation_data.into_inner().email,
|
||||
&pool,
|
||||
&smtp_cfg,
|
||||
)
|
||||
})
|
||||
.await??;
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
@@ -47,7 +56,7 @@ fn create_invitation(
|
||||
eml: String,
|
||||
pool: &web::Data<Pool>,
|
||||
smtp_cfg: &web::Data<SmtpOptions>,
|
||||
) -> Result<(), crate::lib::errors::ServiceError> {
|
||||
) -> Result<(), utils::errors::ServiceError> {
|
||||
let invitation = query(eml, pool)?;
|
||||
if let Err(err) = send_invitation(&invitation, smtp_cfg) {
|
||||
dbg!(err);
|
||||
@@ -59,7 +68,7 @@ fn create_invitation(
|
||||
fn send_invitation(
|
||||
invitation: &Invitation,
|
||||
smtp_cfg: &web::Data<SmtpOptions>,
|
||||
) -> Result<(), crate::lib::errors::ServiceError> {
|
||||
) -> Result<(), utils::errors::ServiceError> {
|
||||
let email = Message::builder()
|
||||
.from(
|
||||
"ArtixWeb Packages <artixweb@artixlinux.org>"
|
||||
@@ -71,8 +80,11 @@ fn send_invitation(
|
||||
.body(EmailTemplate { invitation }.render().unwrap())
|
||||
.unwrap();
|
||||
|
||||
let smtp_credentials = Credentials::new(smtp_cfg.user.clone(), smtp_cfg.password.clone());
|
||||
let mailer = if let Ok(transport) = SmtpTransport::starttls_relay(&smtp_cfg.relay.clone()) {
|
||||
let smtp_credentials =
|
||||
Credentials::new(smtp_cfg.user.clone(), smtp_cfg.password.clone());
|
||||
let mailer = if let Ok(transport) =
|
||||
SmtpTransport::starttls_relay(&smtp_cfg.relay.clone())
|
||||
{
|
||||
transport.credentials(smtp_credentials).build()
|
||||
} else {
|
||||
// open a local connection on port 25
|
||||
@@ -84,7 +96,7 @@ fn send_invitation(
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => {
|
||||
log::error!("{}", e);
|
||||
Err(crate::lib::errors::ServiceError::InternalServerError)
|
||||
Err(utils::errors::ServiceError::InternalServerError)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,11 +105,11 @@ fn send_invitation(
|
||||
fn query(
|
||||
eml: String,
|
||||
pool: &web::Data<Pool>,
|
||||
) -> Result<Invitation, crate::lib::errors::ServiceError> {
|
||||
) -> Result<Invitation, utils::errors::ServiceError> {
|
||||
use crate::schema::invitations::dsl::invitations;
|
||||
|
||||
let new_invitation: Invitation = eml.into();
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
|
||||
let inserted_invitation = diesel::insert_into(invitations)
|
||||
.values(&new_invitation)
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
//! Packages route handlers definitions
|
||||
@@ -20,20 +21,24 @@ use askama::Template;
|
||||
use chrono::prelude::NaiveDateTime;
|
||||
use diesel::prelude::*;
|
||||
use diesel::PgConnection;
|
||||
use lettre::{transport::smtp::authentication::Credentials, Message, SmtpTransport, Transport};
|
||||
use lettre::{
|
||||
transport::smtp::authentication::Credentials, Message, SmtpTransport,
|
||||
Transport,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::config::SmtpOptions;
|
||||
use crate::models::PackageWithFlagView;
|
||||
use crate::models::{Package as PackageMeta, PrivatePackage};
|
||||
use crate::utils;
|
||||
use crate::{
|
||||
config::{sync_databases, SETTINGS},
|
||||
lib::{
|
||||
models::{PackageFlag, Pool},
|
||||
utils::{
|
||||
database::packages,
|
||||
errors::{ArtixWebPackageError, ServiceError},
|
||||
templates::PackageFlagEmail,
|
||||
},
|
||||
models::{PackageFlag, Pool},
|
||||
};
|
||||
|
||||
use super::auth::LoggedUser;
|
||||
@@ -169,7 +174,11 @@ pub async fn flag_package(
|
||||
let user_name = logged_user.email.clone();
|
||||
let package_doublet = format!("{}-{}", data.0, data.1);
|
||||
web::block(move || {
|
||||
flag_package_query(&format!("{}-{}", data.0, data.1), &logged_user.email, &pool)
|
||||
flag_package_query(
|
||||
&format!("{}-{}", data.0, data.1),
|
||||
&logged_user.email,
|
||||
&pool,
|
||||
)
|
||||
})
|
||||
.await??;
|
||||
|
||||
@@ -195,8 +204,11 @@ pub async fn flag_package(
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let smtp_credentials = Credentials::new(smtp_cfg.user.clone(), smtp_cfg.password.clone());
|
||||
let mailer = if let Ok(transport) = SmtpTransport::starttls_relay(&smtp_cfg.relay.clone()) {
|
||||
let smtp_credentials =
|
||||
Credentials::new(smtp_cfg.user.clone(), smtp_cfg.password.clone());
|
||||
let mailer = if let Ok(transport) =
|
||||
SmtpTransport::starttls_relay(&smtp_cfg.relay.clone())
|
||||
{
|
||||
transport.credentials(smtp_credentials).build()
|
||||
} else {
|
||||
// open a local connection on port 25
|
||||
@@ -208,7 +220,7 @@ pub async fn flag_package(
|
||||
Ok(_) => Ok(HttpResponse::Ok().finish()),
|
||||
Err(e) => {
|
||||
log::error!("{}", e);
|
||||
Err(crate::lib::errors::ServiceError::BadRequest(
|
||||
Err(utils::errors::ServiceError::BadRequest(
|
||||
format!("could not send email: {:?}", e),
|
||||
Some(start_time),
|
||||
)
|
||||
@@ -236,7 +248,9 @@ pub async fn flag_package_delete(
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(result) = web::block(move || flag_package_delete_query(&package_doublet, &pool)).await
|
||||
if let Ok(result) =
|
||||
web::block(move || flag_package_delete_query(&package_doublet, &pool))
|
||||
.await
|
||||
{
|
||||
match result {
|
||||
Ok(_) => HttpResponse::Ok().finish(),
|
||||
@@ -251,11 +265,12 @@ pub async fn flag_package_delete(
|
||||
fn flag_package_delete_query(
|
||||
package_doublet: &str,
|
||||
pool: &web::Data<Pool>,
|
||||
) -> Result<(), crate::lib::errors::ServiceError> {
|
||||
) -> Result<(), utils::errors::ServiceError> {
|
||||
use crate::schema::package_flags::dsl::{package_flags, package_name};
|
||||
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
diesel::delete(package_flags.filter(package_name.eq(package_doublet))).execute(conn)?;
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
diesel::delete(package_flags.filter(package_name.eq(package_doublet)))
|
||||
.execute(conn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -264,11 +279,11 @@ fn flag_package_query(
|
||||
package_doublet: &str,
|
||||
email: &str,
|
||||
pool: &web::Data<Pool>,
|
||||
) -> Result<(), crate::lib::errors::ServiceError> {
|
||||
) -> Result<(), utils::errors::ServiceError> {
|
||||
use crate::schema::package_flags::dsl::package_flags;
|
||||
|
||||
let pf = PackageFlag::from_details(email, package_doublet);
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
diesel::insert_into(package_flags)
|
||||
.values(&pf)
|
||||
.execute(conn)?;
|
||||
@@ -310,7 +325,10 @@ pub async fn flags_package_ui(
|
||||
// the user has already flag this package_name (plus version)
|
||||
return Ok(HttpResponse::Ok().content_type("text/html").body(
|
||||
PackageAlreadyFlaggedTemplate {
|
||||
error_message: format!("You have already flag package {}", package_doublet),
|
||||
error_message: format!(
|
||||
"You have already flag package {}",
|
||||
package_doublet
|
||||
),
|
||||
user_email: logged_user.email,
|
||||
generation_time: start_time.elapsed().as_millis(),
|
||||
}
|
||||
@@ -367,10 +385,12 @@ fn get_package_flags_query(
|
||||
email: &str,
|
||||
pool: &web::Data<Pool>,
|
||||
start_time: std::time::Instant,
|
||||
) -> Result<bool, crate::lib::errors::ServiceError> {
|
||||
use crate::schema::package_flags::dsl::{package_flags, package_name, user_email};
|
||||
) -> Result<bool, utils::errors::ServiceError> {
|
||||
use crate::schema::package_flags::dsl::{
|
||||
package_flags, package_name, user_email,
|
||||
};
|
||||
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
package_flags
|
||||
.filter(package_name.eq_all(pkg_id))
|
||||
.filter(user_email.eq_all(email))
|
||||
@@ -398,7 +418,9 @@ fn get_package_flags_query(
|
||||
pub async fn get_packages<'a>(
|
||||
data: web::Path<(String, usize, usize)>,
|
||||
) -> Result<HttpResponse, ArtixWebPackageError> {
|
||||
if let Ok(result) = get_packages_inner(&data.0, data.1, data.2, None, None).await {
|
||||
if let Ok(result) =
|
||||
get_packages_inner(&data.0, data.1, data.2, None, None).await
|
||||
{
|
||||
return Ok(HttpResponse::Ok()
|
||||
.content_type("application/json; charset=utf-8")
|
||||
.insert_header(("X-Packages-Number", result.0.len()))
|
||||
@@ -513,8 +535,10 @@ pub(crate) async fn get_packages_details_inner(
|
||||
|
||||
let pkg_name_version = format!("{}-{}", pkg.name(), pkg.version());
|
||||
let p_pool = pool.clone();
|
||||
if let Ok(Ok(metadata)) =
|
||||
web::block(move || get_package_metadata(&pkg_name_version, &pool)).await
|
||||
if let Ok(Ok(metadata)) = web::block(move || {
|
||||
get_package_metadata(&pkg_name_version, &pool)
|
||||
})
|
||||
.await
|
||||
{
|
||||
result.last_updated = metadata.last_update.timestamp();
|
||||
result.gitea_url = metadata.gitea_url;
|
||||
@@ -550,7 +574,11 @@ pub(crate) async fn get_packages_details_inner(
|
||||
let metadata = PackageMeta {
|
||||
package_name: format!("{}-{}", pkg.name(), pkg.version()),
|
||||
gitea_url: result.gitea_url.clone(),
|
||||
last_update: chrono::NaiveDateTime::from_timestamp(result.last_updated, 0),
|
||||
last_update: chrono::NaiveDateTime::from_timestamp_opt(
|
||||
result.last_updated,
|
||||
0,
|
||||
)
|
||||
.unwrap(),
|
||||
};
|
||||
if web::block(move || add_package_metadata(&metadata, &p_pool))
|
||||
.await
|
||||
@@ -573,8 +601,10 @@ pub(crate) async fn get_packages_details_inner(
|
||||
fn add_package_metadata(metadata: &PackageMeta, pool: &web::Data<Pool>) {
|
||||
use crate::schema::packages::dsl::packages;
|
||||
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
if let Err(err) = diesel::insert_into(packages).values(metadata).execute(conn) {
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
if let Err(err) =
|
||||
diesel::insert_into(packages).values(metadata).execute(conn)
|
||||
{
|
||||
dbg!(err.to_string());
|
||||
}
|
||||
}
|
||||
@@ -583,31 +613,34 @@ fn add_package_metadata(metadata: &PackageMeta, pool: &web::Data<Pool>) {
|
||||
fn get_package_metadata<'a>(
|
||||
pkg_doublet: &'a str,
|
||||
pool: &'a web::Data<Pool>,
|
||||
) -> Result<PrivatePackage, crate::lib::errors::ServiceError> {
|
||||
) -> Result<PrivatePackage, utils::errors::ServiceError> {
|
||||
use crate::schema::{package_flags, packages};
|
||||
|
||||
let start_time = std::time::Instant::now();
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
let metadata: Vec<(PackageMeta, Option<chrono::NaiveDateTime>, Option<String>)> =
|
||||
packages::table
|
||||
.find(pkg_doublet)
|
||||
.left_join(
|
||||
package_flags::table.on(package_flags::package_name
|
||||
.eq(packages::package_name)
|
||||
.and(package_flags::flag_on.ge(packages::last_update))),
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
let metadata: Vec<(
|
||||
PackageMeta,
|
||||
Option<chrono::NaiveDateTime>,
|
||||
Option<String>,
|
||||
)> = packages::table
|
||||
.find(pkg_doublet)
|
||||
.left_join(
|
||||
package_flags::table.on(package_flags::package_name
|
||||
.eq(packages::package_name)
|
||||
.and(package_flags::flag_on.ge(packages::last_update))),
|
||||
)
|
||||
.select((
|
||||
packages::all_columns,
|
||||
package_flags::flag_on.nullable(),
|
||||
package_flags::user_email.nullable(),
|
||||
))
|
||||
.load(conn)
|
||||
.map_err(|_db_error| {
|
||||
ServiceError::BadRequest(
|
||||
format!("Could not find package {}", pkg_doublet),
|
||||
Some(start_time),
|
||||
)
|
||||
.select((
|
||||
packages::all_columns,
|
||||
package_flags::flag_on.nullable(),
|
||||
package_flags::user_email.nullable(),
|
||||
))
|
||||
.load(conn)
|
||||
.map_err(|_db_error| {
|
||||
ServiceError::BadRequest(
|
||||
format!("Could not find package {}", pkg_doublet),
|
||||
Some(start_time),
|
||||
)
|
||||
})?;
|
||||
})?;
|
||||
|
||||
if let Some(user_metadata) = metadata.first() {
|
||||
let flaggers = metadata.iter().map(|meta| meta.2.clone()).collect();
|
||||
@@ -679,7 +712,9 @@ pub(crate) async fn get_packages_inner(
|
||||
let pkgs = pkgs.unwrap();
|
||||
|
||||
let flagged_packages = if let Some(pool) = pool {
|
||||
if let Ok(flagged_packages) = get_flagged_packages(start_time, pool).await {
|
||||
if let Ok(flagged_packages) =
|
||||
get_flagged_packages(start_time, pool).await
|
||||
{
|
||||
flagged_packages
|
||||
} else {
|
||||
Vec::new()
|
||||
@@ -707,7 +742,11 @@ pub(crate) async fn get_packages_inner(
|
||||
},
|
||||
package_name: pkg.name().to_string(),
|
||||
version: pkg.version().as_str().to_string(),
|
||||
last_update: NaiveDateTime::from_timestamp(pkg.build_date(), 0),
|
||||
last_update: NaiveDateTime::from_timestamp_opt(
|
||||
pkg.build_date(),
|
||||
0,
|
||||
)
|
||||
.unwrap(),
|
||||
description: String::from(pkg.desc().unwrap_or_default()),
|
||||
flag_on,
|
||||
flagged,
|
||||
@@ -727,24 +766,28 @@ pub(crate) async fn get_packages_inner(
|
||||
async fn get_flagged_packages(
|
||||
start_time: std::time::Instant,
|
||||
pool: &web::Data<Pool>,
|
||||
) -> Result<Vec<PackageWithFlagView>, crate::lib::errors::ServiceError> {
|
||||
) -> Result<Vec<PackageWithFlagView>, utils::errors::ServiceError> {
|
||||
use crate::schema::package_flags::dsl::{
|
||||
flag_on, package_flags, package_name as package_flag_name,
|
||||
};
|
||||
use crate::schema::packages::dsl::{last_update, package_name, packages};
|
||||
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
let packages_data: Vec<(PackageMeta, Option<chrono::NaiveDateTime>)> = packages
|
||||
.inner_join(
|
||||
package_flags.on(flag_on
|
||||
.ge(last_update)
|
||||
.and(package_name.eq(package_flag_name))),
|
||||
)
|
||||
.select((packages::all_columns(), flag_on.nullable()))
|
||||
.load(conn)
|
||||
.map_err(|_db_error| {
|
||||
ServiceError::BadRequest(String::from("Could not find packages"), Some(start_time))
|
||||
})?;
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
let packages_data: Vec<(PackageMeta, Option<chrono::NaiveDateTime>)> =
|
||||
packages
|
||||
.inner_join(
|
||||
package_flags.on(flag_on
|
||||
.ge(last_update)
|
||||
.and(package_name.eq(package_flag_name))),
|
||||
)
|
||||
.select((packages::all_columns(), flag_on.nullable()))
|
||||
.load(conn)
|
||||
.map_err(|_db_error| {
|
||||
ServiceError::BadRequest(
|
||||
String::from("Could not find packages"),
|
||||
Some(start_time),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(packages_data
|
||||
.iter()
|
||||
@@ -764,7 +807,8 @@ async fn retrieve_maintainers(gitea_repo: &Repository) -> Vec<String> {
|
||||
for line in lines {
|
||||
let lower = line.to_lowercase();
|
||||
if lower.contains("maintainer") || lower.contains("contributor") {
|
||||
let data: Vec<String> = line.split(':').map(|m| m.trim().to_string()).collect();
|
||||
let data: Vec<String> =
|
||||
line.split(':').map(|m| m.trim().to_string()).collect();
|
||||
if data.len() > 1 {
|
||||
maintainers.push(data[1].clone());
|
||||
}
|
||||
@@ -826,13 +870,21 @@ fn construct_dependency(arch: &str, alpm: &Alpm, dep: Dep<'_>) -> Dependency {
|
||||
|
||||
// constructs a (make) Dependency instance with the given data and return it back
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
fn construct_make_dependency(arch: &str, alpm: &Alpm, dep: Dep<'_>) -> Dependency {
|
||||
fn construct_make_dependency(
|
||||
arch: &str,
|
||||
alpm: &Alpm,
|
||||
dep: Dep<'_>,
|
||||
) -> Dependency {
|
||||
common_dependency_data(arch, alpm, &dep, DependencyKind::Make)
|
||||
}
|
||||
|
||||
// constructs a (opt) Dependency instance with the given data and return it back
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
fn construct_opt_dependency(arch: &str, alpm: &Alpm, dep: Dep<'_>) -> Dependency {
|
||||
fn construct_opt_dependency(
|
||||
arch: &str,
|
||||
alpm: &Alpm,
|
||||
dep: Dep<'_>,
|
||||
) -> Dependency {
|
||||
common_dependency_data(arch, alpm, &dep, DependencyKind::Opt)
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
use actix_session::Session;
|
||||
@@ -13,8 +14,9 @@ use diesel::PgConnection;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::config::{check_password_strength, hash_password};
|
||||
use crate::lib::errors::ServiceError;
|
||||
use crate::models::{Invitation, Pool, SlimUser, User};
|
||||
use crate::utils;
|
||||
use crate::utils::errors::ServiceError;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct UserData {
|
||||
@@ -93,17 +95,20 @@ pub async fn invitation(
|
||||
fn check_invitation(
|
||||
invitation_id: &str,
|
||||
pool: &web::Data<Pool>,
|
||||
) -> Result<bool, crate::lib::errors::ServiceError> {
|
||||
) -> Result<bool, utils::errors::ServiceError> {
|
||||
use crate::schema::invitations::dsl::{id, invitations};
|
||||
|
||||
let invitation_id = uuid::Uuid::parse_str(invitation_id)?;
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
|
||||
let inv = invitations
|
||||
.filter(id.eq(invitation_id))
|
||||
.load::<Invitation>(conn)
|
||||
.map_err(|_db_error| {
|
||||
ServiceError::BadRequest("Invalid or expired Invitation".into(), None)
|
||||
ServiceError::BadRequest(
|
||||
"Invalid or expired Invitation".into(),
|
||||
None,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(!inv.is_empty())
|
||||
@@ -141,7 +146,8 @@ pub async fn new_user(
|
||||
}
|
||||
|
||||
// create user from the input data in the form
|
||||
web::block(move || query(&invitation_id.into_inner(), &password, &pool)).await??;
|
||||
web::block(move || query(&invitation_id.into_inner(), &password, &pool))
|
||||
.await??;
|
||||
Ok(HttpResponse::SeeOther()
|
||||
.append_header((http::header::LOCATION, "/login"))
|
||||
.finish())
|
||||
@@ -151,13 +157,13 @@ fn query(
|
||||
invitation_id: &str,
|
||||
password: &str,
|
||||
pool: &web::Data<Pool>,
|
||||
) -> Result<SlimUser, crate::lib::errors::ServiceError> {
|
||||
) -> Result<SlimUser, utils::errors::ServiceError> {
|
||||
use crate::schema::invitations::dsl::{id, invitations};
|
||||
use crate::schema::users::dsl::users;
|
||||
|
||||
let start_time = std::time::Instant::now();
|
||||
let invitation_id = uuid::Uuid::parse_str(invitation_id)?;
|
||||
let conn: &PgConnection = &pool.get().unwrap();
|
||||
let conn: &mut PgConnection = &mut pool.get().unwrap();
|
||||
invitations
|
||||
.filter(id.eq(invitation_id))
|
||||
.load::<Invitation>(conn)
|
||||
@@ -175,8 +181,9 @@ fn query(
|
||||
let password = hash_password(password)?;
|
||||
|
||||
let user = User::from_details(invitation.email, password);
|
||||
let inserted_user: User =
|
||||
diesel::insert_into(users).values(&user).get_result(conn)?;
|
||||
let inserted_user: User = diesel::insert_into(users)
|
||||
.values(&user)
|
||||
.get_result(conn)?;
|
||||
|
||||
return Ok(inserted_user.into());
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2023 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
//! This crate provides an HTTP API to work with Artix Packages
|
||||
@@ -20,10 +21,10 @@ extern crate diesel;
|
||||
|
||||
mod config;
|
||||
mod handlers;
|
||||
mod lib;
|
||||
mod models;
|
||||
mod routes;
|
||||
mod schema;
|
||||
mod utils;
|
||||
|
||||
use actix_identity::{CookieIdentityPolicy, IdentityService};
|
||||
use actix_session::{storage::CookieSessionStore, SessionMiddleware};
|
||||
@@ -38,6 +39,12 @@ use diesel::r2d2::ConnectionManager;
|
||||
use log::{debug, warn};
|
||||
use time::Duration;
|
||||
|
||||
const DEFAULT_BIND_ADDR: &'static str = "127.0.0.1";
|
||||
const DEFAULT_PORT_STR: &'static str = "1936";
|
||||
const DEFAULT_PORT: u16 = 1936;
|
||||
const DEFAULT_DB_URL: &'static str = "localhost";
|
||||
const DEFAULT_DOMAIN: &'static str = "localhost";
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
// parse config
|
||||
@@ -45,20 +52,24 @@ async fn main() -> std::io::Result<()> {
|
||||
.arg(
|
||||
arg!(-b --bind <BIND_ADDRESS>)
|
||||
.required(false)
|
||||
.default_value("127.0.0.1")
|
||||
.default_value(DEFAULT_BIND_ADDR)
|
||||
.env("BIND_ADDRESS"),
|
||||
)
|
||||
.arg(arg!(-p --port <PORT>).required(false).default_value("1936"))
|
||||
.arg(
|
||||
arg!(-p --port <PORT>)
|
||||
.required(false)
|
||||
.default_value(DEFAULT_PORT_STR),
|
||||
)
|
||||
.arg(
|
||||
arg!(-u --databaseurl <DATABASE_URL>)
|
||||
.required(false)
|
||||
.default_value("localhost")
|
||||
.default_value(DEFAULT_DB_URL)
|
||||
.env("DATABASE_URL"),
|
||||
)
|
||||
.arg(
|
||||
arg!(-d --domain <DOMAIN>)
|
||||
.required(false)
|
||||
.default_value("localhost"),
|
||||
.default_value(DEFAULT_DOMAIN),
|
||||
)
|
||||
.arg(
|
||||
arg!(-k --key <SESSION_KEY>)
|
||||
@@ -79,38 +90,41 @@ async fn main() -> std::io::Result<()> {
|
||||
.arg(arg!(-v - -verbose ... ))
|
||||
.get_matches();
|
||||
|
||||
// count how many appearances of verbose we got and assign a value for env_logger
|
||||
let debug_level = match matches.occurrences_of("verbose") {
|
||||
// count how many appearances of verbose we got and assign a value
|
||||
// for env_logger
|
||||
let debug_level = match matches.get_count("verbose") {
|
||||
0 => "warn",
|
||||
1 => "info",
|
||||
_ => "debug",
|
||||
};
|
||||
|
||||
// configure logger
|
||||
env_logger::init_from_env(env_logger::Env::default().default_filter_or(debug_level));
|
||||
env_logger::init_from_env(
|
||||
env_logger::Env::default().default_filter_or(debug_level),
|
||||
);
|
||||
debug!("environment logger level set to 'debug'");
|
||||
|
||||
let host_addr = matches.value_of("bind").unwrap_or_default();
|
||||
let port = matches.value_of("port").unwrap_or_default();
|
||||
let host_addr = matches.get_one::<String>("bind").unwrap();
|
||||
let port = matches.get_one::<String>("port").unwrap();
|
||||
let host_port = if let Ok(n) = port.parse::<u16>() {
|
||||
n
|
||||
} else {
|
||||
warn!("could not parse {} host_port, defaulting to 1936", port);
|
||||
1936
|
||||
DEFAULT_PORT
|
||||
};
|
||||
|
||||
let database_url = matches.value_of("databaseurl").unwrap_or_default();
|
||||
let domain = matches.value_of("domain").unwrap_or_default();
|
||||
let master_key = matches.value_of("key").unwrap();
|
||||
let database_url = matches.get_one::<String>("databaseurl").unwrap();
|
||||
let domain = matches.get_one::<String>("domain").unwrap();
|
||||
let master_key = matches.get_one::<String>("key").unwrap();
|
||||
|
||||
let smtp_config = config::SmtpOptions {
|
||||
user: String::from(matches.value_of("smtp_user").unwrap_or_default()),
|
||||
password: String::from(matches.value_of("smtp_pwd").unwrap_or_default()),
|
||||
relay: String::from(matches.value_of("smtp_relay").unwrap_or_default()),
|
||||
user: String::from(matches.get_one::<String>("smtp_user").unwrap()),
|
||||
password: String::from(matches.get_one::<String>("smtp_pwd").unwrap()),
|
||||
relay: String::from(matches.get_one::<String>("smtp_relay").unwrap()),
|
||||
};
|
||||
|
||||
// start http server
|
||||
debug!("starting Artix web server on {}:{}", host_addr, host_port);
|
||||
debug!("Starting Artix web server on {}:{}", host_addr, host_port);
|
||||
start_web_server(
|
||||
host_addr,
|
||||
host_port,
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
use diesel::{r2d2::ConnectionManager, PgConnection};
|
||||
@@ -15,7 +16,7 @@ use super::schema::{invitations, package_flags, packages, users};
|
||||
pub type Pool = r2d2::Pool<ConnectionManager<PgConnection>>;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Queryable, Insertable)]
|
||||
#[table_name = "packages"]
|
||||
#[diesel(table_name = packages)]
|
||||
pub struct Package {
|
||||
pub package_name: String,
|
||||
pub gitea_url: String,
|
||||
@@ -23,7 +24,10 @@ pub struct Package {
|
||||
}
|
||||
|
||||
impl Package {
|
||||
pub fn from_details<S: Into<String>, T: Into<String>>(name: S, url: T) -> Self {
|
||||
pub fn from_details<S: Into<String>, T: Into<String>>(
|
||||
name: S,
|
||||
url: T,
|
||||
) -> Self {
|
||||
Package {
|
||||
package_name: name.into(),
|
||||
gitea_url: url.into(),
|
||||
@@ -79,7 +83,7 @@ impl PackageWithFlagView {
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Queryable, Insertable)]
|
||||
#[table_name = "users"]
|
||||
#[diesel(table_name = users)]
|
||||
pub struct User {
|
||||
pub email: String,
|
||||
pub hash: String,
|
||||
@@ -88,7 +92,10 @@ pub struct User {
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn from_details<S: Into<String>, T: Into<String>>(email: S, pwd: T) -> Self {
|
||||
pub fn from_details<S: Into<String>, T: Into<String>>(
|
||||
email: S,
|
||||
pwd: T,
|
||||
) -> Self {
|
||||
User {
|
||||
email: email.into(),
|
||||
hash: pwd.into(),
|
||||
@@ -99,7 +106,7 @@ impl User {
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Queryable, Insertable)]
|
||||
#[table_name = "invitations"]
|
||||
#[diesel(table_name = invitations)]
|
||||
pub(crate) struct Invitation {
|
||||
pub id: Uuid,
|
||||
pub email: String,
|
||||
@@ -115,13 +122,14 @@ where
|
||||
Invitation {
|
||||
id: uuid::Uuid::new_v4(),
|
||||
email: email.into(),
|
||||
expires_at: chrono::Local::now().naive_local() + chrono::Duration::hours(24),
|
||||
expires_at: chrono::Local::now().naive_local()
|
||||
+ chrono::Duration::hours(24),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Queryable, Insertable)]
|
||||
#[table_name = "package_flags"]
|
||||
#[diesel(table_name = package_flags)]
|
||||
pub struct PackageFlag {
|
||||
pub user_email: String,
|
||||
pub package_name: String,
|
||||
@@ -129,7 +137,10 @@ pub struct PackageFlag {
|
||||
}
|
||||
|
||||
impl PackageFlag {
|
||||
pub fn from_details<S: Into<String>, T: Into<String>>(user_email: S, package_name: T) -> Self {
|
||||
pub fn from_details<S: Into<String>, T: Into<String>>(
|
||||
user_email: S,
|
||||
package_name: T,
|
||||
) -> Self {
|
||||
PackageFlag {
|
||||
user_email: user_email.into(),
|
||||
package_name: package_name.into(),
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
use actix_files::Files;
|
||||
@@ -14,7 +15,10 @@ use crate::handlers::{auth, details, index, invitation, packages, register};
|
||||
pub fn config_app(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(
|
||||
web::scope("")
|
||||
.service(web::resource("/api/invitation").route(web::post().to(invitation::post)))
|
||||
.service(
|
||||
web::resource("/api/invitation")
|
||||
.route(web::post().to(invitation::post)),
|
||||
)
|
||||
.service(
|
||||
web::scope("/api/packages")
|
||||
.service(
|
||||
@@ -22,7 +26,9 @@ pub fn config_app(cfg: &mut web::ServiceConfig) {
|
||||
.route(web::get().to(packages::get_packages)),
|
||||
)
|
||||
.service(web::scope("/{package_name}").service(
|
||||
web::resource("").route(web::get().to(packages::get_package_details)),
|
||||
web::resource("").route(
|
||||
web::get().to(packages::get_package_details),
|
||||
),
|
||||
))
|
||||
.default_service(
|
||||
web::route()
|
||||
@@ -46,7 +52,9 @@ pub fn config_app(cfg: &mut web::ServiceConfig) {
|
||||
.route(web::delete().to(auth::logout))
|
||||
.route(web::get().to(auth::ui)),
|
||||
)
|
||||
.service(web::resource("/logout").route(web::post().to(auth::logout)))
|
||||
.service(
|
||||
web::resource("/logout").route(web::post().to(auth::logout)),
|
||||
)
|
||||
.service(
|
||||
web::resource("/flag_package/{package_name}/{package_version}")
|
||||
.route(web::post().to(packages::flag_package))
|
||||
|
@@ -3,11 +3,12 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
use artix_pkglib::prelude::{get_all_packages, Alpm, PackagesResultData};
|
||||
|
||||
use crate::lib::errors::ArtixWebPackageError;
|
||||
use crate::utils::errors::ArtixWebPackageError;
|
||||
|
||||
/// Retrieve all the packages in all the databases in the system
|
||||
/// If `limit` is used then the results are limited to its value
|
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
use actix_web::{
|
||||
@@ -70,9 +71,11 @@ struct UnauthorizedTemplate {
|
||||
impl error::ResponseError for ServiceError {
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
match self {
|
||||
ServiceError::InternalServerError => HttpResponse::InternalServerError()
|
||||
.reason("Internal Server Error, Please try later")
|
||||
.body("Internal Server Error, Please try later"),
|
||||
ServiceError::InternalServerError => {
|
||||
HttpResponse::InternalServerError()
|
||||
.reason("Internal Server Error, Please try later")
|
||||
.body("Internal Server Error, Please try later")
|
||||
}
|
||||
ServiceError::BadRequest(ref message, start_time) => {
|
||||
let t = if let Some(start_time) = start_time {
|
||||
start_time.elapsed().as_millis()
|
||||
@@ -90,15 +93,19 @@ impl error::ResponseError for ServiceError {
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
ServiceError::Unauthorized => HttpResponse::Unauthorized().reason("Unauthorized").body(
|
||||
UnauthorizedTemplate {
|
||||
user_email: String::new(),
|
||||
error_message: String::from("You are not authorized to access this resource"),
|
||||
generation_time: 0,
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
),
|
||||
ServiceError::Unauthorized => {
|
||||
HttpResponse::Unauthorized().reason("Unauthorized").body(
|
||||
UnauthorizedTemplate {
|
||||
user_email: String::new(),
|
||||
error_message: String::from(
|
||||
"You are not authorized to access this resource",
|
||||
),
|
||||
generation_time: 0,
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,9 +121,15 @@ impl From<DBError> for ServiceError {
|
||||
match error {
|
||||
DBError::DatabaseError(kind, info) => {
|
||||
if let DatabaseErrorKind::UniqueViolation = kind {
|
||||
let mut message = info.details().unwrap_or_else(|| info.message()).to_string();
|
||||
let mut message = info
|
||||
.details()
|
||||
.unwrap_or_else(|| info.message())
|
||||
.to_string();
|
||||
if message.contains("Key (email)=") {
|
||||
message = format!("Can not register user, already exists: {}", message);
|
||||
message = format!(
|
||||
"Can not register user, already exists: {}",
|
||||
message
|
||||
);
|
||||
}
|
||||
return ServiceError::BadRequest(message, None);
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
//! `ArtixWeb` Packages Library.
|
@@ -3,6 +3,7 @@
|
||||
|
||||
Copyright (c) 2022 - Artix Linux
|
||||
Copyright (c) 2022 - Oscar Campos <damnwidget@artixlinux.org>
|
||||
Copyright (c) 2022 - Nikola Radojević <nikolar@artixlinux.org>
|
||||
*/
|
||||
|
||||
use askama::Template;
|
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
@@ -0,0 +1 @@
|
||||
max_width = 80
|
Reference in New Issue
Block a user