From 72180ba3847d42e6aaa8b325f811f5cbcee0ed2a Mon Sep 17 00:00:00 2001 From: stack72 Date: Mon, 23 Dec 2024 21:28:20 +0000 Subject: [PATCH] chore(sdf): Migrate module builtin promotion and rejection to v2 endpoints --- app/web/src/store/module.store.ts | 9 +- lib/sdf-server/src/service/module.rs | 7 - .../src/service/module/builtin_module_spec.rs | 82 ----------- .../src/service/module/reject_module.rs | 82 ----------- lib/sdf-server/src/service/v2/module.rs | 6 + .../src/service/v2/module/builtins.rs | 134 ++++++++++++++++++ 6 files changed, 144 insertions(+), 176 deletions(-) delete mode 100644 lib/sdf-server/src/service/module/builtin_module_spec.rs delete mode 100644 lib/sdf-server/src/service/module/reject_module.rs create mode 100644 lib/sdf-server/src/service/v2/module/builtins.rs diff --git a/app/web/src/store/module.store.ts b/app/web/src/store/module.store.ts index 5054aa44a4..1127420cb0 100644 --- a/app/web/src/store/module.store.ts +++ b/app/web/src/store/module.store.ts @@ -1,6 +1,6 @@ import { defineStore } from "pinia"; import * as _ from "lodash-es"; -import { addStoreHooks, ApiRequest } from "@si/vue-lib/pinia"; +import { addStoreHooks, ApiRequest, URLPattern } from "@si/vue-lib/pinia"; import { useWorkspacesStore } from "@/store/workspaces.store"; import { ChangeSetId } from "@/api/sdf/dal/change_set"; import router from "@/router"; @@ -133,7 +133,7 @@ export const useModuleStore = () => { "change-sets", { changeSetId }, "modules", - ]; + ] as URLPattern; const WORKSPACE_API_PREFIX = ["v2", "workspaces", { workspaceId }]; @@ -399,7 +399,7 @@ export const useModuleStore = () => { async REJECT_REMOTE_MODULE(moduleId: ModuleId) { return new ApiRequest<{ success: true }>({ method: "post", - url: "/module/reject_module", + url: API_PREFIX.concat([{ moduleId }, "builtins", "reject"]), params: { id: moduleId, ...getVisibilityParams() }, optimistic: () => { // remove selection from URL @@ -418,8 +418,7 @@ export const useModuleStore = () => { async PROMOTE_TO_BUILTIN(moduleId: ModuleId) { return new ApiRequest<{ success: true }>({ method: "post", - url: "/module/set_as_builtin", - params: { id: moduleId, ...getVisibilityParams() }, + url: API_PREFIX.concat([{ moduleId }, "builtins", "promote"]), optimistic: () => { // remove selection from URL router.replace({ diff --git a/lib/sdf-server/src/service/module.rs b/lib/sdf-server/src/service/module.rs index 3901eb841d..16fdb5d065 100644 --- a/lib/sdf-server/src/service/module.rs +++ b/lib/sdf-server/src/service/module.rs @@ -31,11 +31,9 @@ const PKG_EXTENSION: &str = "sipkg"; const MAX_NAME_SEARCH_ATTEMPTS: usize = 100; pub mod approval_process; -pub mod builtin_module_spec; pub mod get_module; pub mod import_workspace_vote; pub mod install_module; -pub mod reject_module; pub mod remote_module_spec; #[remain::sorted] @@ -247,11 +245,6 @@ pub fn routes() -> Router { "/remote_module_spec", get(remote_module_spec::remote_module_spec), ) - .route( - "/set_as_builtin", - post(builtin_module_spec::promote_to_builtin), - ) - .route("/reject_module", post(reject_module::reject_module)) .route( "/begin_approval_process", post(approval_process::begin_approval_process), diff --git a/lib/sdf-server/src/service/module/builtin_module_spec.rs b/lib/sdf-server/src/service/module/builtin_module_spec.rs deleted file mode 100644 index 918a501490..0000000000 --- a/lib/sdf-server/src/service/module/builtin_module_spec.rs +++ /dev/null @@ -1,82 +0,0 @@ -use axum::{ - extract::{Host, OriginalUri}, - Json, -}; -use dal::{HistoryActor, User, Visibility}; -use module_index_client::ModuleIndexClient; -use serde::{Deserialize, Serialize}; -use ulid::Ulid; - -use crate::{ - extract::{AccessBuilder, HandlerContext, PosthogClient, RawAccessToken}, - service::module::{ModuleError, ModuleResult}, - track, -}; - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct PromoteToBuiltinModuleRequest { - pub id: Ulid, - #[serde(flatten)] - pub visibility: Visibility, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct PromoteToBuiltinModuleResponse { - pub success: bool, -} - -pub async fn promote_to_builtin( - HandlerContext(builder): HandlerContext, - AccessBuilder(request_ctx): AccessBuilder, - RawAccessToken(raw_access_token): RawAccessToken, - PosthogClient(posthog_client): PosthogClient, - OriginalUri(original_uri): OriginalUri, - Host(host_name): Host, - Json(request): Json, -) -> ModuleResult> { - let ctx = builder.build(request_ctx.build(request.visibility)).await?; - - let module_index_url = match ctx.module_index_url() { - Some(url) => url, - None => return Err(ModuleError::ModuleIndexNotConfigured), - }; - - let user = match ctx.history_actor() { - HistoryActor::User(user_pk) => User::get_by_pk(&ctx, *user_pk).await?, - _ => None, - }; - - let (_, created_by_email) = user - .map(|user| (user.name().to_owned(), user.email().to_owned())) - .unwrap_or(( - "unauthenticated user name".into(), - "unauthenticated user email".into(), - )); - - let module_id = request.id; - - let module_index_client = - ModuleIndexClient::new(module_index_url.try_into()?, &raw_access_token); - - module_index_client - .promote_to_builtin(module_id, created_by_email.clone()) - .await?; - - track( - &posthog_client, - &ctx, - &original_uri, - &host_name, - "promote_to_builtin", - serde_json::json!({ - "pkg_id": module_id, - "pkg_promoted_to_builtin_by": created_by_email, - }), - ); - - ctx.commit().await?; - - Ok(Json(PromoteToBuiltinModuleResponse { success: true })) -} diff --git a/lib/sdf-server/src/service/module/reject_module.rs b/lib/sdf-server/src/service/module/reject_module.rs deleted file mode 100644 index 4f09e8466d..0000000000 --- a/lib/sdf-server/src/service/module/reject_module.rs +++ /dev/null @@ -1,82 +0,0 @@ -use axum::{ - extract::{Host, OriginalUri}, - Json, -}; -use dal::{HistoryActor, User, Visibility}; -use module_index_client::ModuleIndexClient; -use serde::{Deserialize, Serialize}; -use ulid::Ulid; - -use crate::{ - extract::{AccessBuilder, HandlerContext, PosthogClient, RawAccessToken}, - service::module::{ModuleError, ModuleResult}, - track, -}; - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct RejectModuleRequest { - pub id: Ulid, - #[serde(flatten)] - pub visibility: Visibility, -} - -#[derive(Deserialize, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct RejectModuleResponse { - pub success: bool, -} - -pub async fn reject_module( - HandlerContext(builder): HandlerContext, - AccessBuilder(request_ctx): AccessBuilder, - RawAccessToken(raw_access_token): RawAccessToken, - PosthogClient(posthog_client): PosthogClient, - OriginalUri(original_uri): OriginalUri, - Host(host_name): Host, - Json(request): Json, -) -> ModuleResult> { - let ctx = builder.build(request_ctx.build(request.visibility)).await?; - - let module_index_url = match ctx.module_index_url() { - Some(url) => url, - None => return Err(ModuleError::ModuleIndexNotConfigured), - }; - - let user = match ctx.history_actor() { - HistoryActor::User(user_pk) => User::get_by_pk(&ctx, *user_pk).await?, - _ => None, - }; - - let (_, created_by_email) = user - .map(|user| (user.name().to_owned(), user.email().to_owned())) - .unwrap_or(( - "unauthenticated user name".into(), - "unauthenticated user email".into(), - )); - - let module_id = request.id; - - let module_index_client = - ModuleIndexClient::new(module_index_url.try_into()?, &raw_access_token); - - module_index_client - .reject_module(module_id, created_by_email.clone()) - .await?; - - track( - &posthog_client, - &ctx, - &original_uri, - &host_name, - "reject_pkg", - serde_json::json!({ - "pkg_id": module_id, - "pkg_rejected_by": created_by_email, - }), - ); - - ctx.commit().await?; - - Ok(Json(RejectModuleResponse { success: true })) -} diff --git a/lib/sdf-server/src/service/v2/module.rs b/lib/sdf-server/src/service/v2/module.rs index e6295aa133..051dbd25bc 100644 --- a/lib/sdf-server/src/service/v2/module.rs +++ b/lib/sdf-server/src/service/v2/module.rs @@ -4,12 +4,14 @@ use axum::{ routing::{get, post}, Router, }; +use dal::UserError; use si_frontend_types as frontend_types; use telemetry::prelude::*; use thiserror::Error; use crate::{service::ApiError, AppState}; +mod builtins; mod contribute; mod list; mod sync; @@ -35,6 +37,8 @@ pub enum ModulesAPIError { Transactions(#[from] dal::TransactionsError), #[error("url parse error: {0}")] UrlParse(#[from] url::ParseError), + #[error("user error: {0}")] + User(#[from] UserError), } impl IntoResponse for ModulesAPIError { @@ -61,4 +65,6 @@ pub fn v2_routes() -> Router { .route("/contribute", post(contribute::contribute)) .route("/sync", get(sync::sync)) .route("/", get(list::list)) + .route("/:module_id/builtins/reject", post(builtins::reject)) + .route("/:module_id/builtins/promote", post(builtins::promote)) } diff --git a/lib/sdf-server/src/service/v2/module/builtins.rs b/lib/sdf-server/src/service/v2/module/builtins.rs new file mode 100644 index 0000000000..92b71dff8d --- /dev/null +++ b/lib/sdf-server/src/service/v2/module/builtins.rs @@ -0,0 +1,134 @@ +use axum::{ + extract::{Host, OriginalUri, Path}, + Json, +}; +use dal::{module::ModuleId, ChangeSetId, HistoryActor, User, WorkspacePk}; +use module_index_client::ModuleIndexClient; +use serde::{Deserialize, Serialize}; + +use crate::{ + extract::{AccessBuilder, HandlerContext, PosthogClient, RawAccessToken}, + track, +}; + +use super::{ModuleAPIResult, ModulesAPIError}; + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct PromoteToBuiltinModuleResponse { + pub success: bool, +} + +pub async fn promote( + HandlerContext(builder): HandlerContext, + AccessBuilder(request_ctx): AccessBuilder, + RawAccessToken(raw_access_token): RawAccessToken, + PosthogClient(posthog_client): PosthogClient, + OriginalUri(original_uri): OriginalUri, + Host(host_name): Host, + Path((_workspace_pk, change_set_id, module_id)): Path<(WorkspacePk, ChangeSetId, ModuleId)>, +) -> ModuleAPIResult> { + let ctx = builder + .build(request_ctx.build(change_set_id.into())) + .await?; + + let module_index_url = match ctx.module_index_url() { + Some(url) => url, + None => return Err(ModulesAPIError::ModuleIndexNotConfigured), + }; + + let user = match ctx.history_actor() { + HistoryActor::User(user_pk) => User::get_by_pk(&ctx, *user_pk).await?, + _ => None, + }; + + let (_, created_by_email) = user + .map(|user| (user.name().to_owned(), user.email().to_owned())) + .unwrap_or(( + "unauthenticated user name".into(), + "unauthenticated user email".into(), + )); + + let module_index_client = + ModuleIndexClient::new(module_index_url.try_into()?, &raw_access_token); + + module_index_client + .promote_to_builtin(module_id.into(), created_by_email.clone()) + .await?; + + track( + &posthog_client, + &ctx, + &original_uri, + &host_name, + "promote_to_builtin", + serde_json::json!({ + "pkg_id": module_id, + "pkg_promoted_to_builtin_by": created_by_email, + }), + ); + + ctx.commit().await?; + + Ok(Json(PromoteToBuiltinModuleResponse { success: true })) +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct RejectModuleResponse { + pub success: bool, +} + +pub async fn reject( + HandlerContext(builder): HandlerContext, + AccessBuilder(request_ctx): AccessBuilder, + RawAccessToken(raw_access_token): RawAccessToken, + PosthogClient(posthog_client): PosthogClient, + OriginalUri(original_uri): OriginalUri, + Host(host_name): Host, + Path((_workspace_pk, change_set_id, module_id)): Path<(WorkspacePk, ChangeSetId, ModuleId)>, +) -> ModuleAPIResult> { + let ctx = builder + .build(request_ctx.build(change_set_id.into())) + .await?; + + let module_index_url = match ctx.module_index_url() { + Some(url) => url, + None => return Err(ModulesAPIError::ModuleIndexNotConfigured), + }; + + let user = match ctx.history_actor() { + HistoryActor::User(user_pk) => User::get_by_pk(&ctx, *user_pk).await?, + _ => None, + }; + + let (_, created_by_email) = user + .map(|user| (user.name().to_owned(), user.email().to_owned())) + .unwrap_or(( + "unauthenticated user name".into(), + "unauthenticated user email".into(), + )); + + let module_index_client = + ModuleIndexClient::new(module_index_url.try_into()?, &raw_access_token); + + module_index_client + .reject_module(module_id.into(), created_by_email.clone()) + .await?; + + track( + &posthog_client, + &ctx, + &original_uri, + &host_name, + "reject_pkg", + serde_json::json!({ + "pkg_id": module_id, + "pkg_rejected_by": created_by_email, + }), + ); + + ctx.commit().await?; + + Ok(Json(RejectModuleResponse { success: true })) +}