diff --git a/app/components/app_tab_panel.rb b/app/components/app_tab_panel.rb index 88b5581..b50d775 100644 --- a/app/components/app_tab_panel.rb +++ b/app/components/app_tab_panel.rb @@ -11,6 +11,11 @@ class AppTabPanel < Netzke::Basepack::TabPanel c.text = "CHECK OUT" if controller.current_user end + action :change_account_info do |c| + c.icon = :user_edit + c.text = "Change Email/Password" + end + def configure(c) #all users @@ -57,7 +62,7 @@ class AppTabPanel < Netzke::Basepack::TabPanel end end c.prevent_header = true - c.tbar = [:sign_out, :check_out] + c.tbar = [:sign_out, :check_out, :change_account_info] c.items = @@app_tab_panel_items super end diff --git a/app/components/app_tab_panel/javascripts/sign_out.js b/app/components/app_tab_panel/javascripts/sign_out.js index 8672024..870f79e 100644 --- a/app/components/app_tab_panel/javascripts/sign_out.js +++ b/app/components/app_tab_panel/javascripts/sign_out.js @@ -17,5 +17,8 @@ }); } }); + }, + onChangeAccountInfo: function(){ + window.location.href="users/edit"; } } diff --git a/app/components/users.rb b/app/components/users.rb index e45962d..4a32613 100644 --- a/app/components/users.rb +++ b/app/components/users.rb @@ -1,4 +1,13 @@ class Users < Netzke::Basepack::Grid + include Netzke::Basepack::ActionColumn + + column :reset do |c| + c.type = :action + c.actions = [{name: :reset_password, icon: :lock_break}] + c.header = "" + c.width = 20 + end + def configure(c) super c.header = false @@ -12,6 +21,8 @@ class Users < Netzke::Basepack::Grid :email, :bike__shop_id ] + + c.columns << :reset if can? :manage, User end #override with nil to remove actions diff --git a/app/components/users/javascripts/init_component.js b/app/components/users/javascripts/init_component.js index d330667..de240a6 100644 --- a/app/components/users/javascripts/init_component.js +++ b/app/components/users/javascripts/init_component.js @@ -4,8 +4,32 @@ this.callParent(); this.getView().on('itemclick', function(view, record){ // The beauty of using Ext.Direct: calling 3 endpoints in a row, which results in a single call to the server! - console.log("user: " + record.get('id') ); this.selectCustomer({customer_id: record.get('id'), customer_type: 'User'}); }, this); + }, + onResetPassword: function(record){ + user = record.data; + Ext.Msg.confirm( + "Reset Password", + "Are you sure you want to reset "+user.first_name+" "+user.last_name+"'s password?", + function(butt_id){ + if( butt_id === "yes" ){ + $.ajax({ + type: 'POST', + url: '/api/v1/reset', + dataType: 'json', + contentType: 'application/json', + processData: false, + data: JSON.stringify({"user_id": user.id}), + complete: function() { }, + success: function(data) { + Ext.Msg.alert("Success", "New Password: "+data.password); + }, + error: function(data,textStatus) { + Ext.Msg.alert( "Error", JSON.parse(data.responseText)["error"]); + } + }); + } + }); } } diff --git a/app/components/users_and_profiles_border.rb b/app/components/users_and_profiles_border.rb index e91cb5a..afb31b4 100644 --- a/app/components/users_and_profiles_border.rb +++ b/app/components/users_and_profiles_border.rb @@ -9,7 +9,7 @@ class UsersAndProfilesBorder < Netzke::Base super c.header = false c.items = [ - { netzke_component: :users, header: "Users", region: :center, width: 300, split: true }, + { netzke_component: :users, header: "Users", region: :center, width: 350, split: true }, { netzke_component: :user_profiles, region: :south, height: 150, split: true}, { netzke_component: :user_logs, region: :east, split: true} ] @@ -25,5 +25,5 @@ class UsersAndProfilesBorder < Netzke::Base # store selected boss id in the session for this component's instance session[:selected_user_id] = params[:user_id] end - + end diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb new file mode 100644 index 0000000..35176bd --- /dev/null +++ b/app/controllers/api/v1/users_controller.rb @@ -0,0 +1,28 @@ +require 'securerandom' +class Api::V1::UsersController < Api::V1::BaseController + + def password_reset + if can? :manage, User + user = User.find_by_id(params[:user_id]) + render :json => { "error" => "User not found"}, :status => 404 and return if user.nil? + render :json => { "error" => "Not allowed to reset your own password in this fashion."}, :status => 403 and return if user.id == current_user.id + + new_pass = SecureRandom.hex[0,8] + user.password = new_pass + user.save + render :json => { "password" => new_pass}, :status => 200 and return + else + render :json => { "error" => "You do not have the permission"}, :status => 403 and return + end + end + + def checkout + #must use @current_user since user may not have signed in + if !@current_user.checked_in? + render :json => { "error" => "You were not even checked in."}, :status => 404 and return + else + @current_user.checkout + render :nothing => true, :status => 204 and return + end + end +end diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index bb66fbf..e2e50f8 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -1,3 +1,5 @@ +<%= stylesheet_link_tag "bootstrap_and_overrides", :media => "all" %> +

Edit <%= resource_name.to_s.humanize %>

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %> diff --git a/config/routes.rb b/config/routes.rb index 59ff145..1e005fb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,6 +10,7 @@ Velocipede::Application.routes.draw do scope 'v1', :module => :v1 do post 'checkin' => "logs#checkin", :as => "api_checkin" post 'checkout' => "logs#checkout", :as => "api_checkout" + post 'reset' => "users#password_reset", :as => "api_password_reset" end end