diff --git a/app/controllers/v1/room_adverts_controller.rb b/app/controllers/v1/room_adverts_controller.rb new file mode 100644 index 00000000..76b6ea57 --- /dev/null +++ b/app/controllers/v1/room_adverts_controller.rb @@ -0,0 +1,3 @@ +class V1::RoomAdvertsController < V1::ApplicationController + before_action :doorkeeper_authorize!, except: %i[index show] +end diff --git a/app/models/room_advert.rb b/app/models/room_advert.rb new file mode 100644 index 00000000..53450456 --- /dev/null +++ b/app/models/room_advert.rb @@ -0,0 +1,12 @@ +class RoomAdvert < ApplicationRecord + mount_base64_uploader :cover_photo, CoverPhotoUploader + + belongs_to :author, class_name: 'User' + + validates :house_name, presence: true + validates :contact, presence: true + validates :description, presence: true + validates :publicly_visible, inclusion: [true, false] + + scope :publicly_visible, (-> { where(publicly_visible: true) }) +end diff --git a/app/policies/room_advert_policy.rb b/app/policies/room_advert_policy.rb new file mode 100644 index 00000000..0be2aa8e --- /dev/null +++ b/app/policies/room_advert_policy.rb @@ -0,0 +1,33 @@ +class RoomAdvertPolicy < ApplicationPolicy + class Scope < ApplicationPolicy::Scope + def resolve + if user_can_read? + scope + else + scope.publicly_visible + end + end + end + + def index? + true + end + + def show? + super || scope.exists?(id: record.id) + end + + def update? + user_is_owner? || super + end + + def destroy? + user_is_owner? || super + end + + private + + def user_is_owner? + record.author == user + end +end diff --git a/app/resources/v1/room_advert_resource.rb b/app/resources/v1/room_advert_resource.rb new file mode 100644 index 00000000..7532eee1 --- /dev/null +++ b/app/resources/v1/room_advert_resource.rb @@ -0,0 +1,31 @@ +class V1::RoomAdvertResource < V1::ApplicationResource + attributes :house_name, :contact, :location, :available_from, + :description, :description_camofied, :author_name, + :cover_photo_url, :cover_photo, :publicly_visible + + def cover_photo_url + @model.cover_photo.url + end + + def description_camofied + camofy(@model['description']) + end + + def author_name + @model.author.full_name + end + + has_one :author, always_include_linkage_data: true + + def fetchable_fields + super - [:cover_photo] + end + + def self.creatable_fields(_context) + %i[house_name contact location available_from description cover_photo publicly_visible] + end + + before_create do + @model.author_id = current_user.id + end +end diff --git a/config/routes.rb b/config/routes.rb index 23d33e5d..33f9b09e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -44,6 +44,7 @@ jsonapi_resources :photo_comments jsonapi_resources :photos, only: %i[index show destroy] jsonapi_resources :polls + jsonapi_resources :room_adverts jsonapi_resources :static_pages jsonapi_resources :stored_mails, only: %i[index show destroy] do jsonapi_relationships diff --git a/db/migrate/20230727114709_create_room_adverts.rb b/db/migrate/20230727114709_create_room_adverts.rb new file mode 100644 index 00000000..e57c8f19 --- /dev/null +++ b/db/migrate/20230727114709_create_room_adverts.rb @@ -0,0 +1,22 @@ +class CreateRoomAdverts < ActiveRecord::Migration[7.0] + def change + create_table :room_adverts do |t| + t.string :house_name, null: false + t.string :contact, null: false + t.string :location + t.string :available_from + t.string :description, null: false + t.string :cover_photo + t.boolean :publicly_visible + t.integer :author_id + t.datetime :deleted_at + + t.timestamps + end + + Permission.create(name: 'room_advert.create') + Permission.create(name: 'room_advert.read') + Permission.create(name: 'room_advert.update') + Permission.create(name: 'room_advert.destroy') + end +end diff --git a/db/schema.rb b/db/schema.rb index 146243fa..c16453c8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,8 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_12_19_204657) do - +ActiveRecord::Schema[7.0].define(version: 2023_07_27_114709) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -19,8 +18,8 @@ t.integer "status", default: 0, null: false t.string "message_id", null: false t.string "message_checksum", null: false - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.index ["message_id", "message_checksum"], name: "index_action_mailbox_inbound_emails_uniqueness", unique: true end @@ -29,7 +28,7 @@ t.string "record_type", null: false t.bigint "record_id", null: false t.bigint "blob_id", null: false - t.datetime "created_at", null: false + t.datetime "created_at", precision: nil, null: false t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true end @@ -41,7 +40,7 @@ t.text "metadata" t.bigint "byte_size", null: false t.string "checksum", null: false - t.datetime "created_at", null: false + t.datetime "created_at", precision: nil, null: false t.string "service_name", null: false t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true end @@ -54,14 +53,14 @@ create_table "activities", id: :serial, force: :cascade do |t| t.integer "form_id" - t.datetime "deleted_at" + t.datetime "deleted_at", precision: nil t.decimal "price", precision: 8, scale: 2 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "cover_photo" t.string "location" - t.datetime "start_time" - t.datetime "end_time" + t.datetime "start_time", precision: nil + t.datetime "end_time", precision: nil t.string "title" t.string "description" t.integer "author_id" @@ -76,9 +75,9 @@ t.text "content" t.integer "article_id" t.integer "author_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.index ["article_id"], name: "index_article_comments_on_article_id" t.index ["author_id"], name: "index_article_comments_on_author_id" end @@ -86,10 +85,10 @@ create_table "articles", id: :serial, force: :cascade do |t| t.string "title" t.string "content" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.integer "group_id" - t.datetime "deleted_at" + t.datetime "deleted_at", precision: nil t.boolean "publicly_visible", default: false, null: false t.integer "author_id" t.string "cover_photo" @@ -101,13 +100,13 @@ end create_table "board_room_presences", id: :serial, force: :cascade do |t| - t.datetime "start_time" - t.datetime "end_time" + t.datetime "start_time", precision: nil + t.datetime "end_time", precision: nil t.text "status" t.integer "user_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.index ["user_id"], name: "index_board_room_presences_on_user_id" end @@ -117,9 +116,9 @@ t.string "description" t.string "isbn" t.string "cover_photo" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.datetime "deleted_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.datetime "deleted_at", precision: nil t.index ["isbn"], name: "index_books_on_isbn", unique: true end @@ -127,9 +126,9 @@ t.string "name", null: false t.date "date", null: false t.integer "author_id" - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["author_id"], name: "index_debit_collections_on_author_id" end @@ -139,9 +138,9 @@ t.date "start_date", null: false t.date "end_date" t.bigint "user_id" - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["user_id"], name: "index_debit_mandates_on_user_id" end @@ -150,9 +149,9 @@ t.integer "collection_id" t.string "description" t.decimal "amount", precision: 8, scale: 2 - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.index ["collection_id"], name: "index_debit_transactions_on_collection_id" t.index ["user_id"], name: "index_debit_transactions_on_user_id" end @@ -160,9 +159,9 @@ create_table "form_closed_question_answers", id: :serial, force: :cascade do |t| t.integer "option_id" t.integer "response_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.integer "question_id" t.boolean "radio_question", default: false, null: false t.index ["question_id", "response_id"], name: "index_form_closed_question_answers_on_question_and_response", unique: true, where: "(radio_question IS TRUE)" @@ -172,9 +171,9 @@ create_table "form_closed_question_options", id: :serial, force: :cascade do |t| t.string "option" t.integer "question_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.integer "position", default: 0 end @@ -184,18 +183,18 @@ t.integer "position" t.boolean "required", default: false, null: false t.integer "form_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil end create_table "form_forms", id: :serial, force: :cascade do |t| t.integer "author_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" - t.datetime "respond_until" - t.datetime "respond_from" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil + t.datetime "respond_until", precision: nil + t.datetime "respond_from", precision: nil t.integer "group_id" t.integer "responses_count", default: 0, null: false t.index ["group_id"], name: "index_form_forms_on_group_id" @@ -205,9 +204,9 @@ t.text "answer" t.integer "response_id" t.integer "question_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.index ["response_id", "question_id"], name: "index_form_open_question_answers_on_response_id_and_question_id", unique: true end @@ -217,17 +216,17 @@ t.integer "position" t.boolean "required", default: false, null: false t.integer "form_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil end create_table "form_responses", id: :serial, force: :cascade do |t| t.integer "form_id" t.integer "user_id" - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.boolean "completed", default: false, null: false t.integer "lock_version" t.index ["form_id", "user_id"], name: "index_form_responses_on_form_id_and_user_id", unique: true @@ -236,9 +235,9 @@ create_table "forum_categories", id: :serial, force: :cascade do |t| t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.integer "threads_count", default: 0, null: false t.index ["deleted_at"], name: "index_forum_categories_on_deleted_at" end @@ -247,9 +246,9 @@ t.string "message" t.integer "author_id" t.integer "thread_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.index ["author_id"], name: "index_forum_posts_on_author_id" t.index ["deleted_at"], name: "index_forum_posts_on_deleted_at" t.index ["thread_id"], name: "index_forum_posts_on_thread_id" @@ -259,9 +258,9 @@ t.integer "user_id" t.integer "thread_id" t.integer "post_id" - t.datetime "deleted_at" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false + t.datetime "deleted_at", precision: nil + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.index ["thread_id"], name: "index_forum_read_threads_on_thread_id" t.index ["user_id"], name: "index_forum_read_threads_on_user_id" end @@ -270,10 +269,10 @@ t.string "title" t.integer "author_id" t.integer "category_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" - t.datetime "closed_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil + t.datetime "closed_at", precision: nil t.integer "posts_count", default: 0, null: false t.index ["author_id"], name: "index_forum_threads_on_author_id" t.index ["category_id"], name: "index_forum_threads_on_category_id" @@ -285,7 +284,7 @@ t.integer "sluggable_id", null: false t.string "sluggable_type", limit: 50 t.string "scope" - t.datetime "created_at" + t.datetime "created_at", precision: nil t.index ["slug", "sluggable_type", "scope"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type_and_scope", unique: true t.index ["slug", "sluggable_type"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type" t.index ["sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_id" @@ -294,9 +293,9 @@ create_table "groups", id: :serial, force: :cascade do |t| t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.text "description" t.string "kind", null: false t.string "recognized_at_gma" @@ -309,9 +308,9 @@ create_table "groups_permissions", id: :serial, force: :cascade do |t| t.integer "group_id" t.integer "permission_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.index ["deleted_at"], name: "index_groups_permissions_on_deleted_at" t.index ["group_id"], name: "index_groups_permissions_on_group_id" t.index ["permission_id"], name: "index_groups_permissions_on_permission_id" @@ -323,12 +322,12 @@ t.string "description" t.integer "group_id" t.integer "user_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.bigint "moderator_group_id" t.boolean "smtp_enabled", default: false - t.datetime "last_received_at" + t.datetime "last_received_at", precision: nil t.index ["email"], name: "index_mail_aliases_on_email", unique: true t.index ["moderator_group_id"], name: "index_mail_aliases_on_moderator_group_id" end @@ -336,9 +335,9 @@ create_table "memberships", id: :serial, force: :cascade do |t| t.integer "group_id" t.integer "user_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.date "start_date", null: false t.date "end_date" t.string "function" @@ -354,8 +353,8 @@ t.string "token", null: false t.integer "expires_in", null: false t.text "redirect_uri", null: false - t.datetime "created_at", null: false - t.datetime "revoked_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "revoked_at", precision: nil t.string "scopes" t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true end @@ -366,8 +365,8 @@ t.string "token", null: false t.string "refresh_token" t.integer "expires_in" - t.datetime "revoked_at" - t.datetime "created_at", null: false + t.datetime "revoked_at", precision: nil + t.datetime "created_at", precision: nil, null: false t.string "scopes" t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id" @@ -380,17 +379,17 @@ t.string "secret", null: false t.text "redirect_uri", null: false t.string "scopes", default: "", null: false - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", precision: nil + t.datetime "updated_at", precision: nil t.boolean "confidential", default: true, null: false t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true end create_table "permissions", id: :serial, force: :cascade do |t| t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.index ["deleted_at"], name: "index_permissions_on_deleted_at" t.index ["name"], name: "index_permissions_on_name", unique: true end @@ -398,9 +397,9 @@ create_table "permissions_users", id: :serial, force: :cascade do |t| t.integer "user_id" t.integer "permission_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.index ["deleted_at"], name: "index_permissions_users_on_deleted_at" t.index ["permission_id"], name: "index_permissions_users_on_permission_id" t.index ["user_id"], name: "index_permissions_users_on_user_id" @@ -409,9 +408,9 @@ create_table "photo_albums", id: :serial, force: :cascade do |t| t.string "title" t.date "date" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.boolean "publicly_visible", default: false, null: false t.bigint "author_id" t.bigint "group_id" @@ -422,9 +421,9 @@ create_table "photo_comments", id: :serial, force: :cascade do |t| t.text "content" - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.integer "author_id" t.integer "photo_id" t.index ["author_id"], name: "index_photo_comments_on_author_id" @@ -434,15 +433,15 @@ create_table "photos", id: :serial, force: :cascade do |t| t.string "image" t.integer "photo_album_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.string "original_filename" t.integer "uploader_id" t.integer "comments_count", default: 0, null: false t.string "exif_make" t.string "exif_model" - t.datetime "exif_date_time_original" + t.datetime "exif_date_time_original", precision: nil t.string "exif_exposure_time" t.string "exif_aperture_value" t.string "exif_iso_speed_ratings" @@ -455,9 +454,9 @@ end create_table "polls", id: :serial, force: :cascade do |t| - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.integer "author_id" t.integer "form_id" t.index ["author_id"], name: "index_polls_on_author_id" @@ -467,32 +466,46 @@ create_table "quickpost_messages", id: :serial, force: :cascade do |t| t.integer "author_id" t.text "message" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" - t.datetime "datetime" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil + t.datetime "datetime", precision: nil t.index ["datetime"], name: "index_quickpost_messages_on_datetime" t.index ["deleted_at"], name: "index_quickpost_messages_on_deleted_at" end + create_table "room_adverts", force: :cascade do |t| + t.string "house_name", null: false + t.string "contact", null: false + t.string "location" + t.string "available_from" + t.string "description", null: false + t.string "cover_photo" + t.boolean "publicly_visible" + t.integer "author_id" + t.datetime "deleted_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "static_pages", id: :serial, force: :cascade do |t| t.string "title", null: false t.string "slug", null: false t.string "content", null: false t.boolean "publicly_visible" - t.datetime "deleted_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.string "category", default: "vereniging" t.index ["slug"], name: "index_static_pages_on_slug", unique: true end create_table "stored_mails", force: :cascade do |t| - t.datetime "deleted_at" + t.datetime "deleted_at", precision: nil t.bigint "mail_alias_id" - t.datetime "received_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "received_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false t.bigint "inbound_email_id" t.index ["inbound_email_id"], name: "index_stored_mails_on_inbound_email_id" t.index ["mail_alias_id"], name: "index_stored_mails_on_mail_alias_id" @@ -502,9 +515,9 @@ t.string "email" t.string "username" t.string "password_digest" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.datetime "deleted_at" + t.datetime "created_at", precision: nil, null: false + t.datetime "updated_at", precision: nil, null: false + t.datetime "deleted_at", precision: nil t.string "first_name", null: false t.string "last_name_prefix" t.string "last_name", null: false @@ -517,10 +530,10 @@ t.string "study" t.date "start_study" t.boolean "login_enabled", default: false, null: false - t.datetime "activated_at" + t.datetime "activated_at", precision: nil t.string "activation_token" t.string "avatar" - t.datetime "activation_token_valid_till" + t.datetime "activation_token_valid_till", precision: nil t.boolean "sidekiq_access" t.boolean "vegetarian", default: false t.string "otp_secret_key" @@ -553,9 +566,9 @@ t.date "deadline" t.integer "author_id", null: false t.integer "group_id" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.datetime "deleted_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.datetime "deleted_at", precision: nil end create_table "versions", id: :serial, force: :cascade do |t| @@ -563,7 +576,7 @@ t.integer "item_id", null: false t.string "event", null: false t.string "whodunnit" - t.datetime "created_at" + t.datetime "created_at", precision: nil t.jsonb "object" t.jsonb "object_changes" t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id" diff --git a/db/seeds/permissions.rb b/db/seeds/permissions.rb index 25a2066a..08cdc412 100644 --- a/db/seeds/permissions.rb +++ b/db/seeds/permissions.rb @@ -33,6 +33,7 @@ def create_permissions(permission_map) 'photo' => %i[create read update destroy], 'photo_comment' => %i[create read update destroy], 'quickpost_message' => %i[create read update destroy], + 'room_advert' => %i[create read update destroy], 'stored_mail' => %i[read destroy], 'forum/category' => %i[create read update destroy], 'forum/thread' => %i[create read update destroy], @@ -72,6 +73,7 @@ def create_permissions(permission_map) 'photo' => %i[create read], 'photo_comment' => %i[create read], 'quickpost_message' => %i[create read], + 'room_advert' => %i[create read], 'forum/category' => %i[read], 'forum/thread' => %i[create read], 'forum/post' => %i[create read], @@ -104,6 +106,7 @@ def create_permissions(permission_map) 'photo' => %i[read], 'photo_comment' => %i[create read], 'quickpost_message' => %i[create read], + 'room_advert' => %i[], 'forum/category' => %i[read], 'forum/thread' => %i[create read], 'forum/post' => %i[create read], diff --git a/spec/factories/room_advert.rb b/spec/factories/room_advert.rb new file mode 100644 index 00000000..047a6d36 --- /dev/null +++ b/spec/factories/room_advert.rb @@ -0,0 +1,16 @@ +FactoryBot.define do + factory :room_advert do + author do + FactoryBot.create(:user) + end + + house_name { Faker::Company.name } + contact { Faker::Internet.email } + location { Faker::Address.street_name } + available_from { Faker::Date.forward(days: 31) } + description { Faker::Hipster.paragraph } + publicly_visible { false } + + trait(:public) { publicly_visible { true } } + end +end diff --git a/spec/models/room_advert_spec.rb b/spec/models/room_advert_spec.rb new file mode 100644 index 00000000..8a0000ce --- /dev/null +++ b/spec/models/room_advert_spec.rb @@ -0,0 +1,54 @@ +require 'rails_helper' + +RSpec.describe RoomAdvert, type: :model do + subject(:room_advert) { build_stubbed(:room_advert) } + + describe '#valid' do + it { expect(room_advert).to be_valid } + + context 'when without an author' do + subject(:room_advert) { build_stubbed(:room_advert, author: nil) } + + it { expect(room_advert).not_to be_valid } + end + + context 'when without a house_name' do + subject(:room_advert) { build_stubbed(:room_advert, house_name: nil) } + + it { expect(room_advert).not_to be_valid } + end + + context 'when without a contact' do + subject(:room_advert) { build_stubbed(:room_advert, contact: nil) } + + it { expect(room_advert).not_to be_valid } + end + + context 'when without a description' do + subject(:room_advert) { build_stubbed(:room_advert, description: nil) } + + it { expect(room_advert).not_to be_valid } + end + + context 'when without public visibility' do + subject(:room_advert) { build_stubbed(:room_advert, publicly_visible: nil) } + + it { expect(room_advert).not_to be_valid } + end + end + + describe '#save' do + it_behaves_like 'a model accepting a base 64 image as', :cover_photo + end + + describe '#publicly_visible' do + before do + create(:room_advert, publicly_visible: true) + create(:room_advert, publicly_visible: true) + create(:room_advert, publicly_visible: false) + end + + it { expect(described_class.publicly_visible.count).to be 2 } + it { expect(described_class.count - described_class.publicly_visible.count).to be 1 } + end +end diff --git a/spec/policies/room_advert_policy_spec.rb b/spec/policies/room_advert_policy_spec.rb new file mode 100644 index 00000000..35ba8638 --- /dev/null +++ b/spec/policies/room_advert_policy_spec.rb @@ -0,0 +1,24 @@ +require 'rails_helper' + +RSpec.describe RoomAdvertPolicy, type: :policy do + subject(:policy) { described_class } + + let(:user) { build(:user) } + + permissions :update? do + describe 'when room_advert is not owned' do + it { expect(policy).not_to permit(user, build_stubbed(:room_advert)) } + end + + describe 'when room_advert is owned' do + it { expect(policy).to permit(user, build_stubbed(:room_advert, author: user)) } + end + + describe 'when with permission' do + let(:record_permission) { 'room_advert.update' } + let(:user) { create(:user, user_permission_list: [record_permission]) } + + it { expect(policy).to permit(user, build_stubbed(:room_advert)) } + end + end +end diff --git a/spec/requests/v1/room_adverts_controller/create_spec.rb b/spec/requests/v1/room_adverts_controller/create_spec.rb new file mode 100644 index 00000000..ca34b836 --- /dev/null +++ b/spec/requests/v1/room_adverts_controller/create_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +describe V1::RoomAdvertsController do + describe 'POST /room_adverts/:id', version: 1 do + let(:record) { build_stubbed(:room_advert) } + let(:record_url) { '/v1/room_adverts' } + let(:record_permission) { 'room_advert.create' } + + it_behaves_like 'a creatable and permissible model' do + let(:invalid_attributes) { { house_name: '' } } + end + + it_behaves_like 'a creatable model with author' + end +end diff --git a/spec/requests/v1/room_adverts_controller/destroy_spec.rb b/spec/requests/v1/room_adverts_controller/destroy_spec.rb new file mode 100644 index 00000000..11c57aec --- /dev/null +++ b/spec/requests/v1/room_adverts_controller/destroy_spec.rb @@ -0,0 +1,11 @@ +require 'rails_helper' + +describe V1::RoomAdvertsController do + describe 'DELETE /room_adverts/:id', version: 1 do + let(:record) { create(:room_advert) } + let(:record_url) { "/v1/room_adverts/#{record.id}" } + let(:record_permission) { 'room_advert.destroy' } + + it_behaves_like 'a destroyable and permissible model' + end +end diff --git a/spec/requests/v1/room_adverts_controller/index_spec.rb b/spec/requests/v1/room_adverts_controller/index_spec.rb new file mode 100644 index 00000000..dad34440 --- /dev/null +++ b/spec/requests/v1/room_adverts_controller/index_spec.rb @@ -0,0 +1,26 @@ +require 'rails_helper' + +describe V1::RoomAdvertsController do + describe 'GET /room_adverts', version: 1 do + let(:records) do + [ + create(:room_advert, :public), + create(:room_advert) + ] + end + let(:record_url) { '/v1/room_adverts' } + let(:record_permission) { 'room_advert.read' } + + before { Bullet.enable = false } + + after { Bullet.enable = true } + + subject(:request) { get(record_url) } + + it_behaves_like 'an indexable model' + + it_behaves_like 'a publicly visible index request' do + let(:model_name) { :room_advert } + end + end +end diff --git a/spec/requests/v1/room_adverts_controller/show_spec.rb b/spec/requests/v1/room_adverts_controller/show_spec.rb new file mode 100644 index 00000000..06205a83 --- /dev/null +++ b/spec/requests/v1/room_adverts_controller/show_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +describe V1::RoomAdvertsController do + describe 'GET /room_adverts/:id', version: 1 do + subject(:request) { get(record_url) } + + let(:record) { create(:room_advert) } + let(:record_url) { "/v1/room_adverts/#{record.id}" } + let(:record_permission) { 'room_advert.read' } + let(:public_record) { create(:room_advert, :public) } + let(:public_record_url) { "/v1/room_adverts/#{public_record.id}" } + + it_behaves_like 'a publicly visible model' + end +end diff --git a/spec/requests/v1/room_adverts_controller/update_spec.rb b/spec/requests/v1/room_adverts_controller/update_spec.rb new file mode 100644 index 00000000..1a590632 --- /dev/null +++ b/spec/requests/v1/room_adverts_controller/update_spec.rb @@ -0,0 +1,23 @@ +require 'rails_helper' + +describe V1::RoomAdvertsController do + describe 'PUT /room_adverts/:id', version: 1 do + let(:record) { create(:room_advert) } + let(:record_url) { "/v1/room_adverts/#{record.id}" } + let(:record_permission) { 'room_advert.update' } + + it_behaves_like 'an updatable and permissible model', response: :ok do + let(:invalid_attributes) { { house_name: '' } } + end + + context 'when with permission' do + include_context 'when authenticated' do + let(:user) { create(:user, user_permission_list: [record_permission]) } + end + + subject(:request) { put(record_url) } + + it { expect { request && record.reload }.not_to(change(record, :author)) } + end + end +end diff --git a/spec/support/behaviors/requests/model_accepting_base_64_image.rb b/spec/support/behaviors/requests/model_accepting_base_64_image.rb index a83a1a35..74459f47 100644 --- a/spec/support/behaviors/requests/model_accepting_base_64_image.rb +++ b/spec/support/behaviors/requests/model_accepting_base_64_image.rb @@ -3,9 +3,9 @@ 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAA AAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=' end - let(:model_name) { described_class.to_s.downcase } + let(:model_name) { described_class.to_s.underscore } - subject(:model) { create(described_class.to_s.downcase) } + subject(:model) { create(described_class.to_s.underscore) } context 'when passing a valid image' do it do