diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 2f3d529..81a28c1 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -13,7 +13,7 @@ jobs: # Service containers to run with `runner-job` services: postgres: - image: postgis/postgis:16-3.5 + image: renatolond/pg_uuidv7:v1.6.0 # Provide the password for postgres env: POSTGRES_PASSWORD: postgres @@ -40,7 +40,7 @@ jobs: - name: Create needed user run: PGPASSWORD=postgres createuser -U postgres -h localhost postgres_password - name: Create needed extensions - run: PGPASSWORD=postgres psql -h localhost -U postgres -c "CREATE EXTENSION citext" retromeet_test + run: PGPASSWORD=postgres psql -h localhost -U postgres -c "CREATE EXTENSION citext" retromeet_test && PGPASSWORD=postgres psql -h localhost -U postgres -c "CREATE EXTENSION pg_uuidv7" retromeet_test # We don't need to create the extension because it's already in the image # && PGPASSWORD=postgres psql -h localhost -U postgres -c "CREATE EXTENSION postgis" retromeet_test - name: Setup the database diff --git a/README.md b/README.md index 5cf8f6d..106f7f4 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ There's a [pronto](https://github.com/prontolabs/pronto) github action running o ### Setup -RetroMeet requires Postgresql >= 16.0 (it might work with a lower version than that, but it is not guaranteed) and PostGIS >= 3.4 (again, might work with a lower version, but not guaranteed). +RetroMeet requires Postgresql >= 16.0 (it might work with a lower version than that, but it is not guaranteed), PostGIS >= 3.4 (again, might work with a lower version, but not guaranteed) and the [pg_uuidv7](https://github.com/fboulnois/pg_uuidv7) extension. First, we need to set up the database. RetroMeet uses [rodauth](https://github.com/jeremyevans/rodauth), the following instructions will create the needed users, database and extensions needed for roda. 1. Create two users: @@ -36,6 +36,10 @@ psql -U postgres -c "CREATE EXTENSION citext" retromeet_dev ```sh psql -U postgres -c "CREATE EXTENSION postgis" retromeet_dev ``` +1. Load the pg_uuidv7 extension: +```sh +psql -U postgres -c "CREATE EXTENSION pg_uuidv7" retromeet_dev +``` 1. Give the password user temporary rights to the schema: ```sh psql -U postgres -c "GRANT CREATE ON SCHEMA public TO retromeet_password" retromeet_dev @@ -56,6 +60,7 @@ The same setup needs to be done for the test database, replacing `retromeet_dev` createdb -U postgres -O retromeet retromeet_test psql -U postgres -c "CREATE EXTENSION citext" retromeet_test psql -U postgres -c "CREATE EXTENSION postgis" retromeet_test +psql -U postgres -c "CREATE EXTENSION pg_uuidv7" retromeet_test psql -U postgres -c "GRANT CREATE ON SCHEMA public TO retromeet_password" retromeet_test RACK_ENV=test rake db:setup psql -U postgres -c "REVOKE CREATE ON SCHEMA public FROM retromeet_password" retromeet_test diff --git a/app/api/authenticated/listing.rb b/app/api/authenticated/listing.rb index 54bbbcc..0086e78 100644 --- a/app/api/authenticated/listing.rb +++ b/app/api/authenticated/listing.rb @@ -15,7 +15,7 @@ class Listing < Grape::API namespace :listing do get "/" do profiles = Persistence::Repository::Listing.nearby(account_id: rodauth.session[:account_id], max_distance_in_meters: params[:max_distance] * 1_000) - present profiles, with: Entities::OtherProfileInfos, only: [{ profiles: %i[display_name account_id age genders orientations relationship_status location_display_name location_distance] }] + present profiles, with: Entities::OtherProfileInfos, only: [{ profiles: %i[display_name id age genders orientations relationship_status location_display_name location_distance] }] end end end diff --git a/app/api/authenticated/profile.rb b/app/api/authenticated/profile.rb index efd227e..af99d03 100644 --- a/app/api/authenticated/profile.rb +++ b/app/api/authenticated/profile.rb @@ -21,7 +21,7 @@ class Profile < Grape::API produces: Authenticated::PRODUCES, consumes: Authenticated::CONSUMES get :complete do - profile_info = Persistence::Repository::Account.profile_info(account_id: rodauth.session[:account_id]) + profile_info = Persistence::Repository::Account.profile_info(id: rodauth.session[:profile_id]) Entities::ProfileInfo.represent(profile_info) end @@ -58,7 +58,7 @@ class Profile < Grape::API error!({ error: :AT_LEAST_ONE_PARAMETER_NEEDED, detail: "You need to provide at least one parameter to be changed, none given" }, :bad_request) if declared_params.empty? Persistence::Repository::Account.update_profile_info(account_id: rodauth.session[:account_id], **declared_params) - profile_info = Persistence::Repository::Account.profile_info(account_id: rodauth.session[:account_id]) + profile_info = Persistence::Repository::Account.profile_info(id: rodauth.session[:profile_id]) status :ok Entities::ProfileInfo.represent(profile_info, only: declared_params.keys.map(&:to_sym)) end @@ -78,13 +78,13 @@ class Profile < Grape::API error!({ error: :UNEXPECTED_RESULTS_SIZE, detail: "Expected to have exactly one location with the given name, had #{results.size} instead" }, :unprocessable_content) if results.size != 1 Persistence::Repository::Account.update_profile_location(account_id: rodauth.session[:account_id], location_result: results.first) - profile_info = Persistence::Repository::Account.profile_info(account_id: rodauth.session[:account_id]) + profile_info = Persistence::Repository::Account.profile_info(id: rodauth.session[:profile_id]) status :ok Entities::ProfileInfo.represent(profile_info, only: %i[location_display_name]) end namespace ":id" do params do - requires :id, type: Integer + requires :id, type: String, regexp: /\A[0-9A-F]{8}-[0-9A-F]{4}-7[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}\z/i end desc "Returns the complete profile information for the requested account id.", @@ -93,7 +93,7 @@ class Profile < Grape::API produces: Authenticated::PRODUCES, consumes: Authenticated::CONSUMES get :complete do - profile_info = Persistence::Repository::Account.profile_info(account_id: params[:id]) + profile_info = Persistence::Repository::Account.profile_info(id: params[:id]) error!({ error: :PROFILE_NOT_FOUND, detail: "The requested profile does not exist or you don't have permission to see it" }, :not_found) unless profile_info Entities::OtherProfileInfo.represent(profile_info) diff --git a/app/api/entities/other_profile_info.rb b/app/api/entities/other_profile_info.rb index dee8199..bf858ca 100644 --- a/app/api/entities/other_profile_info.rb +++ b/app/api/entities/other_profile_info.rb @@ -17,7 +17,7 @@ class OtherProfileInfo < Grape::Entity distance / 1_000 end end - expose :account_id, documentation: { type: Integer } + expose :id, documentation: { type: String } expose :display_name, documentation: { type: String } expose :about_me, documentation: { type: String } expose :genders, documentation: { type: String, is_array: true } diff --git a/app/api/rodauth_middleware.rb b/app/api/rodauth_middleware.rb index 50e8902..8d2868e 100644 --- a/app/api/rodauth_middleware.rb +++ b/app/api/rodauth_middleware.rb @@ -16,7 +16,7 @@ class RodauthMiddleware < Roda after_create_account do display_name = account[:email].split("@", 2).first - Database.connection[:account_informations].insert(account_id: account[:id], display_name:) + Persistence::Repository::Account.create_profile(account_id: account[:id], display_name:) end end @@ -25,6 +25,7 @@ class RodauthMiddleware < Roda r.rodauth rodauth.require_authentication rodauth.check_active_session + rodauth.session[:profile_id] = Persistence::Repository::Account.profile_id_from_account_id(account_id: rodauth.session[:account_id]) env["rodauth"] = rodauth end end diff --git a/app/persistence/repository/account.rb b/app/persistence/repository/account.rb index 19da3cc..abd6770 100644 --- a/app/persistence/repository/account.rb +++ b/app/persistence/repository/account.rb @@ -92,60 +92,73 @@ module Account ].freeze class << self + # @param account_id [Integer] An id for an account + def profile_id_from_account_id(account_id:) + profiles.where(account_id:).get(:id) + end + # Returns profile information for a given account # - # @param account_id [Integer] An id for an account + # @param id [Integer] An id for a profile, it should be an UUID # @return [Hash{Symbol => Object}] A record containing +account_id+, +created_at+ and +display_name+ - def profile_info(account_id:) - account_informations.left_join(:locations, id: :location_id) - .where(account_id:) - .select_all(:account_informations) - # TODO: (renatolond, 2024-11-14) Filter the location display name for only the users' language and the fallback one - .select_append(Sequel[:locations][:display_name].as(:location_display_name)) - .first + def profile_info(id:) + profiles.left_join(:locations, id: :location_id) + .where(Sequel[:profiles][:id] => id) + .select_all(:profiles) + # TODO: (renatolond, 2024-11-14) Filter the location display name for only the users' language and the fallback one + .select_append(Sequel[:locations][:display_name].as(:location_display_name)) + .first end # Returns basic profile information for a given account # - # @param account_id [Integer] An id for an account + # @param account_id (see .profile_id_from_account_id) # @return [Hash{Symbol => Object}] A record containing +account_id+, +created_at+ and +display_name+ def basic_profile_info(account_id:) - account_informations.where(account_id:).select(:created_at, :display_name, :account_id).first + profiles.where(account_id:).select(:created_at, :display_name, :account_id).first end # Updates the profile information for a given account # Does not validate argument names passed to +args+, so if not validated before-hand can raise an exception - # @param account_id (see .profile_info) + # @param account_id (see .profile_id_from_account_id) # @param args [Hash{Symbol => Object}] A hash containing the fields to be updated. Will not be verified for validity. # @return [void] def update_profile_info(account_id:, **args) args["languages"] = Sequel.pg_array(args["languages"], :languages) if args.key?("languages") && args["languages"] args["genders"] = Sequel.pg_array(args["genders"], :genders) if args.key?("genders") && args["genders"] args["orientations"] = Sequel.pg_array(args["orientations"], :orientations) if args.key?("orientations") && args["orientations"] - account_informations.where(account_id:).update(args) + profiles.where(account_id:).update(args) end # Updates the profile location for a given account - # @param account_id (see .profile_info) + # @param account_id (see .profile_id_from_account_id) # @param location_result (see Persistence::Repository::Location.upsert_location) # @return [void] def update_profile_location(account_id:, location_result:) location_id = Persistence::Repository::Location.upsert_location(location_result:) - account_informations.where(account_id:).update(location_id:) + profiles.where(account_id:).update(location_id:) end + # @param account_id (see .profile_id_from_account_id) # @return [String] def profile_location(account_id:) - account_informations.inner_join(:locations, id: :location_id) - .where(account_id:) - .get(Sequel[:locations][:geom]) + profiles.inner_join(:locations, id: :location_id) + .where(account_id:) + .get(Sequel[:locations][:geom]) + end + + # @param account_id (see .profile_id_from_account_id) + # @param display_name [String] the display name for the profile + # @return [void] + def create_profile(account_id:, display_name:) + profiles.insert(account_id:, display_name:) end private # @return [Sequel::Postgres::Dataset] - def account_informations - Database.connection[:account_informations] + def profiles + Database.connection[:profiles] end end end diff --git a/app/persistence/repository/listing.rb b/app/persistence/repository/listing.rb index f6a18ae..c0edf21 100644 --- a/app/persistence/repository/listing.rb +++ b/app/persistence/repository/listing.rb @@ -18,9 +18,9 @@ def nearby(account_id:, min_account_id: nil, max_distance_in_meters: 5_000) .select_append(:id, Sequel[:display_name].as(:location_display_name)) .where(Sequel.function(:ST_DWithin, Sequel.lit("geom::geography"), Sequel.lit("?::geography", profile_location), max_distance_in_meters)) .order(:dist) - accounts = account_informations.inner_join(location_subquery, id: :location_id) - .select(:display_name, :account_id, :birth_date, :genders, :orientations, :relationship_status, :location_display_name, Sequel[:dist].as(:location_distance)) - .exclude(Sequel[:account_informations][:account_id] => account_id) + accounts = profiles.inner_join(location_subquery, id: :location_id) + .select(:display_name, Sequel[:profiles][:id], :birth_date, :genders, :orientations, :relationship_status, :location_display_name, Sequel[:dist].as(:location_distance)) + .exclude(Sequel[:profiles][:account_id] => account_id) accounts.where { account_id > min_account_id } if min_account_id accounts.to_a end @@ -33,8 +33,8 @@ def locations end # @return [Sequel::Postgres::Dataset] - def account_informations - Database.connection[:account_informations] + def profiles + Database.connection[:profiles] end end end diff --git a/db/migrations/20241119110138_change_table_name_and_add_id.rb b/db/migrations/20241119110138_change_table_name_and_add_id.rb new file mode 100644 index 0000000..54ae466 --- /dev/null +++ b/db/migrations/20241119110138_change_table_name_and_add_id.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +Sequel.migration do + up do + rename_table(:account_informations, :profiles) + alter_table(:profiles) do + add_column :id, :uuid, null: false, default: Sequel.lit("uuid_generate_v7()") + drop_constraint(:account_informations_pkey) + add_primary_key(%i[id]) + end + run "UPDATE profiles set id = uuid_timestamptz_to_v7(created_at)" + end + down do + rename_table(:profiles, :account_informations) + alter_table(:account_informations) do + drop_constraint(:profiles_pkey) + add_primary_key(%i[account_id]) + drop_column :id + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 88c30ee..262bd9c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,5 +1,5 @@ # **Autogenerated file! Do not modify by hand!** -# Current migration: 20241115154326_fix_osm_id_type.rb +# Current migration: 20241119110138_change_table_name_and_add_id.rb Sequel.migration do change do @@ -89,32 +89,6 @@ primary_key %i[id] end - create_table(:account_informations) do - foreign_key :account_id, :accounts, type: "bigint", null: false, key: %i[id] - column :created_at, "timestamp without time zone", default: Sequel::CURRENT_TIMESTAMP, null: false - column :display_name, "text", null: false - column :about_me, "text" - column :birth_date, "date" - column :genders, "genders[]" - column :orientations, "orientations[]" - column :languages, "languages[]" - column :relationship_type, "relationship_type" - column :relationship_status, "relationship_status" - column :tobacco, "frequency" - column :marijuana, "frequency" - column :alcohol, "frequency" - column :other_recreational_drugs, "frequency" - column :pets, "haves_or_have_nots" - column :wants_pets, "wants" - column :kids, "haves_or_have_nots" - column :wants_kids, "wants" - column :religion, "religions" - column :religion_importance, "importance" - foreign_key :location_id, :locations, type: "bigint", key: %i[id] - - primary_key %i[account_id] - end - create_table(:account_jwt_refresh_keys) do primary_key :id, type: :Bignum foreign_key :account_id, :accounts, type: "bigint", null: false, key: %i[id] @@ -244,5 +218,32 @@ primary_key %i[id] end + + create_table(:profiles) do + foreign_key :account_id, :accounts, type: "bigint", null: false, key: %i[id] + column :created_at, "timestamp without time zone", default: Sequel::CURRENT_TIMESTAMP, null: false + column :display_name, "text", null: false + column :about_me, "text" + column :birth_date, "date" + column :genders, "genders[]" + column :orientations, "orientations[]" + column :languages, "languages[]" + column :relationship_type, "relationship_type" + column :relationship_status, "relationship_status" + column :tobacco, "frequency" + column :marijuana, "frequency" + column :alcohol, "frequency" + column :other_recreational_drugs, "frequency" + column :pets, "haves_or_have_nots" + column :wants_pets, "wants" + column :kids, "haves_or_have_nots" + column :wants_kids, "wants" + column :religion, "religions" + column :religion_importance, "importance" + foreign_key :location_id, :locations, type: "bigint", key: %i[id] + column :id, "uuid", default: Sequel::LiteralString.new("uuid_generate_v7()"), null: false + + primary_key %i[id] + end end end diff --git a/test/app/api/authenticated/listing_test.rb b/test/app/api/authenticated/listing_test.rb index 10ff76c..2be8d2f 100644 --- a/test/app/api/authenticated/listing_test.rb +++ b/test/app/api/authenticated/listing_test.rb @@ -14,48 +14,48 @@ @login = "foo@retromeet.social" @password = "bogus123" - @account = create(:account, email: @login, password: @password, account_information: { display_name: "Foo", created_at: Time.new(2024, 9, 20, 16, 50, 0), location_id: @schaerbeek.id }) - @etterbeek_account = create(:account, account_information: { display_name: "Etterbeek account", location_id: @etterbeek.id, birth_date: Date.new(1987, 1, 1) }) - @amsterdam_account = create(:account, account_information: { display_name: "Amsterdam account", location_id: @amsterdam.id, birth_date: Date.new(1997, 1, 1) }) - @cologne_account = create(:account, account_information: { display_name: "Cologne account", location_id: @cologne.id, birth_date: Date.new(2004, 1, 1) }) - @paris_account = create(:account, account_information: { display_name: "Paris account", location_id: @paris.id, birth_date: Date.new(2004, 6, 1) }) + @account = create(:account, email: @login, password: @password, profile: { display_name: "Foo", created_at: Time.new(2024, 9, 20, 16, 50, 0), location_id: @schaerbeek.id }) + @etterbeek_account = create(:account, profile: { display_name: "Etterbeek account", location_id: @etterbeek.id, birth_date: Date.new(1987, 1, 1) }) + @amsterdam_account = create(:account, profile: { display_name: "Amsterdam account", location_id: @amsterdam.id, birth_date: Date.new(1997, 1, 1) }) + @cologne_account = create(:account, profile: { display_name: "Cologne account", location_id: @cologne.id, birth_date: Date.new(2004, 1, 1) }) + @paris_account = create(:account, profile: { display_name: "Paris account", location_id: @paris.id, birth_date: Date.new(2004, 6, 1) }) @etterbeek_profile = { - account_id: @etterbeek_account.id, + id: @etterbeek_account.profile.id, display_name: "Etterbeek account", - genders: @etterbeek_account.account_information.genders, - orientations: @etterbeek_account.account_information.orientations, - relationship_status: @etterbeek_account.account_information.relationship_status, + genders: @etterbeek_account.profile.genders, + orientations: @etterbeek_account.profile.orientations, + relationship_status: @etterbeek_account.profile.relationship_status, location_display_name: @etterbeek.display_name.transform_keys(&:to_sym), location_distance: 3.60585778981352, age: 37 # TODO: calculate this so that this test don't breaks when the profile ages } @amsterdam_profile = { - account_id: @amsterdam_account.id, + id: @amsterdam_account.profile.id, display_name: "Amsterdam account", - genders: @amsterdam_account.account_information.genders, - orientations: @amsterdam_account.account_information.orientations, - relationship_status: @amsterdam_account.account_information.relationship_status, + genders: @amsterdam_account.profile.genders, + orientations: @amsterdam_account.profile.orientations, + relationship_status: @amsterdam_account.profile.relationship_status, location_display_name: @amsterdam.display_name.transform_keys(&:to_sym), location_distance: 171.18810403107398, age: 27 # TODO: calculate this so that this test don't breaks when the profile ages } @cologne_profile = { - account_id: @cologne_account.id, + id: @cologne_account.profile.id, display_name: "Cologne account", - genders: @cologne_account.account_information.genders, - orientations: @cologne_account.account_information.orientations, - relationship_status: @cologne_account.account_information.relationship_status, + genders: @cologne_account.profile.genders, + orientations: @cologne_account.profile.orientations, + relationship_status: @cologne_account.profile.relationship_status, location_display_name: @cologne.display_name.transform_keys(&:to_sym), location_distance: 181.5191324427601, age: 20 # TODO: calculate this so that this test don't breaks when the profile ages } @paris_profile = { - account_id: @paris_account.id, + id: @paris_account.profile.id, display_name: "Paris account", - genders: @paris_account.account_information.genders, - orientations: @paris_account.account_information.orientations, - relationship_status: @paris_account.account_information.relationship_status, + genders: @paris_account.profile.genders, + orientations: @paris_account.profile.orientations, + relationship_status: @paris_account.profile.relationship_status, location_display_name: @paris.display_name.transform_keys(&:to_sym), location_distance: 266.8743807484807, age: 20 # TODO: calculate this so that this test don't breaks when the profile ages diff --git a/test/app/api/authenticated/profile_test.rb b/test/app/api/authenticated/profile_test.rb index aa8bd83..7343a83 100644 --- a/test/app/api/authenticated/profile_test.rb +++ b/test/app/api/authenticated/profile_test.rb @@ -7,7 +7,7 @@ before(:all) do @login = "foo@retromeet.social" @password = "bogus123" - @account = create(:account, email: @login, password: @password, account_information: { display_name: "Foo", created_at: Time.new(2024, 9, 20, 16, 50, 0) }) + @account = create(:account, email: @login, password: @password, profile: { display_name: "Foo", created_at: Time.new(2024, 9, 20, 16, 50, 0) }) end describe "get /profile/info" do @@ -31,28 +31,28 @@ end it "gets the user information" do - account_information = @account.account_information + profile = @account.profile expected_response = { - about_me: account_information.about_me, - created_at: account_information.created_at.iso8601, - birth_date: account_information.birth_date.to_s, - genders: account_information.genders, - orientations: account_information.orientations, - languages: account_information.languages, - relationship_status: account_information.relationship_status, - relationship_type: account_information.relationship_type, - tobacco: account_information.tobacco, - marijuana: account_information.marijuana, - alcohol: account_information.alcohol, - other_recreational_drugs: account_information.other_recreational_drugs, - pets: account_information.pets, - wants_pets: account_information.wants_pets, - kids: account_information.kids, - wants_kids: account_information.wants_kids, - religion: account_information.religion, - religion_importance: account_information.religion_importance, - display_name: account_information.display_name, - location_display_name: account_information.location.display_name.transform_keys(&:to_sym) + about_me: profile.about_me, + created_at: profile.created_at.iso8601, + birth_date: profile.birth_date.to_s, + genders: profile.genders, + orientations: profile.orientations, + languages: profile.languages, + relationship_status: profile.relationship_status, + relationship_type: profile.relationship_type, + tobacco: profile.tobacco, + marijuana: profile.marijuana, + alcohol: profile.alcohol, + other_recreational_drugs: profile.other_recreational_drugs, + pets: profile.pets, + wants_pets: profile.wants_pets, + kids: profile.kids, + wants_kids: profile.wants_kids, + religion: profile.religion, + religion_importance: profile.religion_importance, + display_name: profile.display_name, + location_display_name: profile.location.display_name.transform_keys(&:to_sym) } authorized_get @auth, @endpoint @@ -127,25 +127,25 @@ end it "posts with the same information as the user account" do - account_information = @account.account_information + profile = @account.profile body = { - about_me: account_information.about_me, - genders: account_information.genders, - orientations: account_information.orientations, - languages: account_information.languages, - relationship_status: account_information.relationship_status, - relationship_type: account_information.relationship_type, - tobacco: account_information.tobacco, - marijuana: account_information.marijuana, - alcohol: account_information.alcohol, - other_recreational_drugs: account_information.other_recreational_drugs, - pets: account_information.pets, - wants_pets: account_information.wants_pets, - kids: account_information.kids, - wants_kids: account_information.wants_kids, - religion: account_information.religion, - religion_importance: account_information.religion_importance, - display_name: account_information.display_name + about_me: profile.about_me, + genders: profile.genders, + orientations: profile.orientations, + languages: profile.languages, + relationship_status: profile.relationship_status, + relationship_type: profile.relationship_type, + tobacco: profile.tobacco, + marijuana: profile.marijuana, + alcohol: profile.alcohol, + other_recreational_drugs: profile.other_recreational_drugs, + pets: profile.pets, + wants_pets: profile.wants_pets, + kids: profile.kids, + wants_kids: profile.wants_kids, + religion: profile.religion, + religion_importance: profile.religion_importance, + display_name: profile.display_name } authorized_post @auth, @endpoint, body.to_json @@ -186,19 +186,18 @@ # We iterate through all the params that the endpoint supports and for each we get possible values in the database and update it post_endpoint = API::Authenticated::Profile.routes.find { |v| v.request_method == "POST" && v.path == "/profile/complete(.:format)" } post_endpoint.params.each_key do |param| - next if %w[text date].include? AccountInformation.db_schema[param.to_sym][:db_type] + next if %w[text date].include? Profile.db_schema[param.to_sym][:db_type] - if AccountInformation.db_schema[param.to_sym][:db_type].ends_with?("[]") - enum_type = Database.connection[:pg_type].where(typname: "_#{AccountInformation.db_schema[param.to_sym][:db_type][..-3]}").get(:typelem) + if Profile.db_schema[param.to_sym][:db_type].ends_with?("[]") + enum_type = Database.connection[:pg_type].where(typname: "_#{Profile.db_schema[param.to_sym][:db_type][..-3]}").get(:typelem) enum_values = Database.connection.instance_variable_get(:@enum_labels)[enum_type].map { |v| [v] } else - enum_values = AccountInformation.db_schema[param.to_sym][:enum_values] + enum_values = Profile.db_schema[param.to_sym][:enum_values] end next unless enum_values - sub_tests = [] - enum_values.each do |value| - sub_tests << %(it "test that the value #{value.is_a?(Array) ? value[0] : value} is accepted" do + sub_tests = enum_values.map do |value| + %(it "test that the value #{value.is_a?(Array) ? value[0] : value} is accepted" do body = { #{param}: #{value.is_a?(Array) ? value : "\"#{value}\""} } @@ -226,33 +225,32 @@ @auth = login(login: @login, password: @password) end - make_my_diffs_pretty! it "gets the user information" do - account_information = @account.account_information + profile = @account.profile expected_response = { - account_id: @account.id, - about_me: account_information.about_me, - genders: account_information.genders, - orientations: account_information.orientations, - languages: account_information.languages, - relationship_status: account_information.relationship_status, - relationship_type: account_information.relationship_type, - tobacco: account_information.tobacco, - marijuana: account_information.marijuana, - alcohol: account_information.alcohol, - other_recreational_drugs: account_information.other_recreational_drugs, - pets: account_information.pets, - wants_pets: account_information.wants_pets, - kids: account_information.kids, - wants_kids: account_information.wants_kids, - religion: account_information.religion, - religion_importance: account_information.religion_importance, - display_name: account_information.display_name, - location_display_name: account_information.location.display_name.transform_keys(&:to_sym), + id: @account.profile.id, + about_me: profile.about_me, + genders: profile.genders, + orientations: profile.orientations, + languages: profile.languages, + relationship_status: profile.relationship_status, + relationship_type: profile.relationship_type, + tobacco: profile.tobacco, + marijuana: profile.marijuana, + alcohol: profile.alcohol, + other_recreational_drugs: profile.other_recreational_drugs, + pets: profile.pets, + wants_pets: profile.wants_pets, + kids: profile.kids, + wants_kids: profile.wants_kids, + religion: profile.religion, + religion_importance: profile.religion_importance, + display_name: profile.display_name, + location_display_name: profile.location.display_name.transform_keys(&:to_sym), location_distance: nil, # TODO: I think this should display the distance to the logged in user age: 39 # TODO: calculate this so that this test don't breaks when the profile ages } - authorized_get @auth, format(@endpoint, id: @account.id) + authorized_get @auth, format(@endpoint, id: @account.profile.id) assert_predicate last_response, :ok? assert_equal expected_response, JSON.parse(last_response.body, symbolize_names: true) diff --git a/test/app/api/authenticated/search_test.rb b/test/app/api/authenticated/search_test.rb index 0d0b0d0..8d1aba5 100644 --- a/test/app/api/authenticated/search_test.rb +++ b/test/app/api/authenticated/search_test.rb @@ -8,7 +8,7 @@ before(:all) do @login = "foo@retromeet.social" @password = "bogus123" - @account = create(:account, email: @login, password: @password, account_information: { display_name: "Foo", created_at: Time.new(2024, 9, 20, 16, 50, 0) }) + @account = create(:account, email: @login, password: @password, profile: { display_name: "Foo", created_at: Time.new(2024, 9, 20, 16, 50, 0) }) end describe "GET /api/search/address" do diff --git a/test/app/api/rodauth_middleware_test.rb b/test/app/api/rodauth_middleware_test.rb index 0fec6fc..7a59ccc 100644 --- a/test/app/api/rodauth_middleware_test.rb +++ b/test/app/api/rodauth_middleware_test.rb @@ -9,12 +9,14 @@ expected_response = { success: "Your account has been created" } header "content-type", "application/json" login = "john@retromeet.info" - assert_difference("Database.connection[:account_informations].count", 1) do + assert_difference("Profile.count", 1) do post "/create-account", { login:, password: Faker::Internet.password }.to_json - assert last_response.ok? + + assert_predicate last_response, :ok? assert_equal expected_response, JSON.parse(last_response.body, symbolize_names: true) end - inserted = Database.connection[:account_informations].order(:account_id).last + inserted = Database.connection[:profiles].order(:account_id).last + assert_equal "john", inserted[:display_name] end end diff --git a/test/factories/account.rb b/test/factories/account.rb index a455c92..d082355 100644 --- a/test/factories/account.rb +++ b/test/factories/account.rb @@ -3,20 +3,20 @@ class Account < Sequel::Model many_to_one :account_status, key: :status_id one_to_one :account_password_hash - one_to_one :account_information + one_to_one :profile end FactoryBot.define do factory :account do transient do password { "password" } - account_information { {} } + profile { {} } end email { Faker::Internet.email } account_status { AccountStatus.verified } after(:create) do |account, evaluator| create(:account_password_hash, account:, password: evaluator.password) - create(:account_information, account:, **evaluator.account_information) + create(:profile, account:, **evaluator.profile) end end end diff --git a/test/factories/account_information.rb b/test/factories/profile.rb similarity index 91% rename from test/factories/account_information.rb rename to test/factories/profile.rb index 8572049..5d71917 100644 --- a/test/factories/account_information.rb +++ b/test/factories/profile.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -class AccountInformation < Sequel::Model +class Profile < Sequel::Model many_to_one :account many_to_one :location end FactoryBot.define do - factory :account_information do + factory :profile do account location about_me { Faker::Lorem.paragraph }