diff --git a/app/controllers/admin/disputes_controller.rb b/app/controllers/admin/disputes_controller.rb new file mode 100644 index 000000000..8061eb890 --- /dev/null +++ b/app/controllers/admin/disputes_controller.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module Admin + class DisputesController < BaseController + load_and_authorize_resource + before_action :set_dispute, only: %i[show edit update destroy] + + # GET /admin/disputes + def index + params[:q] ||= {} + disputes = Dispute.all.order(:domain_name) + @q = disputes.search(params[:q]) + @disputes = @q.result.page(params[:page]) + @disputes = @disputes.per(params[:results_per_page]) if params[:results_per_page].to_i.positive? + end + + # GET /admin/disputes/1 + def show; end + + # GET /admin/disputes/new + def new + @dispute = Dispute.new + end + + # GET /admin/disputes/1/edit + def edit; end + + # POST /admin/disputes + def create + @dispute = Dispute.new(dispute_params) + + if @dispute.save + redirect_to @dispute, notice: 'Dispute was successfully created.' + else + render :new + end + end + + # PATCH/PUT /admin/disputes/1 + def update + if @dispute.update(dispute_params) + redirect_to @dispute, notice: 'Dispute was successfully updated.' + else + render :edit + end + end + + # DELETE /admin/disputes/1 + def destroy + @dispute.destroy + redirect_to disputes_url, notice: 'Dispute was successfully destroyed.' + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_dispute + @dispute = Dispute.find(params[:id]) + end + + # Only allow a trusted parameter "white list" through. + def dispute_params + params.require(:dispute).permit(:domain_name, :password, :expires_at, :comment, :created_at) + end + end +end diff --git a/app/models/ability.rb b/app/models/ability.rb index a727254ad..0e18f433a 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -100,6 +100,7 @@ class Ability can :manage, Invoice can :manage, WhiteIp can :manage, AccountActivity + can :manage, Dispute can :read, ApiLog::EppLog can :read, ApiLog::ReppLog can :update, :pending diff --git a/app/models/dispute.rb b/app/models/dispute.rb new file mode 100644 index 000000000..874e46b30 --- /dev/null +++ b/app/models/dispute.rb @@ -0,0 +1,5 @@ +class Dispute < ApplicationRecord + validates :domain_name, :password, :starts_at, :expires_at, :comment, + presence: true + validates_uniqueness_of :domain_name, case_sensitive: true +end diff --git a/app/views/admin/base/_menu.haml b/app/views/admin/base/_menu.haml index fa1b50440..a327419fd 100644 --- a/app/views/admin/base/_menu.haml +++ b/app/views/admin/base/_menu.haml @@ -32,10 +32,11 @@ %li= link_to t('.zones'), admin_zones_path %li= link_to t('.blocked_domains'), admin_blocked_domains_path %li= link_to t('.reserved_domains'), admin_reserved_domains_path + %li= link_to t('.disputed_domains'), admin_disputes_path %li= link_to t('.epp_log'), admin_epp_logs_path(created_after: 'today') %li= link_to t('.repp_log'), admin_repp_logs_path(created_after: 'today') %li= link_to t('.que'), '/admin/que' %ul.nav.navbar-nav.navbar-right %li= link_to t('.sign_out'), destroy_admin_user_session_path, method: :delete, - class: 'navbar-link' \ No newline at end of file + class: 'navbar-link' diff --git a/app/views/admin/disputes/_form.html.erb b/app/views/admin/disputes/_form.html.erb new file mode 100644 index 000000000..a234c17bc --- /dev/null +++ b/app/views/admin/disputes/_form.html.erb @@ -0,0 +1,58 @@ +<%= form_for([:admin, @dispute], html: { class: 'form-horizontal' }) do |f| %> + <%= render 'shared/full_errors', object: @dispute %> + +
+
+
+
+
+ <%= t(:general) %> +
+
+
+
+
+ <%= f.label :domain_name %> +
+
+ <%= f.text_field(:domain_name, class: 'form-control', disabled: !f.object.new_record?) %> +
+
+
+
+ <%= f.label :password %> +
+
+ <%= f.text_field(:password, placeholder: t(:optional), class: 'form-control') %> + <%= t '.password_hint' %> +
+
+
+
+ <%= f.label :starts_at %> +
+
+ <%= f.text_field(:starts_at, placeholder: t(:optional), class: 'form-control') %> + <%= t '.password_hint' %> +
+
+
+
+ <%= f.label :expires_at %> +
+
+ <%= f.text_field(:expires_at, placeholder: t(:optional), class: 'form-control') %> + <%= t '.password_hint' %> +
+
+
+
+
+
+ +
+
+ <%= button_tag(t(:save), class: 'btn btn-primary') %> +
+
+<% end %> diff --git a/app/views/admin/disputes/edit.haml b/app/views/admin/disputes/edit.haml new file mode 100644 index 000000000..51d77f0cc --- /dev/null +++ b/app/views/admin/disputes/edit.haml @@ -0,0 +1,3 @@ += render 'shared/title', name: t(:edit_pw) + += render 'form' diff --git a/app/views/admin/disputes/index.haml b/app/views/admin/disputes/index.haml new file mode 100644 index 000000000..63438ad9e --- /dev/null +++ b/app/views/admin/disputes/index.haml @@ -0,0 +1,72 @@ +- content_for :actions do + = link_to(t('.new_btn'), new_admin_dispute_path, class: 'btn btn-primary') += render 'shared/title', name: t('.title') + +.row + .col-md-12 + = search_form_for [:admin, @q], html: { style: 'margin-bottom: 0;', class: 'js-form', autocomplete: 'off' } do |f| + .row + .col-md-3 + .form-group + = f.label :name + = f.search_field :name_matches, value: params[:q][:name_matches], class: 'form-control', placeholder: t(:name) + .col-md-3 + .form-group + = f.label t(:created_at_from) + = f.search_field :created_at_gteq, value: params[:q][:created_at_gteq], class: 'form-control js-datepicker', placeholder: t(:created_at_from) + .col-md-3 + .form-group + = f.label t(:created_at_until) + = f.search_field :created_at_lteq, value: params[:q][:created_at_lteq], class: 'form-control js-datepicker', placeholder: t(:created_at_until) + .row + .col-md-3 + .form-group + = label_tag t(:results_per_page) + = text_field_tag :results_per_page, params[:results_per_page], class: 'form-control', placeholder: t(:results_per_page) + .col-md-3{style: 'padding-top: 25px;'} + %button.btn.btn-primary +   + %span.glyphicon.glyphicon-search +   + = link_to(t('.reset_btn'), admin_disputes_path, class: 'btn btn-default') +%hr +.row + .col-md-12 + .table-responsive + %table.table.table-hover.table-bordered.table-condensed + %thead + %tr + %th{class: 'col-xs-2'} + = sort_link(@q, 'name') + %th{class: 'col-xs-2'} + = sort_link(@q, 'password') + %th{class: 'col-xs-2'} + = sort_link(@q, 'expires_at') + %th{class: 'col-xs-2'} + = sort_link(@q, 'comment') + %th{class: 'col-xs-2'} + = sort_link(@q, 'created_at', t(:created_at)) + %th{class: 'col-xs-2'} + = sort_link(@q, 'updated_at', t(:updated_at)) + %th{class: 'col-xs-2'} + = t(:actions) + %tbody + - @disputes.each do |x| + %tr + %td= x.domain_name + %td= x.password + %td= x.expires_at + %td= x.comment + %td= l(x.created_at, format: :short) + %td= l(x.updated_at, format: :short) + %td + = link_to(t(:edit_pw), edit_admin_dispute_path(id: x.id), + class: 'btn btn-primary btn-xs') + = link_to(t(:delete), delete_admin_dispute_path(id: x.id), + data: { confirm: t(:are_you_sure) }, class: 'btn btn-danger btn-xs') +.row + .col-md-6 + = paginate @disputes + .col-md-6.text-right + .pagination + = t(:result_count, count: @disputes.total_count) diff --git a/app/views/admin/disputes/new.haml b/app/views/admin/disputes/new.haml new file mode 100644 index 000000000..0a57af7be --- /dev/null +++ b/app/views/admin/disputes/new.haml @@ -0,0 +1,3 @@ += render 'shared/title', name: t(:add_disputed_domain) + += render 'form' diff --git a/config/locales/admin/disputes.en.yml b/config/locales/admin/disputes.en.yml new file mode 100644 index 000000000..4073d6e61 --- /dev/null +++ b/config/locales/admin/disputes.en.yml @@ -0,0 +1,10 @@ +en: + admin: + disputes: + index: + title: Domain disputes + new_btn: New domain dispute + reset_btn: Reset + + form: + password_hint: Generated automatically if left blank diff --git a/config/locales/admin/menu.en.yml b/config/locales/admin/menu.en.yml index 2c31a5193..1cb396ed6 100644 --- a/config/locales/admin/menu.en.yml +++ b/config/locales/admin/menu.en.yml @@ -13,6 +13,7 @@ en: zones: Zones blocked_domains: Blocked domains reserved_domains: Reserved domains + disputed_domains: Domain disputes epp_log: EPP log repp_log: REPP log que: Que diff --git a/config/locales/en.yml b/config/locales/en.yml index cf72b1027..f1d2ad817 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -629,6 +629,7 @@ en: available_verification_url_not_found: 'Available verification url not found, for domain.' add_reserved_domain: 'Add domain to reserved list' add_blocked_domain: 'Add domain to blocked list' + add_disputed_domain: 'Add domain to disputed list' edit_pw: 'Edit Pw' optional: 'Optional' test_registrar: "Test registrar" diff --git a/config/routes.rb b/config/routes.rb index 53d78dfa9..0d2093d36 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ require_dependency 'epp_constraint' Rails.application.routes.draw do + resources :disputes # https://github.com/internetee/epp_proxy#translation-of-epp-calls namespace :epp do constraints(EppConstraint.new(:session)) do @@ -258,6 +259,7 @@ Rails.application.routes.draw do get 'delete' end end + resources :disputes resources :registrars do resources :api_users, except: %i[index] diff --git a/db/migrate/20200421093637_create_disputes.rb b/db/migrate/20200421093637_create_disputes.rb new file mode 100644 index 000000000..48cdfae59 --- /dev/null +++ b/db/migrate/20200421093637_create_disputes.rb @@ -0,0 +1,14 @@ +class CreateDisputes < ActiveRecord::Migration[5.2] + def change + create_table :disputes do |t| + t.string :domain_name + t.string :password + t.date :expires_at + t.date :starts_at + t.text :comment + t.datetime :created_at + + t.timestamps + end + end +end