Skip to content
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

Add createRealmLineage mutation to API #1179

Merged
merged 1 commit into from
Sep 12, 2024
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
3 changes: 2 additions & 1 deletion backend/src/api/model/realm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ use super::block::{Block, BlockValue, SeriesBlock, VideoBlock};
mod mutations;

pub(crate) use mutations::{
ChildIndex, NewRealm, RemovedRealm, UpdateRealm, UpdatedPermissions, UpdatedRealmName, RealmSpecifier,
ChildIndex, NewRealm, RemovedRealm, UpdateRealm, UpdatedPermissions,
UpdatedRealmName, RealmSpecifier, RealmLineageComponent, CreateRealmLineageOutcome,
};


Expand Down
11 changes: 11 additions & 0 deletions backend/src/api/model/realm/mutations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,19 @@ pub(crate) struct RealmSpecifier {
pub(crate) path_segment: String,
}

#[derive(Clone, juniper::GraphQLInputObject)]
pub(crate) struct RealmLineageComponent {
pub(crate) name: String,
pub(crate) path_segment: String,
}

#[derive(juniper::GraphQLObject)]
#[graphql(Context = Context)]
pub(crate) struct RemovedRealm {
parent: Option<Realm>,
}

#[derive(juniper::GraphQLObject)]
pub struct CreateRealmLineageOutcome {
pub num_created: i32,
}
45 changes: 44 additions & 1 deletion backend/src/api/mutation.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use juniper::graphql_object;

use crate::{
api::model::event::RemovedEvent,
api::{err::map_db_err, model::event::RemovedEvent},
auth::AuthContext,
};
use super::{
Expand All @@ -21,6 +21,8 @@ use super::{
UpdatedRealmName,
UpdateRealm,
RealmSpecifier,
RealmLineageComponent,
CreateRealmLineageOutcome,
},
block::{
BlockValue,
Expand Down Expand Up @@ -209,6 +211,47 @@ impl Mutation {
BlockValue::remove(id, context).await
}

/// Basically `mkdir -p` for realms: makes sure the given realm lineage
/// exists, creating the missing realms. Existing realms are *not* updated.
/// Each realm in the given list is the sub-realm of the previous item in
/// the list. The first item is sub-realm of the root realm.
async fn create_realm_lineage(
realms: Vec<RealmLineageComponent>,
context: &Context,
) -> ApiResult<CreateRealmLineageOutcome> {
if context.auth != AuthContext::TrustedExternal {
return Err(not_authorized!("only trusted external applications can use this mutation"));
}

if realms.len() == 0 {
return Ok(CreateRealmLineageOutcome { num_created: 0 });
}

if context.config.general.reserved_paths().any(|r| realms[0].path_segment == r) {
return Err(invalid_input!(key = "realm.path-is-reserved", "path is reserved and cannot be used"));
}

let mut parent_path = String::new();
let mut num_created = 0;
for realm in realms {
let sql = "\
insert into realms (parent, name, path_segment) \
values ((select id from realms where full_path = $1), $2, $3) \
on conflict do nothing";
let res = context.db.execute(sql, &[&parent_path, &realm.name, &realm.path_segment])
.await;
let affected = map_db_err!(res, {
if constraint == "valid_path" => invalid_input!("path invalid"),
})?;
num_created += affected as i32;

parent_path.push('/');
parent_path.push_str(&realm.path_segment);
}

Ok(CreateRealmLineageOutcome { num_created })
}

/// Atomically mount a series into an (empty) realm.
/// Creates all the necessary realms on the path to the target
/// and adds a block with the given series at the leaf.
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ input NewVideoBlock {
showLink: Boolean!
}

type CreateRealmLineageOutcome {
numCreated: Int!
}

"A `Block`: a UI element that belongs to a realm."
interface Block {
id: ID!
Expand Down Expand Up @@ -519,6 +523,13 @@ type Mutation {
updateVideoBlock(id: ID!, set: UpdateVideoBlock!): Block!
"Remove a block from a realm."
removeBlock(id: ID!): RemovedBlock!
"""
Basically `mkdir -p` for realms: makes sure the given realm lineage
exists, creating the missing realms. Existing realms are *not* updated.
Each realm in the given list is the sub-realm of the previous item in
the list. The first item is sub-realm of the root realm.
"""
createRealmLineage(realms: [RealmLineageComponent!]!): CreateRealmLineageOutcome!
"""
Atomically mount a series into an (empty) realm.
Creates all the necessary realms on the path to the target
Expand Down Expand Up @@ -677,6 +688,11 @@ enum ItemType {
REALM
}

input RealmLineageComponent {
name: String!
pathSegment: String!
}

enum EventSortColumn {
TITLE
CREATED
Expand Down
Loading