From 22d0bfe15cc91dce6e66288e12cda3471a2ed3f2 Mon Sep 17 00:00:00 2001 From: Raphael Date: Sat, 9 May 2026 20:58:09 +0200 Subject: [PATCH 1/8] feat: added readme user migration --- .../20260509183408_add_readme_to_user.rb | 7 ++++ db/schema_migrations/20260509183408 | 1 + db/structure.sql | 34 +++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 db/migrate/20260509183408_add_readme_to_user.rb create mode 100644 db/schema_migrations/20260509183408 diff --git a/db/migrate/20260509183408_add_readme_to_user.rb b/db/migrate/20260509183408_add_readme_to_user.rb new file mode 100644 index 00000000..ee10e561 --- /dev/null +++ b/db/migrate/20260509183408_add_readme_to_user.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddReadmeToUser < Code0::ZeroTrack::Database::Migration[1.0] + def change + add_column :users, :readme, :text, null: true + end +end diff --git a/db/schema_migrations/20260509183408 b/db/schema_migrations/20260509183408 new file mode 100644 index 00000000..d494d0c2 --- /dev/null +++ b/db/schema_migrations/20260509183408 @@ -0,0 +1 @@ +80d9fdf9c4750b00b13bd15ea77bb053c3adf998670c519fb3f49b23ee029511 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 7ce0a9a3..12c68332 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -830,6 +830,24 @@ CREATE SEQUENCE user_identities_id_seq ALTER SEQUENCE user_identities_id_seq OWNED BY user_identities.id; +CREATE TABLE user_organization_pins ( + id bigint NOT NULL, + user_id bigint NOT NULL, + organization_id bigint NOT NULL, + priority integer NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL +); + +CREATE SEQUENCE user_organization_pins_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE user_organization_pins_id_seq OWNED BY user_organization_pins.id; + CREATE TABLE user_sessions ( id bigint NOT NULL, user_id bigint NOT NULL, @@ -860,6 +878,7 @@ CREATE TABLE users ( admin boolean DEFAULT false NOT NULL, totp_secret text, email_verified_at timestamp with time zone, + readme text, CONSTRAINT check_3bedaaa612 CHECK ((char_length(email) <= 255)), CONSTRAINT check_56606ce552 CHECK ((char_length(username) <= 50)), CONSTRAINT check_60346c5299 CHECK ((char_length(lastname) <= 50)), @@ -953,6 +972,8 @@ ALTER TABLE ONLY translations ALTER COLUMN id SET DEFAULT nextval('translations_ ALTER TABLE ONLY user_identities ALTER COLUMN id SET DEFAULT nextval('user_identities_id_seq'::regclass); +ALTER TABLE ONLY user_organization_pins ALTER COLUMN id SET DEFAULT nextval('user_organization_pins_id_seq'::regclass); + ALTER TABLE ONLY user_sessions ALTER COLUMN id SET DEFAULT nextval('user_sessions_id_seq'::regclass); ALTER TABLE ONLY users ALTER COLUMN id SET DEFAULT nextval('users_id_seq'::regclass); @@ -1095,6 +1116,9 @@ ALTER TABLE ONLY translations ALTER TABLE ONLY user_identities ADD CONSTRAINT user_identities_pkey PRIMARY KEY (id); +ALTER TABLE ONLY user_organization_pins + ADD CONSTRAINT user_organization_pins_pkey PRIMARY KEY (id); + ALTER TABLE ONLY user_sessions ADD CONSTRAINT user_sessions_pkey PRIMARY KEY (id); @@ -1253,6 +1277,10 @@ CREATE INDEX index_user_identities_on_user_id ON user_identities USING btree (us CREATE UNIQUE INDEX index_user_identities_on_user_id_and_provider_id ON user_identities USING btree (user_id, provider_id); +CREATE UNIQUE INDEX index_user_organization_pins_on_user_id_and_organization_id ON user_organization_pins USING btree (user_id, organization_id); + +CREATE UNIQUE INDEX index_user_organization_pins_on_user_id_and_priority ON user_organization_pins USING btree (user_id, priority); + CREATE UNIQUE INDEX index_user_sessions_on_token ON user_sessions USING btree (token); CREATE INDEX index_user_sessions_on_user_id ON user_sessions USING btree (user_id); @@ -1263,6 +1291,9 @@ CREATE UNIQUE INDEX "index_users_on_LOWER_username" ON users USING btree (lower( CREATE UNIQUE INDEX index_users_on_totp_secret ON users USING btree (totp_secret) WHERE (totp_secret IS NOT NULL); +ALTER TABLE ONLY user_organization_pins + ADD CONSTRAINT fk_rails_036679312e FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + ALTER TABLE ONLY node_parameters ADD CONSTRAINT fk_rails_0d79310cfa FOREIGN KEY (node_function_id) REFERENCES node_functions(id) ON DELETE CASCADE; @@ -1338,6 +1369,9 @@ ALTER TABLE ONLY flow_types ALTER TABLE ONLY namespace_role_project_assignments ADD CONSTRAINT fk_rails_69066bda8f FOREIGN KEY (project_id) REFERENCES namespace_projects(id); +ALTER TABLE ONLY user_organization_pins + ADD CONSTRAINT fk_rails_6b125cdf79 FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; + ALTER TABLE ONLY namespace_member_roles ADD CONSTRAINT fk_rails_6c0d5a04c4 FOREIGN KEY (member_id) REFERENCES namespace_members(id) ON DELETE CASCADE; From 92af74a21ac0a9c5da08c185ff1918655fbb5c48 Mon Sep 17 00:00:00 2001 From: Raphael Date: Sat, 9 May 2026 20:58:17 +0200 Subject: [PATCH 2/8] docs: regen with readme --- docs/graphql/mutation/usersupdate.md | 1 + docs/graphql/object/user.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/graphql/mutation/usersupdate.md b/docs/graphql/mutation/usersupdate.md index d27a05e0..3aff8dae 100644 --- a/docs/graphql/mutation/usersupdate.md +++ b/docs/graphql/mutation/usersupdate.md @@ -16,6 +16,7 @@ Update an existing user. | `mfa` | [`MfaInput`](../input_object/mfainput.md) | The data of the mfa validation | | `password` | [`String`](../scalar/string.md) | New password for the user. | | `passwordRepeat` | [`String`](../scalar/string.md) | New password repeat for the user to check for typos, required if password is set. | +| `readme` | [`String`](../scalar/string.md) | New readme for the user. | | `userId` | [`UserID!`](../scalar/userid.md) | ID of the user to update. | | `username` | [`String`](../scalar/string.md) | New username for the user. | diff --git a/docs/graphql/object/user.md b/docs/graphql/object/user.md index 16ca68de..0b8f27af 100644 --- a/docs/graphql/object/user.md +++ b/docs/graphql/object/user.md @@ -20,6 +20,7 @@ Represents a user | `mfaStatus` | [`MfaStatus`](../object/mfastatus.md) | Multi-factor authentication status of this user | | `namespace` | [`Namespace`](../object/namespace.md) | Namespace of this user | | `namespaceMemberships` | [`NamespaceMemberConnection!`](../object/namespacememberconnection.md) | Namespace Memberships of this user | +| `readme` | [`String`](../scalar/string.md) | Readme of the user | | `sessions` | [`UserSessionConnection!`](../object/usersessionconnection.md) | Sessions of this user | | `updatedAt` | [`Time!`](../scalar/time.md) | Time when this User was last updated | | `userAbilities` | [`UserUserAbilities!`](../object/useruserabilities.md) | Abilities for the current user on this User | From a20cc600de7691ef9ae81e9c8641c7de1efa5ed6 Mon Sep 17 00:00:00 2001 From: Raphael Date: Sat, 9 May 2026 20:58:27 +0200 Subject: [PATCH 3/8] feat: added tests for readme presence --- spec/graphql/types/user_type_spec.rb | 1 + .../graphql/mutation/users/update_spec.rb | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb index 361d0193..e27bba55 100644 --- a/spec/graphql/types/user_type_spec.rb +++ b/spec/graphql/types/user_type_spec.rb @@ -11,6 +11,7 @@ namespace firstname lastname + readme admin namespaceMemberships avatarPath diff --git a/spec/requests/graphql/mutation/users/update_spec.rb b/spec/requests/graphql/mutation/users/update_spec.rb index 8fdf21cc..bf59034f 100644 --- a/spec/requests/graphql/mutation/users/update_spec.rb +++ b/spec/requests/graphql/mutation/users/update_spec.rb @@ -147,6 +147,45 @@ end end + context 'when updating readme' do + let(:mutation) do + <<~QUERY + mutation($input: UsersUpdateInput!) { + usersUpdate(input: $input) { + #{error_query} + user { + id + readme + } + } + } + QUERY + end + + let(:input) do + { + userId: current_user.to_global_id.to_s, + readme: "# Hello\n\nThis is my profile README.", + } + end + + it 'updates the user readme' do + expect(graphql_data_at(:users_update, :user, :id)).to be_present + expect(graphql_data_at(:users_update, :user, :readme)).to eq(input[:readme]) + expect(current_user.reload.readme).to eq(input[:readme]) + + is_expected.to create_audit_event( + :user_updated, + author_id: current_user.id, + entity_id: current_user.id, + entity_type: 'User', + details: { readme: input[:readme] }, + target_id: current_user.id, + target_type: 'User' + ) + end + end + context 'when user name is taken' do let(:existing_user) { create(:user) } let(:input) do From a036146baa866fd1faf9a6237a1aac2215ceaf60 Mon Sep 17 00:00:00 2001 From: Raphael Date: Sat, 9 May 2026 20:58:53 +0200 Subject: [PATCH 4/8] feat: added readme to graphql update user servcie --- app/graphql/mutations/users/update.rb | 1 + app/graphql/types/user_type.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/app/graphql/mutations/users/update.rb b/app/graphql/mutations/users/update.rb index d4d1efc3..96e78b94 100644 --- a/app/graphql/mutations/users/update.rb +++ b/app/graphql/mutations/users/update.rb @@ -20,6 +20,7 @@ class Update < BaseMutation String, required: false, description: 'New password repeat for the user to check for typos, required if password is set.' + argument :readme, String, required: false, description: 'New readme for the user.' argument :username, String, required: false, description: 'New username for the user.' argument :mfa, Types::Input::MfaInput, required: false, description: 'The data of the mfa validation' diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb index 4e2f427e..dce975f2 100644 --- a/app/graphql/types/user_type.rb +++ b/app/graphql/types/user_type.rb @@ -19,6 +19,7 @@ class UserType < Types::BaseObject authorize: :read_email field :firstname, String, null: true, description: 'Firstname of the user' field :lastname, String, null: true, description: 'Lastname of the user' + field :readme, String, null: true, description: 'Readme of the user' field :username, String, null: false, description: 'Username of the user' field :namespace_memberships, Types::NamespaceMemberType.connection_type, From a43a9887fdbf808da591f020c14cdda10dc46cc7 Mon Sep 17 00:00:00 2001 From: Raphael Date: Sat, 9 May 2026 21:31:05 +0200 Subject: [PATCH 5/8] drop: removed organization pin schema --- db/structure.sql | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/db/structure.sql b/db/structure.sql index 12c68332..fcf3dee3 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -830,24 +830,6 @@ CREATE SEQUENCE user_identities_id_seq ALTER SEQUENCE user_identities_id_seq OWNED BY user_identities.id; -CREATE TABLE user_organization_pins ( - id bigint NOT NULL, - user_id bigint NOT NULL, - organization_id bigint NOT NULL, - priority integer NOT NULL, - created_at timestamp with time zone NOT NULL, - updated_at timestamp with time zone NOT NULL -); - -CREATE SEQUENCE user_organization_pins_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - -ALTER SEQUENCE user_organization_pins_id_seq OWNED BY user_organization_pins.id; - CREATE TABLE user_sessions ( id bigint NOT NULL, user_id bigint NOT NULL, @@ -972,8 +954,6 @@ ALTER TABLE ONLY translations ALTER COLUMN id SET DEFAULT nextval('translations_ ALTER TABLE ONLY user_identities ALTER COLUMN id SET DEFAULT nextval('user_identities_id_seq'::regclass); -ALTER TABLE ONLY user_organization_pins ALTER COLUMN id SET DEFAULT nextval('user_organization_pins_id_seq'::regclass); - ALTER TABLE ONLY user_sessions ALTER COLUMN id SET DEFAULT nextval('user_sessions_id_seq'::regclass); ALTER TABLE ONLY users ALTER COLUMN id SET DEFAULT nextval('users_id_seq'::regclass); @@ -1116,9 +1096,6 @@ ALTER TABLE ONLY translations ALTER TABLE ONLY user_identities ADD CONSTRAINT user_identities_pkey PRIMARY KEY (id); -ALTER TABLE ONLY user_organization_pins - ADD CONSTRAINT user_organization_pins_pkey PRIMARY KEY (id); - ALTER TABLE ONLY user_sessions ADD CONSTRAINT user_sessions_pkey PRIMARY KEY (id); @@ -1277,10 +1254,6 @@ CREATE INDEX index_user_identities_on_user_id ON user_identities USING btree (us CREATE UNIQUE INDEX index_user_identities_on_user_id_and_provider_id ON user_identities USING btree (user_id, provider_id); -CREATE UNIQUE INDEX index_user_organization_pins_on_user_id_and_organization_id ON user_organization_pins USING btree (user_id, organization_id); - -CREATE UNIQUE INDEX index_user_organization_pins_on_user_id_and_priority ON user_organization_pins USING btree (user_id, priority); - CREATE UNIQUE INDEX index_user_sessions_on_token ON user_sessions USING btree (token); CREATE INDEX index_user_sessions_on_user_id ON user_sessions USING btree (user_id); @@ -1291,9 +1264,6 @@ CREATE UNIQUE INDEX "index_users_on_LOWER_username" ON users USING btree (lower( CREATE UNIQUE INDEX index_users_on_totp_secret ON users USING btree (totp_secret) WHERE (totp_secret IS NOT NULL); -ALTER TABLE ONLY user_organization_pins - ADD CONSTRAINT fk_rails_036679312e FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; - ALTER TABLE ONLY node_parameters ADD CONSTRAINT fk_rails_0d79310cfa FOREIGN KEY (node_function_id) REFERENCES node_functions(id) ON DELETE CASCADE; @@ -1369,9 +1339,6 @@ ALTER TABLE ONLY flow_types ALTER TABLE ONLY namespace_role_project_assignments ADD CONSTRAINT fk_rails_69066bda8f FOREIGN KEY (project_id) REFERENCES namespace_projects(id); -ALTER TABLE ONLY user_organization_pins - ADD CONSTRAINT fk_rails_6b125cdf79 FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; - ALTER TABLE ONLY namespace_member_roles ADD CONSTRAINT fk_rails_6c0d5a04c4 FOREIGN KEY (member_id) REFERENCES namespace_members(id) ON DELETE CASCADE; From 8f388dc8a4be1b5648576ed88d6ebf9615e681d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20G=C3=B6tz?= <52959657+raphael-goetz@users.noreply.github.com> Date: Sun, 10 May 2026 08:00:11 +0200 Subject: [PATCH 6/8] Update db/migrate/20260509183408_add_readme_to_user.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Niklas van Schrick Signed-off-by: Raphael Götz <52959657+raphael-goetz@users.noreply.github.com> --- db/migrate/20260509183408_add_readme_to_user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20260509183408_add_readme_to_user.rb b/db/migrate/20260509183408_add_readme_to_user.rb index ee10e561..7a0e2106 100644 --- a/db/migrate/20260509183408_add_readme_to_user.rb +++ b/db/migrate/20260509183408_add_readme_to_user.rb @@ -2,6 +2,6 @@ class AddReadmeToUser < Code0::ZeroTrack::Database::Migration[1.0] def change - add_column :users, :readme, :text, null: true + add_column :users, :readme, :text, null: true, limit: 5000 end end From 123640254dfa2a0472796d4a7adfaa5e27a3ef8c Mon Sep 17 00:00:00 2001 From: Raphael Date: Sun, 10 May 2026 09:59:17 +0200 Subject: [PATCH 7/8] feat: merged readme test into existing rspec --- .../graphql/mutation/users/update_spec.rb | 45 +++---------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/spec/requests/graphql/mutation/users/update_spec.rb b/spec/requests/graphql/mutation/users/update_spec.rb index bf59034f..772cd58b 100644 --- a/spec/requests/graphql/mutation/users/update_spec.rb +++ b/spec/requests/graphql/mutation/users/update_spec.rb @@ -13,6 +13,7 @@ user { id username + readme admin } } @@ -26,6 +27,7 @@ { userId: current_user.to_global_id.to_s, username: name, + readme: "# Hello\n\nThis is my profile README.", } end @@ -38,16 +40,18 @@ it 'updates user' do expect(graphql_data_at(:users_update, :user, :id)).to be_present + expect(graphql_data_at(:users_update, :user, :readme)).to be_present user = SagittariusSchema.object_from_id(graphql_data_at(:users_update, :user, :id)) expect(user.username).to eq(input[:username]) + expect(user.readme).to eq(input[:readme]) is_expected.to create_audit_event( :user_updated, author_id: current_user.id, entity_id: user.id, entity_type: 'User', - details: { username: input[:username] }, + details: { username: input[:username], readme: input[:readme] }, target_id: user.id, target_type: 'User' ) @@ -147,45 +151,6 @@ end end - context 'when updating readme' do - let(:mutation) do - <<~QUERY - mutation($input: UsersUpdateInput!) { - usersUpdate(input: $input) { - #{error_query} - user { - id - readme - } - } - } - QUERY - end - - let(:input) do - { - userId: current_user.to_global_id.to_s, - readme: "# Hello\n\nThis is my profile README.", - } - end - - it 'updates the user readme' do - expect(graphql_data_at(:users_update, :user, :id)).to be_present - expect(graphql_data_at(:users_update, :user, :readme)).to eq(input[:readme]) - expect(current_user.reload.readme).to eq(input[:readme]) - - is_expected.to create_audit_event( - :user_updated, - author_id: current_user.id, - entity_id: current_user.id, - entity_type: 'User', - details: { readme: input[:readme] }, - target_id: current_user.id, - target_type: 'User' - ) - end - end - context 'when user name is taken' do let(:existing_user) { create(:user) } let(:input) do From 2c662ac32530d2a7baaf1570e0ef50e2ca94682b Mon Sep 17 00:00:00 2001 From: Raphael Date: Sun, 10 May 2026 10:01:21 +0200 Subject: [PATCH 8/8] feat: added limit to schema dump --- db/structure.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/structure.sql b/db/structure.sql index fcf3dee3..55ef764b 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -861,6 +861,7 @@ CREATE TABLE users ( totp_secret text, email_verified_at timestamp with time zone, readme text, + CONSTRAINT check_11461c37fb CHECK ((char_length(readme) <= 5000)), CONSTRAINT check_3bedaaa612 CHECK ((char_length(email) <= 255)), CONSTRAINT check_56606ce552 CHECK ((char_length(username) <= 50)), CONSTRAINT check_60346c5299 CHECK ((char_length(lastname) <= 50)),