Move to SPDX licenses (#449)

* Move to SPDX licenses

Found a way to do this without breaking API compat, so here it is, instead of waiting for v3

Resolves MOD-129
Resolves #396

* License URL updates

* what was I thinking

* Do a thing

* Add open source filter

* Remove dead imports

* Borrow

* Update 20220910132835_spdx-licenses.sql

* Add license text route

* Update migration

* Address comments
This commit is contained in:
triphora
2022-11-29 23:53:24 -05:00
committed by GitHub
parent 34688852a4
commit 820519b4f7
15 changed files with 748 additions and 1007 deletions

View File

@@ -688,16 +688,16 @@ pub async fn project_create_inner(
)
})?;
let license_id = models::categories::License::get_id(
let license_id = spdx::Expression::parse(
&project_create_data.license_id,
&mut *transaction,
)
.await?
.ok_or_else(|| {
CreateError::InvalidInput(
"License specified does not exist.".to_string(),
)
.map_err(|err| {
CreateError::InvalidInput(format!(
"Invalid SPDX license identifier: {}",
err
))
})?;
let mut donation_urls = vec![];
if let Some(urls) = &project_create_data.donation_urls {
@@ -744,7 +744,7 @@ pub async fn project_create_inner(
status: status_id,
client_side: client_side_id,
server_side: server_side_id,
license: license_id,
license: license_id.to_string(),
slug: Some(project_create_data.slug),
donation_urls,
gallery_items: gallery_urls

View File

@@ -857,12 +857,18 @@ pub async fn project_edit(
));
}
let license_id = database::models::categories::License::get_id(
license,
&mut *transaction,
)
.await?
.expect("No database entry found for license");
let mut license = license.clone();
if license.to_lowercase() == "arr" {
license = models::projects::DEFAULT_LICENSE_ID.to_string();
}
spdx::Expression::parse(&*license).map_err(|err| {
ApiError::InvalidInput(format!(
"Invalid SPDX license identifier: {}",
err
))
})?;
sqlx::query!(
"
@@ -870,7 +876,7 @@ pub async fn project_edit(
SET license = $1
WHERE (id = $2)
",
license_id as database::models::LicenseId,
license,
id as database::models::ids::ProjectId,
)
.execute(&mut *transaction)

View File

@@ -1,7 +1,7 @@
use super::ApiError;
use crate::database::models;
use crate::database::models::categories::{
DonationPlatform, License, ProjectType, ReportType,
DonationPlatform, ProjectType, ReportType,
};
use crate::util::auth::check_is_admin_from_headers;
use actix_web::{delete, get, put, web, HttpRequest, HttpResponse};
@@ -21,9 +21,8 @@ pub fn config(cfg: &mut web::ServiceConfig) {
.service(game_version_list)
.service(game_version_create)
.service(game_version_delete)
.service(license_create)
.service(license_delete)
.service(license_list)
.service(license_text)
.service(donation_platform_create)
.service(donation_platform_list)
.service(donation_platform_delete)
@@ -302,75 +301,52 @@ pub async fn game_version_delete(
}
#[derive(serde::Serialize)]
pub struct LicenseQueryData {
pub struct License {
short: String,
name: String,
}
#[get("license")]
pub async fn license_list(
pool: web::Data<PgPool>,
) -> Result<HttpResponse, ApiError> {
let results: Vec<LicenseQueryData> = License::list(&**pool)
.await?
.into_iter()
.map(|x| LicenseQueryData {
short: x.short,
name: x.name,
})
.collect();
Ok(HttpResponse::Ok().json(results))
}
pub async fn license_list() -> HttpResponse {
let licenses = spdx::identifiers::LICENSES;
let mut results: Vec<License> = Vec::with_capacity(licenses.len());
#[derive(serde::Deserialize)]
pub struct LicenseData {
name: String,
}
#[put("license/{name}")]
pub async fn license_create(
req: HttpRequest,
pool: web::Data<PgPool>,
license: web::Path<(String,)>,
license_data: web::Json<LicenseData>,
) -> Result<HttpResponse, ApiError> {
check_is_admin_from_headers(req.headers(), &**pool).await?;
let short = license.into_inner().0;
let _id = License::builder()
.short(&short)?
.name(&license_data.name)?
.insert(&**pool)
.await?;
Ok(HttpResponse::NoContent().body(""))
}
#[delete("license/{name}")]
pub async fn license_delete(
req: HttpRequest,
pool: web::Data<PgPool>,
license: web::Path<(String,)>,
) -> Result<HttpResponse, ApiError> {
check_is_admin_from_headers(req.headers(), &**pool).await?;
let name = license.into_inner().0;
let mut transaction =
pool.begin().await.map_err(models::DatabaseError::from)?;
let result = License::remove(&name, &mut transaction).await?;
transaction
.commit()
.await
.map_err(models::DatabaseError::from)?;
if result.is_some() {
Ok(HttpResponse::NoContent().body(""))
} else {
Ok(HttpResponse::NotFound().body(""))
for (short, name, _) in licenses {
results.push(License {
short: short.to_string(),
name: name.to_string(),
});
}
HttpResponse::Ok().json(results)
}
#[derive(serde::Serialize)]
pub struct LicenseText {
body: String,
}
#[get("license/{id}")]
pub async fn license_text(
params: web::Path<(String,)>,
) -> Result<HttpResponse, ApiError> {
let license_id = params.into_inner().0;
if license_id == crate::models::projects::DEFAULT_LICENSE_ID.to_string() {
return Ok(HttpResponse::Ok().json(LicenseText {
body: "All rights reserved unless explicitly stated.".to_string(),
}));
}
if let Some(license) = spdx::license_id(&*license_id) {
return Ok(HttpResponse::Ok().json(LicenseText {
body: license.text().to_string(),
}));
}
Err(ApiError::InvalidInput(
"Invalid SPDX identifier specified".to_string(),
))
}
#[derive(serde::Serialize)]

View File

@@ -35,8 +35,6 @@ pub fn tags_config(cfg: &mut web::ServiceConfig) {
.service(tags::game_version_list)
.service(super::tags::game_version_create)
.service(super::tags::game_version_delete)
.service(super::tags::license_create)
.service(super::tags::license_delete)
.service(super::tags::license_list)
.service(super::tags::donation_platform_create)
.service(super::tags::donation_platform_list)