diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb new file mode 100644 index 000000000..42c9c4b2a --- /dev/null +++ b/app/controllers/admin/users_controller.rb @@ -0,0 +1,48 @@ +class Admin::UsersController < AdminController + before_action :set_user, only: [:show, :edit, :update, :destroy] + + def index + @q = User.search(params[:q]) + @users = @q.result.page(params[:page]) + end + + def new + @user = User.new + end + + def create + @user = User.new(user_params) + + if @user.save + flash[:notice] = I18n.t('shared.user_added') + redirect_to [:admin, @user] + else + flash.now[:alert] = I18n.t('shared.failed_to_add_user') + render 'new' + end + end + + def show; end + + def edit; end + + def update + if @user.update(user_params) + flash[:notice] = I18n.t('shared.record_updated') + redirect_to [:admin, @user] + else + flash.now[:alert] = I18n.t('shared.failed_to_update_record') + render 'edit' + end + end + + private + + def set_user + @user = User.find(params[:id]) + end + + def user_params + params.require(:user).permit(:username, :password, :identity_code, :email, :registrar_id, :admin, :registrar_typeahead) + end +end diff --git a/app/models/domain.rb b/app/models/domain.rb index d73d630bb..1d1c3ccac 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -51,7 +51,6 @@ class Domain < ActiveRecord::Base validate :validate_domain_statuses_uniqueness, if: :new_record? attr_accessor :owner_contact_typeahead - attr_accessor :registrar_typeahead def name=(value) value.strip! @@ -64,10 +63,6 @@ class Domain < ActiveRecord::Base @owner_contact_typeahead || owner_contact.try(:name) || nil end - def registrar_typeahead - @registrar_typeahead || registrar || nil - end - def pending_transfer domain_transfers.find_by(status: DomainTransfer::PENDING) end diff --git a/app/models/user.rb b/app/models/user.rb index 091281e24..7951cd2a5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,4 +8,32 @@ class User < ActiveRecord::Base belongs_to :role belongs_to :registrar + + validates :username, :password, presence: true + validates :identity_code, uniqueness: true, allow_blank: true + validate :registrar_presence + + before_save :manage_registrar + + attr_accessor :registrar_typeahead + + def to_s + username + end + + def registrar_typeahead + @registrar_typeahead || registrar || nil + end + + private + + def registrar_presence + if !admin && !registrar + errors.add(:registrar, :blank) + end + end + + def manage_registrar + self.registrar = nil if admin? + end end diff --git a/app/views/admin/users/_form.haml b/app/views/admin/users/_form.haml new file mode 100644 index 000000000..4444d03de --- /dev/null +++ b/app/views/admin/users/_form.haml @@ -0,0 +1,56 @@ += form_for([:admin, @user]) do |f| + - if @user.errors.any? + - @user.errors.each do |attr, err| + = err + %br + - if @user.errors.any? + %hr + + .row + .col-md-6 + .form-group + = f.label :username + = f.text_field(:username, class: 'form-control') + .form-group + = f.label :password + = f.text_field(:password, class: 'form-control') + .form-group + = f.label :identity_code + = f.text_field(:identity_code, class: 'form-control') + + .col-md-6.text-left + .form-group + = f.label :email + = f.text_field(:email, class: 'form-control') + .form-group + .form-group.has-feedback.js-typeahead-container + = f.label :registrar_typeahead + = f.text_field(:registrar_typeahead, class: 'form-control js-registrar-typeahead', placeholder: t('shared.registrar'), autocomplete: 'off') + %span.glyphicon.glyphicon-ok.form-control-feedback.js-typeahead-ok.hidden + %span.glyphicon.glyphicon-remove.form-control-feedback.js-typeahead-remove + = f.hidden_field(:registrar_id, class: 'js-registrar-id') + .form-group + .checkbox + %label{for: 'user_admin'} + = f.check_box(:admin, class: 'js-admin') + = t('shared.admin') + %hr + .row + .col-md-12.text-right + = button_tag(t('shared.save'), class: 'btn btn-primary') + +:javascript + Autocomplete.bindAdminRegistrarSearch(); + toggleRegistrar(); + + $('#user_admin').click(function() { + toggleRegistrar(); + }); + + function toggleRegistrar() { + if($('.js-admin').is(':checked')) { + $('.js-registrar-typeahead, .js-registrar-id').attr('disabled', true); + } else { + $('.js-registrar-typeahead, .js-registrar-id').attr('disabled', false); + } + } diff --git a/app/views/admin/users/edit.haml b/app/views/admin/users/edit.haml new file mode 100644 index 000000000..3edfd4c3a --- /dev/null +++ b/app/views/admin/users/edit.haml @@ -0,0 +1,9 @@ +.row + .col-sm-6 + %h2.text-center-xs + = "#{t('shared.edit_user')}" + .col-sm-6 + %h2.text-right.text-center-xs + = link_to(t('shared.back_to_user'), [:admin, @user], class: 'btn btn-default') +%hr += render 'form' diff --git a/app/views/admin/users/index.haml b/app/views/admin/users/index.haml new file mode 100644 index 000000000..2c847a7f8 --- /dev/null +++ b/app/views/admin/users/index.haml @@ -0,0 +1,34 @@ +.row + .col-sm-6 + %h2.text-center-xs= t('shared.users') + .col-sm-6 + %h2.text-right.text-center-xs + = link_to(t('shared.create_new_user'), new_admin_user_path, class: 'btn btn-primary') +%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, 'username') + %th{class: 'col-xs-2'} + = sort_link(@q, 'email', t('shared.email')) + %th{class: 'col-xs-2'} + = sort_link(@q, 'identity_code', t('shared.identity_code')) + %th{class: 'col-xs-2'} + = sort_link(@q, 'admin', t('shared.admin')) + %th{class: 'col-xs-2'} + = sort_link(@q, 'registrar', t('shared.registrar')) + %tbody + - @users.each do |x| + %tr + %td= link_to(x, [:admin, x]) + %td= x.email + %td= x.identity_code + %td= x.admin + %td= x.registrar +.row + .col-md-12 + = paginate @users diff --git a/app/views/admin/users/new.haml b/app/views/admin/users/new.haml new file mode 100644 index 000000000..99f2800d3 --- /dev/null +++ b/app/views/admin/users/new.haml @@ -0,0 +1,3 @@ +%h2= t('shared.create_new_user') +%hr += render 'form' diff --git a/app/views/admin/users/show.haml b/app/views/admin/users/show.haml new file mode 100644 index 000000000..ab406d0a8 --- /dev/null +++ b/app/views/admin/users/show.haml @@ -0,0 +1,46 @@ +.row + .col-sm-6 + %h2.text-center-xs + = "#{t('shared.user_details')}" + .col-sm-6 + %h2.text-right.text-center-xs + = link_to(t('shared.edit'), edit_admin_user_path(@user), class: 'btn btn-primary') + = link_to(t('shared.delete'), admin_user_path(@user), method: :delete, data: { confirm: t('shared.are_you_sure') }, class: 'btn btn-danger') + +%hr +- if @user.errors.any? + - @user.errors.each do |attr, err| + = err + %br +- if @user.errors.any? + %hr +.row + .col-md-6 + .panel.panel-default + .panel-heading + %h3.panel-title= t('shared.general') + .panel-body + %dl.dl-horizontal + %dt= t('shared.username') + %dd= @user.username + + %dt= t('shared.password') + %dd= @user.password + + %dt= t('shared.identity_code') + %dd= @user.identity_code + + .col-md-6 + .panel.panel-default + .panel-heading + %h3.panel-title= t('shared.address') + .panel-body + %dl.dl-horizontal + %dt= t('shared.email') + %dd= @user.email + + %dt= t('shared.registrar') + %dd= @user.registrar + + %dt= t('shared.admin') + %dd= @user.admin diff --git a/app/views/layouts/application.haml b/app/views/layouts/application.haml index 397d3c93e..d733865be 100644 --- a/app/views/layouts/application.haml +++ b/app/views/layouts/application.haml @@ -38,7 +38,7 @@ %li = link_to t('shared.setting_groups'), admin_setting_groups_path %li - = link_to t('shared.users'), '#' + = link_to t('shared.users'), admin_users_path %li = link_to t('shared.epp_users'), '#' %li.divider diff --git a/config/locales/en.yml b/config/locales/en.yml index 482adb60b..5c06de1db 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -156,6 +156,20 @@ en: address: blank: 'Address is missing' + user: + attributes: + username: + blank: 'Username is missing' + taken: 'Username already exists' + password: + blank: 'Password is missing' + identity_code: + taken: 'Identity code already exists' + email: + blank: 'Email is missing' + registrar: + blank: 'Registrar is missing' + attributes: epp_domain: &epp_domain_attributes name: 'Domain name' @@ -332,3 +346,14 @@ en: registrar_deleted: 'Registrar deleted' failed_to_delete_registrar: 'Failed to delete registrar' + users: 'Users' + create_new_user: 'Create new user' + user_added: 'User added!' + failed_to_add_user: 'Failed to add user' + admin: 'Admin' + user_details: 'User details' + edit_user: 'Edit user' + back_to_user: 'Back to user' + + record_updated: 'Record updated' + failed_to_update_record: 'Failed to update record' diff --git a/config/routes.rb b/config/routes.rb index bb97f5f83..c169880ba 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -21,6 +21,8 @@ Rails.application.routes.draw do end end + resources :users + root 'domains#index' end