From: OHASHI, Norikazu Date: Fri, 10 Apr 2020 08:08:56 +0000 (+0900) Subject: 管理者ユーザーまわりについて手を付けた X-Git-Url: http://www.wald-der-katze.sakura.ne.jp/git/gitweb.cgi?a=commitdiff_plain;h=fea2fd7cd3df3766c544e607a16bcb879da0c6df;p=book_server.git 管理者ユーザーまわりについて手を付けた --- diff --git a/create_table.sql b/create_table.sql index fc3597a..5b00dcc 100644 --- a/create_table.sql +++ b/create_table.sql @@ -43,8 +43,9 @@ CREATE TABLE book_covers ( create_at DATETIME NOT NULL, update_at DATETIME NOT NULL); -CREATE VIEW book_fulls (isbn, title, volume, author, publisher, user_id) AS +CREATE VIEW book_fulls (isbn, title, volume, author, publisher, pubdate, user_id) AS SELECT B.isbn AS isbn, B.title AS title, B.volume AS volume, - B.author AS author, B.publisher AS publisher, C.user_id AS user_id + B.author AS author, B.publisher AS publisher, B.pubdate as pubdate, + C.user_id AS user_id FROM (books AS B left join book_collections AS C - ON((B.isbn = C.isbn))); + ON((B.isbn = C.isbn))); diff --git a/sinatra/app/controllers/web_gui.rb b/sinatra/app/controllers/web_gui.rb index 623e614..750abfb 100644 --- a/sinatra/app/controllers/web_gui.rb +++ b/sinatra/app/controllers/web_gui.rb @@ -1,4 +1,4 @@ -# coding: utf-8 + # coding: utf-8 # Web GUI用コントローラ # @author OHASHI, Norikazu @@ -46,7 +46,7 @@ class WebGui < Sinatra::Base haml pageId end - # + # アップロード用にファイルからデータを読む # @params [Hash] Upload用パラメータ # @return [Hash] Uploadデータ情報 def getUploadData(upload_param) @@ -138,7 +138,7 @@ class WebGui < Sinatra::Base user = UserAccount.getUser(id) @id = id @username = user.full_name - @is_addmin = user.isAddmin + @is_admin = UserAccount.checkAdmin(id) @newest_list = BookManager.newestListOfBooks(id, 5) goPage :user_home end @@ -153,9 +153,11 @@ class WebGui < Sinatra::Base end begin user = UserAccount.getUser(id) - @admin_f = false + @is_admin = UserAccount.checkAdmin(id); + @admin_type = false @id = id @username = user.full_name + @editname = user.full_name @account = user.user_name @email = user.email rescue UserAccount::NotFoundInstanceError @@ -164,6 +166,35 @@ class WebGui < Sinatra::Base goPage :user_edit end + # ユーザ情報編集ページ(ユーザID指定) + # @path_param [Integer] editId 更新するユーザのId + # @raise [WebError] セッションの期限切れ + # @raise [WebError] ユーザID不正 + get '/user_edit/:editId' do + id = session[:userId] + edit_id = params[:editId] + if (id == nil) + raise WebError.new(status: 408, message: "セッション期限切れです。再ログインをしてください。") + end + if (not UserAccount.checkAdmin(id)) + raise WebError.new(status: 405, message: "管理者アカウントでないと操作できません。") + end + begin + user = UserAccount.getUser(id) + edit_user = UserAccount.getUser(edit_id) + @admin_type = true + @is_admin = UserAccount.checkAdmin(id); + @id = edit_id + @username = user.full_name + @editname = edit_user.full_name + @account = edit_user.user_name + @email = edit_user.email + rescue UserAccount::NotFoundInstanceError + raise WebError.new(status: 400, message: "該当するユーザが存在しません。") + end + goPage :user_edit + end + # ユーザ情報編集ページ(POST) # @post_param name [String] ログインユーザ名, # @post_param try_pass [String] 旧パスワード @@ -199,7 +230,112 @@ class WebGui < Sinatra::Base end end - # 蔵書の登録 + # ユーザ情報編集ページ(ユーザID指定)(POST) + # @post_param name [String] ログインユーザ名, + # @post_param try_pass [String] 旧パスワード + # @post_param new_pass [String] 新パスワード + # @post_param full_name [String] フルネーム + # @post_param email [String] Eメール + # @raise [WebError] セッションの期限切れ + # @raise [WebError] ユーザ情報編集失敗 + post '/user_edit/:editId' do + id = session[:userId] + edit_id = params[:editId] + full_name = params[:full_name] + email = params[:email] + new_pass = params[:new_pass] + + if (id == nil) + raise WebError.new(staut: 408, message: "セッション期限切れです。再ログインをしてください。") + end + if (not UserAccount.checkAdmin(id)) + raise WebError.new(status: 405, message: "管理者アカウントでないと操作できません。") + end + begin + params = {passwd: new_pass, + full_name: full_name, + email: email} + UserAccount.updateUser(edit_id, params) + redirect to('/user_list') + rescue UserAccount::NotFoundInstanceError, + UserAccount::AuthenticationError + raise WebError.new(status: 400, message: "ユーザ情報の編集に失敗しました。", refs: "/user_edit") + end + end + + # ユーザ一覧ページ + # @raise [WebError] セッションの期限切れ + # @raise [WebError] ユーザID不正 + get '/user_list' do + cache_control :public, :must_revalidate, :max_age => 30 + id = session[:userId] + book_update_f = false + session[:book_update_f] = book_update_f + if (id == nil) + raise WebError.new(status: 408, message: "セッション期限切れです。再ログインをしてください。") + end + if (not UserAccount.checkAdmin(id)) + raise WebError.new(status: 405, message: "管理者アカウントでないと操作できません。") + end + begin + user = UserAccount.getUser(id) + @user_list = UserAccount.getUserList(id); + @username = user.full_name + @is_admin = UserAccount.checkAdmin(id); + rescue UserAccount::AuthenticationError + raise WebError.new(status: 405, message: "管理者でしか利用できません。") + end + goPage :user_list + end + + + # ユーザ情報の削除 + # @path_param [integer] deletId 削除対象のユーザId + # @raise [WebError] セッションの期限切れ + get '/user_delete/:deleteId' do + cache_control :public, :must_revalidate, :max_age => 30 + id = session[:userId] + delete_id = params[:deleteId] + if (id == nil) + raise WebError.new(status: 408, message: "セッション期限切れです。再ログインをしてください。") + end + if (not UserAccount.checkAdmin(id)) + raise WebError.new(status: 405, message: "管理者アカウントでないと操作できません。") + end + begin + user = UserAccount.getUser(id) + @delete_user = UserAccount.getUser(delete_id) + @username = user.full_name + rescue UserAccount::NotFoundInstanceError + raise WebError.new(status: 404, message: "ユーザ情報が存在しません。") + end + goPage :user_delete + end + + # ユーザ情報の削除 (削除実行) + # @path_param [Integer] deleteId 削除対象のユーザId + # @raise [WebError] セッションの期限切れ + get '/user_delete/result/:deleteId' do + cache_control :public, :must_revalidate, :max_age => 30 + id = session[:userId] + delete_id = params[:deleteId] + if (not UserAccount.checkAdmin(id)) + raise WebError.new(status: 405, message: "管理者アカウントでないと操作できません。") + end + begin + BookManager.deleteBookCollectOfUser(delete_id) + UserAccount.deleteUser(delete_id) + rescue UserAccount::NotFoundInstanceError + raise WebError.new(status: 404, message: "ユーザ情報が存在しません。") + rescue UserAccount::AuthenticationError + raise WebError.new(status: 405, message: "管理者でしか利用できません。") + end + redirect to('/user_list') + end + + # 蔵書の登録ページ + # @raise [WebError] セッションの期限切れ + # @raise [WebError] ユーザID不正 get '/book_regist' do cache_control :public, :must_revalidate, :max_age => 30 id = session[:userId] @@ -214,13 +350,17 @@ class WebGui < Sinatra::Base @username = user.full_name @book_info = Hash.new @update_f = book_update_f + @is_admin = UserAccount.checkAdmin(id); rescue UserAccount::NotFoundInstanceError raise WebError.new(status: 404, message: "ユーザ情報が存在しません。") end goPage :book_regist end - # 蔵書の編集 + # 蔵書の編集ページ + # @path_param [string] isbn 編集対象のISBN + # @raise [WebError] セッションの期限切れ + # @raise [WebError] ユーザID不正 get '/book_edit/:isbn' do cache_control :public, :must_revalidate, :max_age => 30 id = session[:userId] @@ -236,6 +376,7 @@ class WebGui < Sinatra::Base @username = user.full_name @book_info = BookManager.getBookCollect(isbn, id) @update_f = book_update_f + @is_admin = UserAccount.checkAdmin(id); rescue UserAccount::NotFoundInstanceError raise WebError.new(status: 404, message: "ユーザ情報が存在しません。") end @@ -348,6 +489,7 @@ class WebGui < Sinatra::Base @id = id @username = user.full_name @book_info = BookManager.searchISBN(isbn, id) + @is_admin = UserAccount.checkAdmin(id); rescue UserAccount::NotFoundInstanceError raise WebError.new(status: 404, message: "ユーザ情報が存在しません。") rescue BookManager::AlreadyInstanceError @@ -374,6 +516,7 @@ class WebGui < Sinatra::Base @id = id @username = user.full_name @book_info = params + @is_admin = UserAccount.checkAdmin(id); cover_image = getUploadData(params[:cover_file]) if (cover_image != nil) base64 = Base64.encode64(cover_image[:data]) @@ -385,6 +528,7 @@ class WebGui < Sinatra::Base goPage :book_regist end + # 書影の表示 get '/book_image/:hash' do cache_control :public, :must_revalidate, :max_age => 30 @@ -399,7 +543,10 @@ class WebGui < Sinatra::Base end - # 蔵書情報の取得 + # 蔵書情報の取得ページ + # @raise [WebError] セッションの期限切れ + # @raise [WebError] ユーザID不正 + # @raise [WebError] 蔵書情報がない get '/book_info/:isbn' do cache_control :public, :must_revalidate, :max_age => 30 id = session[:userId] @@ -415,6 +562,7 @@ class WebGui < Sinatra::Base @id = id @username = user.full_name @book_info = BookManager.getBookCollect(isbn, id) + @is_admin = UserAccount.checkAdmin(id); rescue UserAccount::NotFoundInstanceError raise WebError.new(status: 404, message: "ユーザ情報が存在しません。") rescue BookManager::NotFoundInstanceError @@ -423,7 +571,8 @@ class WebGui < Sinatra::Base goPage :book_info end - #蔵書一覧の取得(トリガページ) + # 蔵書一覧の取得(トリガページ) + # @raise [WebError] セッションの期限切れ get '/book_list' do id = session[:userId] if (id == nil) @@ -434,7 +583,8 @@ class WebGui < Sinatra::Base redirect to('/book_list/main') end - #蔵書一覧の取得(表示件数変更ページ) + # 蔵書一覧の取得(表示件数変更ページ) + # @raise [WebError] セッションの期限切れ post '/book_list/change_step' do id = session[:userId] if (id == nil) @@ -445,7 +595,8 @@ class WebGui < Sinatra::Base redirect to('/book_list/main') end - #蔵書一覧の取得(次ページ) + # 蔵書一覧の取得(次ページ) + # @raise [WebError] セッションの期限切れ post '/book_list/next' do id = session[:userId] if (id == nil) @@ -456,7 +607,8 @@ class WebGui < Sinatra::Base redirect to('/book_list/main') end - #蔵書一覧の取得(前ページ) + # 蔵書一覧の取得(前ページ) + # @raise [WebError] セッションの期限切れ post '/book_list/before' do id = session[:userId] if (id == nil) @@ -467,7 +619,9 @@ class WebGui < Sinatra::Base redirect to('/book_list/main') end - #蔵書一覧の取得(検索後) + + # 蔵書一覧の取得(検索後) + # @raise [WebError] セッションの期限切れ post '/book_list/find' do id = session[:userId] if (id == nil) @@ -486,7 +640,8 @@ class WebGui < Sinatra::Base redirect to('/book_list/main') end - #蔵書一覧の取得 (蔵書情報取得から) + # 蔵書一覧の取得 (蔵書情報取得から) + # @raise [WebError] セッションの期限切れ get '/book_list/fromInfo' do id = session[:userId] if (id == nil) @@ -499,7 +654,9 @@ class WebGui < Sinatra::Base end redirect to('/book_list/main') end - #蔵書一覧の取得(メインページ) + + # 蔵書一覧の取得(メインページ) + # @raise [WebError] セッションの期限切れ get '/book_list/main' do id = session[:userId] list_status = session[:list_status] @@ -510,6 +667,7 @@ class WebGui < Sinatra::Base user = UserAccount.getUser(id) @id = id @username = user.full_name + @is_admin = UserAccount.checkAdmin(id); rescue UserAccount::NotFoundInstanceError raise WebError.new(status: 404, message: "ユーザ情報が存在しません。") end @@ -526,6 +684,8 @@ class WebGui < Sinatra::Base end # 蔵書の削除 + # @path_param [string] isbn 削除対象のISBN + # @raise [WebError] セッションの期限切れ get '/book_delete/:isbn' do cache_control :public, :must_revalidate, :max_age => 30 id = session[:userId] @@ -538,6 +698,7 @@ class WebGui < Sinatra::Base @id = id @username = user.full_name @book_info = BookManager.getBookCollect(isbn, id) + @is_admin = UserAccount.checkAdmin(id); rescue UserAccount::NotFoundInstanceError raise WebError.new(status: 404, message: "ユーザ情報が存在しません。") rescue BookManager::NotFoundInstanceError @@ -546,7 +707,9 @@ class WebGui < Sinatra::Base goPage :book_delete end - # 蔵書の削除 + # 蔵書の削除 (削除実行) + # @path_param [string] isbn 削除対象のISBN + # @raise [WebError] セッションの期限切れ get '/book_delete/result/:isbn' do cache_control :public, :must_revalidate, :max_age => 30 id = session[:userId] diff --git a/sinatra/app/models/books_db.rb b/sinatra/app/models/books_db.rb index 6c5fd31..cb1afaf 100644 --- a/sinatra/app/models/books_db.rb +++ b/sinatra/app/models/books_db.rb @@ -713,4 +713,15 @@ class BookManager end end + # 蔵書情報の削除 + # @param [String] isbn_str 削除対象のISBN + # @param [Integer] user_id 削除対象のユーザID + def self.deleteBookCollectOfUser(user_id) + book_collects = BookCollection.where(user_id: user_id) + book_collects.each do |book_collect| + if (not book_collect.destroy) + raise DbAccessError + end + end + end end diff --git a/sinatra/app/models/users_db.rb b/sinatra/app/models/users_db.rb index 763a518..e700e2f 100644 --- a/sinatra/app/models/users_db.rb +++ b/sinatra/app/models/users_db.rb @@ -29,13 +29,6 @@ class User < ActiveRecord::Base column = columns_hash[key.to_s].name where("`#{table_name}`.`#{column}` REGEXP ?", pattern) end - - # 管理者権限か否か - # @return [Boolean] true: 管理者 - # @return [Boolean] false: 管理者ではない - def isAddmin - return user_role == ROLE_ADMIN - end end # ユーザ管理 @@ -57,17 +50,6 @@ class UserAccount class DbAccessError < StandardError end - # ユーザが管理者であるかをチェック - # @param [Integer] id チェック対象ユーザID - # @return [Boolean] true: 管理者 - # @return [Boolean] false: 管理者ではない - def self.checkAdmin(id) - user = User.find_by(user_id: id) - if (user == nil) - return false - end - return user.isAddmin() - end # SALT と Password Hash を生成する # @param [String] passwd パスワード @@ -79,8 +61,20 @@ class UserAccount return passwd_salt, passwd_hash end - private_class_method :checkAdmin, :makeHash + private_class_method :makeHash + # ユーザが管理者であるかをチェック + # @param [Integer] id チェック対象ユーザID + # @return [Boolean] true: 管理者 + # @return [Boolean] false: 管理者ではない + def self.checkAdmin(id) + user = User.find_by(user_id: id) + if (user == nil) + return false + end + return user.user_role == User::ROLE_ADMIN + end + # ユーザアカウントを作成 # @param [String] name ユーザ名 # @param [String] full_name フルネーム @@ -158,7 +152,7 @@ class UserAccount # @return [Array] 全ユーザ情報の一覧 # @raise [AuthenticationError] ユーザ権限不正 def self.getUserList(id) - if (checkAdmin(id)) + if (not checkAdmin(id)) raise AuthenticationError end return User.all @@ -196,7 +190,7 @@ class UserAccount # 更新内容の適用 if (change_f) user.update_at = DateTime.now - if (user.save) + if (not user.save) raise DbAccessError end end @@ -205,7 +199,7 @@ class UserAccount # ユーザ情報の削除 # @param [Integer] id 削除対象のユーザID def self.deleteUser(id) - user = User.find_by(id: id) + user = User.find_by(user_id: id) if (user == nil) raise NotFoundInstanceError end diff --git a/sinatra/app/views/book_regist.haml b/sinatra/app/views/book_regist.haml index 2dd92fd..194bc9d 100644 --- a/sinatra/app/views/book_regist.haml +++ b/sinatra/app/views/book_regist.haml @@ -1,5 +1,5 @@ - # encoding: utf-8 -- admin_f = @admin_f +- is_admin = @is_admin - id = @id - book_info = @book_info - update_f = @update_f diff --git a/sinatra/app/views/scss/book_info.scss b/sinatra/app/views/scss/book_info.scss new file mode 100644 index 0000000..5338e4b --- /dev/null +++ b/sinatra/app/views/scss/book_info.scss @@ -0,0 +1,19 @@ +@charset "utf-8"; +.book_info { + display: inline-block; + align-items: center; + text-align: center; + th { + width: 10em; + height: 2.5em; + text-align: right; + &:after { + content: ":"; + } + } + td { + width: 25em; + height: 2.5em; + text-align: left; + } +} diff --git a/sinatra/app/views/scss/book_list.scss b/sinatra/app/views/scss/book_list.scss new file mode 100644 index 0000000..931387a --- /dev/null +++ b/sinatra/app/views/scss/book_list.scss @@ -0,0 +1,43 @@ +.book_list{ + max-height: 32em; + margin: 5px; + padding: 2px; + width: 98%; + overflow: auto; + display: inline-block; + align-items: center; + table { + border-collapse: collapse; + } + .number { + width: 2.5em; + } + .title { + width: 20em; + } + .author { + width: 6em; + } + .publisher { + width: 8em; + } + th { + height: 1.5em; + background: #f4dda5; + border: 1px solid #f8e58c; + } + td { + height: 2.8em; + background: #fff1cf; + border: 1px solid #f8e58c; + &.number { + text-align: right + } + &.title, &.author, &.publisher { + text-align: left + } + } + tr:nth-child(odd) td { + background: #f4dda5; + } +} diff --git a/sinatra/app/views/scss/style.scss b/sinatra/app/views/scss/style.scss index e6c0232..98d418e 100644 --- a/sinatra/app/views/scss/style.scss +++ b/sinatra/app/views/scss/style.scss @@ -5,4 +5,6 @@ @import 'widget'; @import 'layout'; @import 'classes'; -@import 'list'; +@import 'book_list'; +@import 'book_info'; +@import 'user_list'; diff --git a/sinatra/app/views/scss/list.scss b/sinatra/app/views/scss/user_list.scss similarity index 86% rename from sinatra/app/views/scss/list.scss rename to sinatra/app/views/scss/user_list.scss index d699f52..62db612 100644 --- a/sinatra/app/views/scss/list.scss +++ b/sinatra/app/views/scss/user_list.scss @@ -1,5 +1,5 @@ @charset "utf-8"; -.book_list{ +.user_list{ max-height: 32em; margin: 5px; padding: 2px; @@ -10,16 +10,22 @@ table { border-collapse: collapse; } - .number { + .id { width: 2.5em; } - .title { - width: 20em; - } - .author { + .name { width: 6em; } - .publisher { + .full_name { + width: 10em; + } + .email { + width: 10em; + } + .role { + width: 5em; + } + .update_at { width: 8em; } th { diff --git a/sinatra/app/views/user_delete.haml b/sinatra/app/views/user_delete.haml new file mode 100644 index 0000000..075e8d9 --- /dev/null +++ b/sinatra/app/views/user_delete.haml @@ -0,0 +1,18 @@ +- # encoding: utf-8 +- id = @id +- username = @username +- delete_id = @delete_user[:user_id] +- delete_name = @delete_user[:user_name] + +%h2 + #{delete_name} のユーザ情報削除 + +.message + #{delete_name} さんのユーザ情報を削除します。 +.message + よろしいですか? + +.buttons + %hr + %input{ :type => 'button', :class=>'push_button', :onclick => "location.href='/user_delete/result/#{delete_id}'", :value => 'Ok'} + %input{ :type => 'button', :class=>'push_button', :onclick =>"location.href='/user_list'", :value => 'もどる' } diff --git a/sinatra/app/views/user_edit.haml b/sinatra/app/views/user_edit.haml index 20da5e1..c02c41e 100644 --- a/sinatra/app/views/user_edit.haml +++ b/sinatra/app/views/user_edit.haml @@ -1,28 +1,33 @@ - # encoding: utf-8 -- admin_f = @admin_f +- is_admin = @admin_type - id = @id - account = @account -- username = @username +- editname = @editname - email = @email - +- if (is_admin) + - post_url="/user_edit/#{id}"; return_url='/user_list' +- else + - post_url='/user_edit'; return_url='/user_home' + %h3 - #{username} さんのユーザデータを変更できます。 + #{editname} さんのユーザデータを変更できます。 .message - パスワードを変更する際には、現在のパスワードと - 新しいパスワードを入力してください。 + -if (not is_admin) + パスワードを変更する際には、現在のパスワードと + 新しいパスワードを入力してください。 %hr -%form{ :action => "/user_edit", :method => "post"} +%form{ :action => post_url, :method => "post"} .formstyle .params - - if (admin_f) + - if (is_admin) .item %label{ :for => 'user_id' } %span ユーザID: - %input{ :name => 'usr_id', :type => 'text', :class => 'input_text', :id => 'user_id', :value => account, :readonly => true} + %input{ :name => 'usr_id', :type => 'text', :class => 'input_text', :id => 'user_id', :value => id, :readonly => true} .item %label{ :for => 'name' } @@ -34,13 +39,14 @@ %label{ :for => 'full_name' } %span フルネーム: - %input{ :name => 'full_name', :type => 'text', :class => 'input_text', :id => 'full_name', :size => 30, :value => username, :maxlength => 127} - - .item - %label{ :for => 'old_passwd' } - %span - 現在のパスワード: - %input{ :name => 'try_pass', :type => 'password', :class => 'input_text', :id => 'old_passwd'} + %input{ :name => 'full_name', :type => 'text', :class => 'input_text', :id => 'full_name', :size => 30, :value => editname, :maxlength => 127} + + - if (not is_admin) + .item + %label{ :for => 'old_passwd' } + %span + 現在のパスワード: + %input{ :name => 'try_pass', :type => 'password', :class => 'input_text', :id => 'old_passwd'} .item %label{ :for => 'passwd' } @@ -63,4 +69,4 @@ .buttons %hr %input{ :type => 'submit', :class => 'push_button', :value => '送信'} - %input{ :type => 'button', :class => 'push_button', :onclick =>"location.href='/user_home'", :value => 'もどる' } + %input{ :type => 'button', :class => 'push_button', :onclick =>"location.href='#{return_url}'", :value => 'もどる' } diff --git a/sinatra/app/views/user_list.haml b/sinatra/app/views/user_list.haml new file mode 100644 index 0000000..624d37d --- /dev/null +++ b/sinatra/app/views/user_list.haml @@ -0,0 +1,51 @@ +- # encoding: utf-8 +- user_list = @user_list +%h3 + 現在登録されているユーザーの一覧です。 + +.user_list + %table + %tr + %th.id + ID + %th.name + ユーザネーム + %th.full_name + フルネーム + %th.email + Eメールアドレス + %th.role + 権限 + %th.update_at + 更新日時 + %th.controll + 操作 + - user_list.each do |user| + - user_id = user[:user_id]; user_name = user[:user_name] + - email = user[:email]; full_name = user[:full_name] + - update_at = user[:update_at].strftime('%D %T') + - delete_disabled = false + - case user[:user_role] + - when User::ROLE_ADMIN + - user_role = '管理者' + - delete_disabled = true + - when User::ROLE_NORMAL + - user_role = '一般利用者' + - when User::ROLE_FORGOT + - user_role = '要再発行' + %tr + %td.id + #{user_id} + %td.name + #{user_name} + %td.full_name + #{full_name} + %td.email + #{email} + %td.role + #{user_role} + %td.update_at + #{update_at} + %td.controll + %input{ :type => 'button', :class => 'side_button', :onclick =>"location.href='/user_edit/#{user_id}'", :value => '編集' } + %input{ :type => 'button', :class => 'side_button', :onclick =>"location.href='/user_delete/#{user_id}'", :value => '削除', :disabled => delete_disabled }