Skip to content

Commit f21b877

Browse files
authored
Merge pull request #7438 from systeminit/feat-luminork-error-on-create-only
feat(luminork): Error when a user tries to update a readonly property
2 parents 459e219 + a8256f7 commit f21b877

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

lib/dal/src/attribute/attributes.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ use crate::{
3333
Component,
3434
DalContext,
3535
Func,
36+
Prop,
3637
PropKind,
3738
WsEvent,
3839
component::resource::ResourceData,
3940
func::intrinsics::IntrinsicFunc,
41+
prop::PropError,
4042
workspace_snapshot::node_weight::{
4143
NodeWeight,
4244
reason_node_weight::Reason,
@@ -60,10 +62,16 @@ pub enum AttributesError {
6062
AttributeValue(#[from] crate::attribute::value::AttributeValueError),
6163
#[error("attribute value {0} not from component {1}")]
6264
AttributeValueNotFromComponent(AttributeValueId, ComponentId),
65+
#[error(
66+
"cannot update create-only property at path '{0}' when component has a resource attached"
67+
)]
68+
CannotUpdateCreateOnlyProperty(String),
6369
#[error("component error: {0}")]
6470
Component(#[from] crate::ComponentError),
6571
#[error("func error: {0}")]
6672
Func(#[from] crate::FuncError),
73+
#[error("prop error: {0}")]
74+
Prop(#[from] PropError),
6775
#[error("serde json error: {0}")]
6876
SerdeJson(#[from] serde_json::Error),
6977
#[error("source component not found: {0}")]
@@ -214,6 +222,17 @@ pub async fn update_attributes_without_validation(
214222
update_attributes_inner(ctx, component_id, updates).await
215223
}
216224

225+
/// Helper function to check if a prop has the "si_create_only_prop" widget option
226+
fn is_create_only_prop(prop: &Prop) -> bool {
227+
if let Some(widget_options) = &prop.widget_options {
228+
widget_options
229+
.iter()
230+
.any(|option| option.label() == "si_create_only_prop")
231+
} else {
232+
false
233+
}
234+
}
235+
217236
async fn get_before_prop_value_source(
218237
ctx: &DalContext,
219238
av_id: AttributeValueId,
@@ -278,6 +297,20 @@ async fn update_attributes_inner(
278297
// Create the attribute at the given pa th if it does not exist
279298
let path = av_to_set.path();
280299
let target_av_id = av_to_set.clone().vivify(ctx, component_id).await?;
300+
301+
// Check if this is a create-only property and component has a resource
302+
let prop_id = AttributeValue::prop_id(ctx, target_av_id).await?;
303+
let prop = Prop::get_by_id(ctx, prop_id).await?;
304+
if is_create_only_prop(&prop)
305+
&& Component::resource_by_id(ctx, component_id)
306+
.await?
307+
.is_some()
308+
{
309+
return Err(AttributesError::CannotUpdateCreateOnlyProperty(
310+
path.to_string(),
311+
));
312+
}
313+
281314
let before_value_source = get_before_prop_value_source(ctx, target_av_id).await?;
282315
let mut after_value_source: Option<PropValueSource> = None;
283316

lib/luminork-server/src/service/v1/components/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ impl From<JsonRejection> for ComponentsError {
211211
impl crate::service::v1::common::ErrorIntoResponse for ComponentsError {
212212
fn status_and_message(&self) -> (StatusCode, String) {
213213
match self {
214+
ComponentsError::Attribute(
215+
dal::attribute::attributes::AttributesError::CannotUpdateCreateOnlyProperty(_),
216+
) => (StatusCode::PRECONDITION_FAILED, self.to_string()),
214217
ComponentsError::Component(dal::ComponentError::NotFound(_)) => {
215218
(StatusCode::NOT_FOUND, self.to_string())
216219
}

0 commit comments

Comments
 (0)