Skip to content

Add Verions Owner Actions to the API #1947

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 38 additions & 10 deletions src/controllers/krate/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use crate::controllers::prelude::*;
use crate::models::{
Category, Crate, CrateCategory, CrateKeyword, CrateVersions, Keyword, RecentCrateDownloads,
User, Version,
User, Version, VersionOwnerAction,
};
use crate::schema::*;
use crate::views::{
Expand Down Expand Up @@ -105,13 +105,26 @@ pub fn show(req: &mut dyn Request) -> AppResult<Response> {
let conn = req.db_conn()?;
let krate = Crate::by_name(name).first::<Crate>(&*conn)?;

let mut versions_and_publishers: Vec<(Version, Option<User>)> = krate
let mut versions_and_publishers = krate
.all_versions()
.left_outer_join(users::table)
.select((versions::all_columns, users::all_columns.nullable()))
.load(&*conn)?;
.load::<(Version, Option<User>)>(&*conn)?;
versions_and_publishers.sort_by(|a, b| b.0.num.cmp(&a.0.num));
let ids = versions_and_publishers.iter().map(|v| v.0.id).collect();
let versions = versions_and_publishers
.iter()
.map(|(v, _)| v)
.cloned()
.collect::<Vec<_>>();
let versions_publishers_and_audit_actions = versions_and_publishers
.into_iter()
.zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
.map(|((v, pb), aas)| (v, pb, aas))
.collect::<Vec<_>>();
let ids = versions_publishers_and_audit_actions
.iter()
.map(|v| v.0.id)
.collect();

let kws = CrateKeyword::belonging_to(&krate)
.inner_join(keywords::table)
Expand Down Expand Up @@ -149,9 +162,9 @@ pub fn show(req: &mut dyn Request) -> AppResult<Response> {
false,
recent_downloads,
),
versions: versions_and_publishers
versions: versions_publishers_and_audit_actions
.into_iter()
.map(|(v, pb)| v.encodable(&krate.name, pb))
.map(|(v, pb, aas)| v.encodable(&krate.name, pb, aas))
.collect(),
keywords: kws.into_iter().map(Keyword::encodable).collect(),
categories: cats.into_iter().map(Category::encodable).collect(),
Expand Down Expand Up @@ -193,9 +206,15 @@ pub fn versions(req: &mut dyn Request) -> AppResult<Response> {
.select((versions::all_columns, users::all_columns.nullable()))
.load(&*conn)?;
versions_and_publishers.sort_by(|a, b| b.0.num.cmp(&a.0.num));
let versions = versions_and_publishers
.iter()
.map(|(v, _)| v)
.cloned()
.collect::<Vec<_>>();
let versions = versions_and_publishers
.into_iter()
.map(|(v, pb)| v.encodable(crate_name, pb))
.zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
.map(|((v, pb), aas)| v.encodable(crate_name, pb, aas))
.collect();

#[derive(Serialize)]
Expand All @@ -220,7 +239,7 @@ pub fn reverse_dependencies(req: &mut dyn Request) -> AppResult<Response> {

let version_ids: Vec<i32> = rev_deps.iter().map(|dep| dep.version_id).collect();

let versions = versions::table
let versions_and_publishers = versions::table
.filter(versions::id.eq(any(version_ids)))
.inner_join(crates::table)
.left_outer_join(users::table)
Expand All @@ -229,9 +248,18 @@ pub fn reverse_dependencies(req: &mut dyn Request) -> AppResult<Response> {
crates::name,
users::all_columns.nullable(),
))
.load::<(Version, String, Option<User>)>(&*conn)?
.load::<(Version, String, Option<User>)>(&*conn)?;
let versions = versions_and_publishers
.iter()
.map(|(v, _, _)| v)
.cloned()
.collect::<Vec<_>>();
let versions = versions_and_publishers
.into_iter()
.map(|(version, krate_name, user)| version.encodable(&krate_name, user))
.zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
.map(|((version, krate_name, published_by), actions)| {
version.encodable(&krate_name, published_by, actions)
})
.collect();

#[derive(Serialize)]
Expand Down
17 changes: 13 additions & 4 deletions src/controllers/user/me.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use crate::email;
use crate::util::bad_request;
use crate::util::errors::AppError;

use crate::models::{CrateOwner, Email, Follow, NewEmail, OwnerKind, User, Version};
use crate::models::{
CrateOwner, Email, Follow, NewEmail, OwnerKind, User, Version, VersionOwnerAction,
};
use crate::schema::{crate_owners, crates, emails, follows, users, versions};
use crate::views::{EncodableMe, EncodableVersion, OwnedCrate};

Expand Down Expand Up @@ -80,12 +82,19 @@ pub fn updates(req: &mut dyn Request) -> AppResult<Response> {
))
.paginate(&req.query())?
.load::<(Version, String, Option<User>)>(&*conn)?;

let more = data.next_page_params().is_some();
let versions = data.iter().map(|(v, _, _)| v).cloned().collect::<Vec<_>>();
let data = data
.into_iter()
.zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
.map(|((v, cn, pb), voas)| (v, cn, pb, voas))
.collect::<Vec<_>>();

let versions = data
.into_iter()
.map(|(version, crate_name, published_by)| version.encodable(&crate_name, published_by))
.map(|(version, crate_name, published_by, actions)| {
version.encodable(&crate_name, published_by, actions)
})
.collect();

#[derive(Serialize)]
Expand Down Expand Up @@ -234,7 +243,7 @@ pub fn update_email_notifications(req: &mut dyn Request) -> AppResult<Response>
let user = req.user()?;
let conn = req.db_conn()?;

// Build inserts from existing crates beloning to the current user
// Build inserts from existing crates belonging to the current user
let to_insert = CrateOwner::by_owner_kind(OwnerKind::User)
.filter(owner_id.eq(user.id))
.select((crate_id, owner_id, owner_kind, email_notifications))
Expand Down
20 changes: 15 additions & 5 deletions src/controllers/version/deprecated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use crate::controllers::prelude::*;

use crate::models::{Crate, User, Version};
use crate::models::{Crate, User, Version, VersionOwnerAction};
use crate::schema::*;
use crate::views::EncodableVersion;

Expand All @@ -22,7 +22,7 @@ pub fn index(req: &mut dyn Request) -> AppResult<Response> {
.filter_map(|(ref a, ref b)| if *a == "ids[]" { b.parse().ok() } else { None })
.collect::<Vec<i32>>();

let versions = versions::table
let versions_and_publishers = versions::table
.inner_join(crates::table)
.left_outer_join(users::table)
.select((
Expand All @@ -31,9 +31,18 @@ pub fn index(req: &mut dyn Request) -> AppResult<Response> {
users::all_columns.nullable(),
))
.filter(versions::id.eq(any(ids)))
.load::<(Version, String, Option<User>)>(&*conn)?
.load::<(Version, String, Option<User>)>(&*conn)?;
let versions = versions_and_publishers
.iter()
.map(|(v, _, _)| v)
.cloned()
.collect::<Vec<_>>();
let versions = versions_and_publishers
.into_iter()
.map(|(version, crate_name, published_by)| version.encodable(&crate_name, published_by))
.zip(VersionOwnerAction::for_versions(&conn, &versions)?.into_iter())
.map(|((version, crate_name, published_by), actions)| {
version.encodable(&crate_name, published_by, actions)
})
.collect();

#[derive(Serialize)]
Expand All @@ -60,12 +69,13 @@ pub fn show_by_id(req: &mut dyn Request) -> AppResult<Response> {
users::all_columns.nullable(),
))
.first(&*conn)?;
let audit_actions = VersionOwnerAction::by_version(&conn, &version)?;

#[derive(Serialize)]
struct R {
version: EncodableVersion,
}
Ok(req.json(&R {
version: version.encodable(&krate.name, published_by),
version: version.encodable(&krate.name, published_by, audit_actions),
}))
}
4 changes: 3 additions & 1 deletion src/controllers/version/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use crate::controllers::prelude::*;

use crate::models::VersionOwnerAction;
use crate::schema::*;
use crate::views::{EncodableDependency, EncodablePublicUser, EncodableVersion};

Expand Down Expand Up @@ -70,12 +71,13 @@ pub fn show(req: &mut dyn Request) -> AppResult<Response> {
let (version, krate) = version_and_crate(req)?;
let conn = req.db_conn()?;
let published_by = version.published_by(&conn);
let actions = VersionOwnerAction::by_version(&conn, &version)?;

#[derive(Serialize)]
struct R {
version: EncodableVersion,
}
Ok(req.json(&R {
version: version.encodable(&krate.name, published_by),
version: version.encodable(&krate.name, published_by, actions),
}))
}
44 changes: 35 additions & 9 deletions src/models/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ pub enum VersionAction {
Unyank = 2,
}

impl Into<&'static str> for VersionAction {
fn into(self) -> &'static str {
match self {
VersionAction::Publish => "publish",
VersionAction::Yank => "yank",
VersionAction::Unyank => "unyank",
}
}
}

impl Into<String> for VersionAction {
fn into(self) -> String {
let string: &'static str = self.into();

string.into()
}
}

impl FromSql<Integer, Pg> for VersionAction {
fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
match <i32 as FromSql<Integer, Pg>>::from_sql(bytes)? {
Expand Down Expand Up @@ -52,22 +70,30 @@ pub struct VersionOwnerAction {
}

impl VersionOwnerAction {
pub fn all(conn: &PgConnection) -> QueryResult<Vec<VersionOwnerAction>> {
pub fn all(conn: &PgConnection) -> QueryResult<Vec<Self>> {
version_owner_actions::table.load(conn)
}

pub fn by_version_id_and_action(
conn: &PgConnection,
version_id_: i32,
action_: VersionAction,
) -> QueryResult<Vec<VersionOwnerAction>> {
use version_owner_actions::dsl::{action, version_id};
pub fn by_version(conn: &PgConnection, version: &Version) -> QueryResult<Vec<(Self, User)>> {
use version_owner_actions::dsl::version_id;

version_owner_actions::table
.filter(version_id.eq(version_id_))
.filter(action.eq(action_))
.filter(version_id.eq(version.id))
.inner_join(users::table)
.order(version_owner_actions::dsl::id)
.load(conn)
}

pub fn for_versions(
conn: &PgConnection,
versions: &[Version],
) -> QueryResult<Vec<Vec<(Self, User)>>> {
Ok(Self::belonging_to(versions)
.inner_join(users::table)
.order(version_owner_actions::dsl::id)
.load::<(VersionOwnerAction, User)>(conn)?
.grouped_by(versions))
}
}

pub fn insert_version_owner_action(
Expand Down
19 changes: 16 additions & 3 deletions src/models/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use diesel::prelude::*;

use crate::util::{cargo_err, AppResult};

use crate::models::{Crate, Dependency, User};
use crate::models::{Crate, Dependency, User, VersionOwnerAction};
use crate::schema::*;
use crate::views::{EncodableVersion, EncodableVersionLinks};
use crate::views::{EncodableAuditAction, EncodableVersion, EncodableVersionLinks};

// Queryable has a custom implementation below
#[derive(Clone, Identifiable, Associations, Debug, Queryable, Deserialize, Serialize)]
Expand Down Expand Up @@ -38,7 +38,12 @@ pub struct NewVersion {
}

impl Version {
pub fn encodable(self, crate_name: &str, published_by: Option<User>) -> EncodableVersion {
pub fn encodable(
self,
crate_name: &str,
published_by: Option<User>,
audit_actions: Vec<(VersionOwnerAction, User)>,
) -> EncodableVersion {
let Version {
id,
num,
Expand Down Expand Up @@ -71,6 +76,14 @@ impl Version {
},
crate_size,
published_by: published_by.map(User::encodable_public),
audit_actions: audit_actions
.into_iter()
.map(|(audit_action, user)| EncodableAuditAction {
action: audit_action.action.into(),
user: User::encodable_public(user),
time: audit_action.time,
})
.collect(),
}
}

Expand Down
Loading