diff --git a/Gemfile b/Gemfile index 2acf5d9..4980677 100644 --- a/Gemfile +++ b/Gemfile @@ -49,7 +49,7 @@ gem "bootsnap", require: false group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem - gem "debug", platforms: %i[ mri windows ] + gem "rdbg", '~> 0.1.0' end group :development do @@ -68,3 +68,5 @@ group :test do gem "capybara" gem "selenium-webdriver" end + +gem 'gon', '~> 6.4' diff --git a/Gemfile.lock b/Gemfile.lock index cb67636..c02de11 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -104,6 +104,11 @@ GEM erubi (1.13.0) globalid (1.2.1) activesupport (>= 6.1) + gon (6.4.0) + actionpack (>= 3.0.20) + i18n (>= 0.7) + multi_json + request_store (>= 1.0) i18n (1.14.5) concurrent-ruby (~> 1.0) importmap-rails (2.0.1) @@ -131,6 +136,7 @@ GEM mini_mime (1.1.5) minitest (5.25.0) msgpack (1.7.2) + multi_json (1.15.0) mutex_m (0.2.0) net-imap (0.4.14) date @@ -199,11 +205,15 @@ GEM thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) rake (13.2.1) + rdbg (0.1.0) + debug (>= 1.2.2) rdoc (6.7.0) psych (>= 4.0.0) regexp_parser (2.9.2) reline (0.5.9) io-console (~> 0.5) + request_store (1.7.0) + rack (>= 1.4) rexml (3.3.5) strscan rubyzip (2.3.2) @@ -270,12 +280,13 @@ DEPENDENCIES bcrypt (~> 3.1.7) bootsnap capybara - debug + gon (~> 6.4) importmap-rails jbuilder pg (~> 1.1) puma (>= 5.0) rails (~> 7.1.3, >= 7.1.3.4) + rdbg (~> 0.1.0) selenium-webdriver sprockets-rails stimulus-rails diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d1..8ed14ff 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,37 @@ class ApplicationController < ActionController::Base + + private + + def authenticate_user! + redirect_to new_session_path, notice: "Sign in to do that" unless user_signed_in? + end + + def unauthenticate_user! + redirect_to root_path, notice: "Sign out to do that" if user_signed_in? + end + + def current_user + Current.user ||= authenticate_user_form_session + end + helper_method :current_user + + def authenticate_user_form_session + User.find(session[:user_name]) if session[:user_name].present? + end + + def user_signed_in? + current_user.present? + end + helper_method :user_signed_in? + + def login(user) + Current.user = user + reset_session + session[:user_name] = user.name + end + + def logout + Current.user = nil + reset_session + end end diff --git a/app/controllers/email_confirmations_controller.rb b/app/controllers/email_confirmations_controller.rb new file mode 100644 index 0000000..0e34c47 --- /dev/null +++ b/app/controllers/email_confirmations_controller.rb @@ -0,0 +1,28 @@ +class EmailConfirmationsController < ApplicationController + before_action :authenticate_user! + before_action :set_user_by_token, only: %i[ update ] + + def create + EmailMailer.with( + user: current_user, + token: current_user.generate_token_for(:email_confirmation) + ).email_confirmation.deliver_later + + redirect_to "#", notice: "Check your email to confirm your email" + end + + def update + if @user.update(verified: true) + redirect_to root_path, notice: "Email has been confirmed" + else + redirect_to root_path, alert: "Try again" + end + end + + private + + def set_user_by_token + @user = User.find_by_token_for(:email_confirmation, params[:token]) + redirect_to root_path, alert: "Try again" unless @user.present? + end +end \ No newline at end of file diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb new file mode 100644 index 0000000..2c0820c --- /dev/null +++ b/app/controllers/home_controller.rb @@ -0,0 +1,7 @@ +class HomeController < ApplicationController + def index + if user_signed_in? + gon.var_new = current_user.task_groups.find_or_create_by(name: current_user.default_task_group_name).tasks.order_by_time.pluck(:during_time) + end + end +end \ No newline at end of file diff --git a/app/controllers/password_resets_controller.rb b/app/controllers/password_resets_controller.rb new file mode 100644 index 0000000..1c64b66 --- /dev/null +++ b/app/controllers/password_resets_controller.rb @@ -0,0 +1,41 @@ +class PasswordResetsController < ApplicationController + before_action :unauthenticate_user! + before_action :set_user_by_token, only: %i[ edit update ] + + def new + end + + def edit + end + + def create + if user = User.find_by(email: params[:email]) + PasswordMailer.with( + user: user, + token: user.generate_token_for(:password_reset) + ).password_reset.deliver_later + end + + redirect_to root_path, notice: "Check your email to reset your password" + end + + def update + if @user.update(password_params) + redirect_to new_session_path, notice: "Password has been reset" + else + render :edit, status: :unprocessable_entity + end + end + + private + + def set_user_by_token + @user = User.find_by_token_for(:password_reset, params[:token]) + redirect_to new_password_reset_path, alert: "Try again" unless @user.present? + end + + def password_params + params.require(:user).permit(:password, :password_confirmation) + end + +end diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb new file mode 100644 index 0000000..219f2ce --- /dev/null +++ b/app/controllers/passwords_controller.rb @@ -0,0 +1,18 @@ +class PasswordsController < ApplicationController + before_action :authenticate_user! + + def update + if current_user.update(password_params) + redirect_to edit_user_profile_path, notice: "Your password was updated succesfully" + else + redirect_to edit_user_profile_path, status: :unprocessable_entity + end + end + + private + + def password_params + params.require(:user).permit(:password, :password_confirmation, :password_challenge).with_defaults(password_challenge: "") + end + +end \ No newline at end of file diff --git a/app/controllers/secret_groups_controller.rb b/app/controllers/secret_groups_controller.rb new file mode 100644 index 0000000..7e8b497 --- /dev/null +++ b/app/controllers/secret_groups_controller.rb @@ -0,0 +1,71 @@ +class SecretGroupsController < ApplicationController + before_action :authenticate_user! + before_action :set_secret_group, only: %i[ show edit update destroy ] + + # GET /secret_groups or /secret_groups.json + def index + @secret_groups = current_user.secret_groups.all + end + + # GET /secret_groups/name or /secret_groups/name.json + def show + end + + # GET /secret_groups/new + def new + @secret_group = SecretGroup.new + end + + # GET /secret_groups/1/edit + def edit + end + + # POST /secret_groups or /secret_groups.json + def create + @secret_group = current_user.secret_groups.new(secret_group_params) + + respond_to do |format| + if @secret_group.save + format.html { redirect_to user_secret_group_path(name: @secret_group.name, owner: @secret_group.owner), notice: "Secret group was successfully created." } + format.json { render :show, status: :created, location: @secret_group } + else + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @secret_group.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /secret_groups/1 or /secret_groups/1.json + def update + respond_to do |format| + if @secret_group.update(secret_group_params) + format.html { redirect_to user_secret_group_path(owner: @secret_group.owner, name: @secret_group.name), notice: "Secret group was successfully updated." } + format.json { render :show, status: :ok, location: @secret_group } + else + format.html { render :edit, status: :unprocessable_entity } + format.json { render json: @secret_group.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /secret_groups/1 or /secret_groups/1.json + def destroy + @secret_group.destroy! + + respond_to do |format| + format.html { redirect_to user_secret_groups_path(owner: current_user.name), notice: "Secret group was successfully destroyed." } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_secret_group + @secret_group = current_user.secret_groups.find_by_name(params[:name]) + end + + # Only allow a list of trusted parameters through. + def secret_group_params + params.require(:secret_group).permit(:name, :description) + end +end diff --git a/app/controllers/secrets_controller.rb b/app/controllers/secrets_controller.rb new file mode 100644 index 0000000..956a31b --- /dev/null +++ b/app/controllers/secrets_controller.rb @@ -0,0 +1,82 @@ +class SecretsController < ApplicationController + before_action :authenticate_user!, except: %i[show] + + # GET /secrets?group_name=name or /secrets.json?group_name=name + def index + if params[:group_name].present? + @secretgroup = current_user.secret_groups.find_by_name(params[:group_name]) + redirect_back fallback_location: root_path, notice: "Group not found" unless @secretgroup.present? + @secrets = @secretgroup.secrets + + else + @secrets = current_user.secrets + end + end + + # GET /secrets/1 or /secrets/1.json + def show + @secret = Secret.find(params[:id]) + end + + # GET /secrets/new + def new + @secret = current_user.secret_groups.find_by_name(params[:secret_group_name]).secrets.new + end + + # GET /secrets/1/edit + def edit + @secret = current_user.secrets.find(params[:id]) + redirect_back fallback_location: root_path, notice: 'Secret not found' unless @secret.present? + end + + # POST /secrets or /secrets.json + def create + @secret = current_user.secrets.new(secret_create_params) + respond_to do |format| + if @secret.save + format.html { redirect_to secret_url(@secret), notice: 'Secret was successfully created.' } + format.json { render :show, status: :created, location: @secret } + else + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @secret.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /secrets/1 or /secrets/1.json + def update + @secret = Secret.find(params[:id]) + respond_to do |format| + if @secret.update(secret_update_params) + format.html do + redirect_to user_secret_group_secret_path(owner: @secret.owner, secret_group_name: @secret.group_name, id: @secret.id), + notice: 'Secret was successfully updated.' + end + format.json { render :show, status: :ok, location: @secret } + else + format.html { render :edit, status: :unprocessable_entity } + format.json { render json: @secret.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /secrets/1 or /secrets/1.json + def destroy + @secret = Secret.find(params[:id]) + @secret.destroy! + respond_to do |format| + format.html { redirect_to root_path, notice: 'Secret was successfully destroyed.' } + format.json { head :no_content } + end + end + + private + + def secret_create_params + params.require(:secret).permit(:name, :description, :value, :interval, :is_google, :length, :group_name) + end + + def secret_update_params + params.require(:secret).permit(:name, :description, :group_name) + end +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000..0940529 --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,31 @@ +class SessionsController < ApplicationController + + def new + end + + def create + if params[:email_or_user_name][/\A[^\s@]{4,16}\z/].present? + params[:name] = params[:email_or_user_name] + elsif params[:email_or_user_name].strip.downcase[/\A[a-z0-9+_.-]+@([a-z0-9]+\.)+[a-z]{2,6}\z/].present? + params[:name] = User.find_by(email: params[:email]) + end + + respond_to do |format| + if @user = User.authenticate_by(name: params[:name], password: params[:password]) + login @user + format.html { redirect_to root_path, notice: "You have been signed in." } + format.json { render json: @user, status: :created, location: @user } + else + flash[:alert] = "Incorrect email or password" + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @user.errors, status: :unprocessable_entity } + end + end + end + + def destroy + logout + redirect_to root_path, notice: "You have been logged out." + end + +end \ No newline at end of file diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2f1084d..3dc0dce 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,70 +1,85 @@ class UsersController < ApplicationController - before_action :set_user, only: %i[ show edit update destroy ] + before_action :authenticate_user!, only: %i[ edit update destroy profile ] - # GET /users or /users.json - def index - @users = User.all + def show + @user = User.find(params[:name]) + redirect_to root_path unless @user.present? end - # GET /users/1 or /users/1.json - def show + def profile + @user = current_user end - # GET /users/new def new @user = User.new end - # GET /users/1/edit + def search + @user = User.find_by(name: params[:name]) + if @user.present? + redirect_to user_path(@user) + else + redirect_to root_path, notice: "User not found" + end + end + def edit + @user = current_user end - # POST /users or /users.json def create - @user = User.new(user_params) + @user = User.new(user_create_params) respond_to do |format| if @user.save - format.html { redirect_to user_url(@user), notice: "User was successfully created." } + login @user + format.html { redirect_to root_path, notice: "User was successfully created." } format.json { render :show, status: :created, location: @user } else + gon.errors = @user.errors.each format.html { render :new, status: :unprocessable_entity } format.json { render json: @user.errors, status: :unprocessable_entity } end end end - # PATCH/PUT /users/1 or /users/1.json def update respond_to do |format| - if @user.update(user_params) - format.html { redirect_to user_url(@user), notice: "User was successfully updated." } - format.json { render :show, status: :ok, location: @user } + if current_user.update(user_update_params) + logout + login User.find_by(user_update_params) + format.html { redirect_to user_url(current_user), notice: "User was successfully updated." } + format.json { render :show, status: :ok, location: current_user } else format.html { render :edit, status: :unprocessable_entity } - format.json { render json: @user.errors, status: :unprocessable_entity } + format.json { render json: current_user.errors, status: :unprocessable_entity } end end end - # DELETE /users/1 or /users/1.json def destroy - @user.destroy! - + @user = User.authenticate_by(name: current_user.name, password: params[:password]) + respond_to do |format| - format.html { redirect_to users_url, notice: "User was successfully destroyed." } - format.json { head :no_content } + if @user.present? + logout + @user.destroy! + format.html { redirect_to root_path, notice: "User was successfully destroyed." } + format.json { head :no_content } + else + format.html { redirect_to user_profile_path, alert: "Password incorrect"} + format.json { head :no_content } + end end end private - # Use callbacks to share common setup or constraints between actions. - def set_user - @user = User.find(params[:id]) + + def user_create_params + params.require(:user).permit(:name, :email, :password, :password_confirmation) end - # Only allow a list of trusted parameters through. - def user_params - params.require(:user).permit(:email, :password, :password_confirmation) + def user_update_params + params.require(:user).permit(:name, :email) end end diff --git a/app/mailers/email_mailer.rb b/app/mailers/email_mailer.rb new file mode 100644 index 0000000..f6b61ab --- /dev/null +++ b/app/mailers/email_mailer.rb @@ -0,0 +1,11 @@ +class EmailMailer < ApplicationMailer + + # Subject can be set in your I18n file at config/locales/en.yml + # with the following lookup: + # + # en.email_mailer.email_confirmation.subject + # + def email_confirmation + mail to: params[:user].email + end +end diff --git a/app/mailers/password_mailer.rb b/app/mailers/password_mailer.rb new file mode 100644 index 0000000..dd28d01 --- /dev/null +++ b/app/mailers/password_mailer.rb @@ -0,0 +1,11 @@ +class PasswordMailer < ApplicationMailer + + # Subject can be set in your I18n file at config/locales/en.yml + # with the following lookup: + # + # en.password_mailer.password_reset.subject + # + def password_reset + mail to: params[:user].email + end +end diff --git a/app/models/current.rb b/app/models/current.rb new file mode 100644 index 0000000..5334537 --- /dev/null +++ b/app/models/current.rb @@ -0,0 +1,3 @@ +class Current < ActiveSupport::CurrentAttributes + attribute :user +end \ No newline at end of file diff --git a/app/models/secret.rb b/app/models/secret.rb new file mode 100644 index 0000000..b0c134c --- /dev/null +++ b/app/models/secret.rb @@ -0,0 +1,3 @@ +class Secret < ApplicationRecord + belongs_to :secret_group, query_constraints: %i[group_name owner] +end diff --git a/app/models/secret_group.rb b/app/models/secret_group.rb new file mode 100644 index 0000000..411168a --- /dev/null +++ b/app/models/secret_group.rb @@ -0,0 +1,6 @@ +class SecretGroup < ApplicationRecord + belongs_to :user, primary_key: :name, foreign_key: :owner + has_many :secrets, query_constraints: %i[group_name owner], primary_key: %i[name owner] + + self.primary_key = %i[name owner] +end diff --git a/app/models/user.rb b/app/models/user.rb index d67da20..0442d0e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,3 +1,37 @@ class User < ApplicationRecord has_secure_password + has_many :secret_groups, primary_key: :name, foreign_key: :owner + has_many :secrets, primary_key: :name, foreign_key: :owner + has_one :default_group, class_name: "SecretGroup", primary_key: :default_group_name, foreign_key: :name, required: false + + self.primary_key = :name + + normalizes :email, with: ->(email) { email.strip.downcase } + validates :email, + format: { with: /\A[a-z0-9+_.-]+@([a-z0-9]+\.)+[a-z]{2,6}\z/, message: "Invalid email."}, + uniqueness: { case_sensitive: false }, + length: { minimum: 4, maximum: 254 } + + validates :name, + format: { with: /\A[^\s@]{4,16}\z/, message: "Invalid user name format."}, + uniqueness: { case_sensitive: false }, + length: { minimum: 4 } + + generates_token_for :password_reset, expires_in: 10.minutes do + password_salt&.last(10) + end + + generates_token_for :email_confirmation, expires_in: 12.hours do + email + end + + before_update do + if email_changed? + self.verified=false + end + end + + after_create do + self.secret_groups.create! name: self.default_group_name, description: "Defaut group that secrets endup in." + end end diff --git a/config/routes.rb b/config/routes.rb index 4067cd3..a300821 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,11 +1,44 @@ +# Rails.application.routes.draw do +# # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html + +# # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. +# # Can be used by load balancers and uptime monitors to verify that the app is live. +# get "up" => "rails/health#show", as: :rails_health_check + +# # Defines the root path route ("/") +# # root "posts#index" +# end Rails.application.routes.draw do - resources :users - # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html + get 'up' => 'rails/health#show', as: :rails_health_check + + root 'home#index' + + get '/login', to: 'sessions#new', as: 'new_session' + resource :session, only: %i[create destroy] + + get '/forgot_password', to: 'password_resets#new', as: 'new_password_reset' + get '/reset_password', to: 'password_resets#edit', as: 'edit_password_reset' + resource :password_reset, only: %i[create update] + + resource :email_confirmation, only: %i[create] + get '/email_confirmation', to: 'email_confirmations#update' + + get '/signup', to: 'users#new', as: 'new_user' + post '/signup', to: 'users#create', as: 'users' + + patch '/profile/change_password', to: 'passwords#update', as: 'user_password_change' + put '/profile/change_password', to: 'passwords#update' + + resources :secret_groups, only: %i[new edit create update destroy], param: :name do + resources :secrets, only: :new + end - # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. - # Can be used by load balancers and uptime monitors to verify that the app is live. - get "up" => "rails/health#show", as: :rails_health_check + resources :secrets, only: %i[index create edit update destroy] - # Defines the root path route ("/") - # root "posts#index" + get '/profile/edit', to: 'users#edit', as: 'edit_user_profile' + patch '/profile/edit', to: 'users#update' + put '/profile/edit', to: 'users#update' + post '/user_search', to: 'users#search', as: 'user_search' + get '/profile', to: 'users#profile', as: 'user_profile' + delete '/profile', to: 'users#destroy' end diff --git a/db/migrate/20240814200701_create_users.rb b/db/migrate/20240814200701_create_users.rb deleted file mode 100644 index 89509d3..0000000 --- a/db/migrate/20240814200701_create_users.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateUsers < ActiveRecord::Migration[7.1] - def change - create_table :users do |t| - t.string :email - t.string :password_digest - - t.timestamps - end - add_index :users, :email, unique: true - end -end diff --git a/db/migrate/20240927121541_users.rb b/db/migrate/20240927121541_users.rb new file mode 100644 index 0000000..860cc39 --- /dev/null +++ b/db/migrate/20240927121541_users.rb @@ -0,0 +1,16 @@ +class Users < ActiveRecord::Migration[7.1] + def change + create_table :users, id: false do |t| + t.string :name, null: false + t.string :email, null: false + t.string :password_digest, null: false + t.boolean :verified, default: false, null: false + t.string :default_group_name, default: "All", null: false + + t.timestamps + end + + add_index :users, :email, unique: true + add_index :users, :name, unique: true + end +end diff --git a/db/migrate/20240927122143_secrets.rb b/db/migrate/20240927122143_secrets.rb new file mode 100644 index 0000000..648e589 --- /dev/null +++ b/db/migrate/20240927122143_secrets.rb @@ -0,0 +1,17 @@ +class Secrets < ActiveRecord::Migration[7.1] + def change + create_table :secrets do |t| + t.string :name + t.text :description + t.string :value, null: false + t.bigint :interval, default: 30000000, null: false + t.boolean :is_google, default: false, null: false + t.integer :length, default: 6, null: false + t.string :group_name, null: false + t.string :owner, null: false + + t.timestamps + end + add_index :secrets, [:group_name, :owner] + end +end diff --git a/db/migrate/20240927122412_secret_groups.rb b/db/migrate/20240927122412_secret_groups.rb new file mode 100644 index 0000000..366cc58 --- /dev/null +++ b/db/migrate/20240927122412_secret_groups.rb @@ -0,0 +1,15 @@ +class SecretGroups < ActiveRecord::Migration[7.1] + def change + create_table :secret_groups, id: false, primary_key: [:name, :owner] do |t| + t.string :name, null: false + t.string :owner, null: false + t.text :description + + t.timestamps + end + + add_index :secret_groups, [:name, :owner], unique: true + add_foreign_key :secret_groups, :users, column: :owner, primary_key: :name, on_update: :cascade, on_delete: :cascade + add_foreign_key :secrets, :secret_groups, column: [:group_name, :owner], primary_key: [:name, :owner], on_update: :cascade, on_delete: :cascade + end +end diff --git a/db/schema.rb b/db/schema.rb index 7ebcfa4..8331cd2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,16 +10,45 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_08_14_200701) do +ActiveRecord::Schema[7.1].define(version: 2024_09_27_122412) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - create_table "users", force: :cascade do |t| - t.string "email" - t.string "password_digest" + create_table "secret_groups", id: false, force: :cascade do |t| + t.string "name", null: false + t.string "owner", null: false + t.text "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["name", "owner"], name: "index_secret_groups_on_name_and_owner", unique: true + end + + create_table "secrets", force: :cascade do |t| + t.string "name" + t.text "description" + t.string "value", null: false + t.bigint "interval", default: 30000000, null: false + t.boolean "is_google", default: false, null: false + t.integer "length", default: 6, null: false + t.string "group_name", null: false + t.string "owner", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["group_name", "owner"], name: "index_secrets_on_group_name_and_owner" + end + + create_table "users", id: false, force: :cascade do |t| + t.string "name", null: false + t.string "email", null: false + t.string "password_digest", null: false + t.boolean "verified", default: false, null: false + t.string "default_group_name", default: "All", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["email"], name: "index_users_on_email", unique: true + t.index ["name"], name: "index_users_on_name", unique: true end + add_foreign_key "secret_groups", "users", column: "owner", primary_key: "name", on_update: :cascade, on_delete: :cascade + add_foreign_key "secrets", "secret_groups", column: ["group_name", "owner"], primary_key: ["name", "owner"], on_update: :cascade, on_delete: :cascade end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb deleted file mode 100644 index 655da23..0000000 --- a/test/controllers/users_controller_test.rb +++ /dev/null @@ -1,48 +0,0 @@ -require "test_helper" - -class UsersControllerTest < ActionDispatch::IntegrationTest - setup do - @user = users(:one) - end - - test "should get index" do - get users_url - assert_response :success - end - - test "should get new" do - get new_user_url - assert_response :success - end - - test "should create user" do - assert_difference("User.count") do - post users_url, params: { user: { email: @user.email, password: "secret", password_confirmation: "secret" } } - end - - assert_redirected_to user_url(User.last) - end - - test "should show user" do - get user_url(@user) - assert_response :success - end - - test "should get edit" do - get edit_user_url(@user) - assert_response :success - end - - test "should update user" do - patch user_url(@user), params: { user: { email: @user.email, password: "secret", password_confirmation: "secret" } } - assert_redirected_to user_url(@user) - end - - test "should destroy user" do - assert_difference("User.count", -1) do - delete user_url(@user) - end - - assert_redirected_to users_url - end -end diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml deleted file mode 100644 index 0bd7fcc..0000000 --- a/test/fixtures/users.yml +++ /dev/null @@ -1,9 +0,0 @@ -# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -one: - email: MyString - password_digest: <%= BCrypt::Password.create("secret") %> - -two: - email: MyString - password_digest: <%= BCrypt::Password.create("secret") %> diff --git a/test/models/user_test.rb b/test/models/user_test.rb deleted file mode 100644 index 5c07f49..0000000 --- a/test/models/user_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "test_helper" - -class UserTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end -end diff --git a/test/system/users_test.rb b/test/system/users_test.rb deleted file mode 100644 index dbd0e9e..0000000 --- a/test/system/users_test.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "application_system_test_case" - -class UsersTest < ApplicationSystemTestCase - setup do - @user = users(:one) - end - - test "visiting the index" do - visit users_url - assert_selector "h1", text: "Users" - end - - test "should create user" do - visit users_url - click_on "New user" - - fill_in "Email", with: @user.email - fill_in "Password", with: "secret" - fill_in "Password confirmation", with: "secret" - click_on "Create User" - - assert_text "User was successfully created" - click_on "Back" - end - - test "should update User" do - visit user_url(@user) - click_on "Edit this user", match: :first - - fill_in "Email", with: @user.email - fill_in "Password", with: "secret" - fill_in "Password confirmation", with: "secret" - click_on "Update User" - - assert_text "User was successfully updated" - click_on "Back" - end - - test "should destroy User" do - visit user_url(@user) - click_on "Destroy this user", match: :first - - assert_text "User was successfully destroyed" - end -end