From b6340c360dd6a9caf5cdb553a9f11ed63746a0fd Mon Sep 17 00:00:00 2001 From: Ali Naqvi Date: Wed, 22 Apr 2026 11:39:48 +0800 Subject: [PATCH] fix(users): disallow users to update email --- shard.lock | 14 +++--- spec/controllers/users_spec.cr | 52 +++++++++++++++++++++++ src/placeos-rest-api/controllers/users.cr | 3 ++ 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/shard.lock b/shard.lock index 57721e14..fdd4f98e 100644 --- a/shard.lock +++ b/shard.lock @@ -199,7 +199,7 @@ shards: placeos-core: git: https://github.com/placeos/core.git - version: 4.21.0+git.commit.d9cd2dce15d4d1702777fab0c914bb63796d097c + version: 4.21.0+git.commit.bd00013f0c31a0d1a1ff82a1a6f141dc4fd18153 placeos-core-client: # Overridden git: https://github.com/placeos/core-client.git @@ -207,11 +207,11 @@ shards: placeos-driver: git: https://github.com/placeos/driver.git - version: 7.20.2 + version: 7.21.1 placeos-frontend-loader: git: https://github.com/placeos/frontend-loader.git - version: 2.7.1+git.commit.f864116fd95a4db8e2684034e0db06a6ceb52f67 + version: 2.7.1+git.commit.f6a6fb1b2d6f22f5fd312c1247ffce911cf735bb placeos-log-backend: git: https://github.com/place-labs/log-backend.git @@ -219,7 +219,7 @@ shards: placeos-models: git: https://github.com/placeos/models.git - version: 9.86.2 + version: 9.86.3 placeos-resource: git: https://github.com/place-labs/resource.git @@ -243,11 +243,11 @@ shards: redis-cluster: git: https://github.com/place-labs/redis-cluster.cr.git - version: 0.8.10 + version: 0.8.11 redis_service_manager: git: https://github.com/place-labs/redis_service_manager.git - version: 3.3.0 + version: 3.3.1 rendezvous-hash: git: https://github.com/caspiano/rendezvous-hash.git @@ -267,7 +267,7 @@ shards: search-ingest: git: https://github.com/placeos/search-ingest.git - version: 2.11.3+git.commit.48fff0631a5719842d38ff54d5cf7426b1ec90c3 + version: 2.11.3+git.commit.bf3c6a409e8e5685adb42fb7d2a3b2ba8b32c24b secrets-env: # Overridden git: https://github.com/spider-gazelle/secrets-env.git diff --git a/spec/controllers/users_spec.cr b/spec/controllers/users_spec.cr index 1f018e97..837686ca 100644 --- a/spec/controllers/users_spec.cr +++ b/spec/controllers/users_spec.cr @@ -122,6 +122,58 @@ module PlaceOS::Api model.destroy end + + it "does not allow email to be updated" do + model = Model::Generator.user.save! + model.persisted?.should be_true + original_email = model.email.to_s + + id = model.id.as(String) + result = client.patch( + path: File.join(Users.base_route, id), + body: {email: "changed@example.com", name: "Updated Name"}.to_json, + headers: Spec::Authentication.headers + ) + + result.status_code.should eq 200 + response_model = Model::User.from_trusted_json(result.body) + response_model.id.should eq id + response_model.email.to_s.should eq original_email + response_model.name.should eq "Updated Name" + + model.destroy + end + + it "does not allow last_login, login_count, or logged_out_at to be updated" do + model = Model::Generator.user.save! + model.persisted?.should be_true + + original_login_count = model.login_count + original_last_login = model.last_login + original_logged_out_at = model.logged_out_at + + id = model.id.as(String) + result = client.patch( + path: File.join(Users.base_route, id), + body: { + login_count: 999, + last_login: Time.utc.to_unix, + logged_out_at: Time.utc.to_rfc3339, + name: "Still Updated", + }.to_json, + headers: Spec::Authentication.headers + ) + + result.status_code.should eq 200 + response_model = Model::User.from_trusted_json(result.body) + response_model.id.should eq id + response_model.login_count.should eq original_login_count + response_model.last_login.should eq original_last_login + response_model.logged_out_at.should eq original_logged_out_at + response_model.name.should eq "Still Updated" + + model.destroy + end end end diff --git a/src/placeos-rest-api/controllers/users.cr b/src/placeos-rest-api/controllers/users.cr index 9feceec8..68ab1986 100644 --- a/src/placeos-rest-api/controllers/users.cr +++ b/src/placeos-rest-api/controllers/users.cr @@ -244,6 +244,9 @@ module PlaceOS::Api @[AC::Route::PATCH("/:id", body: :new_user)] @[AC::Route::PUT("/:id", body: :new_user)] def update(new_user : JSON::Any) : ::PlaceOS::Model::User + # Prevent modification of user email via this endpoint - [PPT-2459] + new_user.as_h?.try &.delete("email") + # Allow additional attributes to be applied by admins # (the users themselves should not have access to these) body = new_user.to_json