concen 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/app/controllers/concen/application_controller.rb +25 -0
  2. data/app/controllers/concen/grid_files_controller.rb +75 -0
  3. data/app/controllers/concen/pages_controller.rb +95 -0
  4. data/app/controllers/concen/performances_controller.rb +35 -0
  5. data/app/controllers/concen/sessions_controller.rb +30 -0
  6. data/app/controllers/concen/statuses_controller.rb +63 -0
  7. data/app/controllers/concen/traffics_controller.rb +43 -0
  8. data/app/controllers/concen/users_controller.rb +118 -0
  9. data/app/controllers/concen/visits_controller.rb +38 -0
  10. data/app/helpers/concen/application_helper.rb +10 -0
  11. data/app/helpers/concen/pages_helper.rb +5 -0
  12. data/app/helpers/concen/visits_helper.rb +4 -0
  13. data/app/models/concen/grid_file.rb +67 -0
  14. data/app/models/concen/page.rb +342 -0
  15. data/app/models/concen/response.rb +45 -0
  16. data/app/models/concen/user.rb +88 -0
  17. data/app/models/concen/visit/page.rb +100 -0
  18. data/app/models/concen/visit/referral.rb +45 -0
  19. data/app/stylesheets/application.sass +445 -0
  20. data/app/stylesheets/config.rb +9 -0
  21. data/app/stylesheets/ie.sass +4 -0
  22. data/app/stylesheets/non_ios.sass +16 -0
  23. data/app/stylesheets/partials/_base.sass +92 -0
  24. data/app/stylesheets/partials/_fileuploader.sass +75 -0
  25. data/app/stylesheets/partials/_flot.sass +8 -0
  26. data/app/stylesheets/partials/_form.sass +74 -0
  27. data/app/stylesheets/partials/_mixins.sass +8 -0
  28. data/app/stylesheets/partials/_variables.sass +17 -0
  29. data/app/stylesheets/print.sass +4 -0
  30. data/app/views/concen/grid_files/_form.html.haml +15 -0
  31. data/app/views/concen/grid_files/edit.html.haml +9 -0
  32. data/app/views/concen/pages/_file_list.haml +7 -0
  33. data/app/views/concen/pages/_files.haml +24 -0
  34. data/app/views/concen/pages/_form.html.haml +18 -0
  35. data/app/views/concen/pages/_nested_list.html.haml +15 -0
  36. data/app/views/concen/pages/edit.html.haml +15 -0
  37. data/app/views/concen/pages/index.html.haml +9 -0
  38. data/app/views/concen/pages/new.html.haml +9 -0
  39. data/app/views/concen/performances/_runtimes.html.haml +5 -0
  40. data/app/views/concen/performances/show.html.haml +30 -0
  41. data/app/views/concen/sessions/new.html.haml +12 -0
  42. data/app/views/concen/statuses/_server.html.haml +19 -0
  43. data/app/views/concen/statuses/show.html.haml +18 -0
  44. data/app/views/concen/traffics/_pages.html.haml +5 -0
  45. data/app/views/concen/traffics/_referrals.html.haml +9 -0
  46. data/app/views/concen/traffics/show.html.haml +30 -0
  47. data/app/views/concen/users/_form.html.haml +29 -0
  48. data/app/views/concen/users/_password_reset.html.haml +0 -0
  49. data/app/views/concen/users/_settings.html.haml +15 -0
  50. data/app/views/concen/users/edit.html.haml +9 -0
  51. data/app/views/concen/users/index.html.haml +32 -0
  52. data/app/views/concen/users/new.html.haml +4 -0
  53. data/app/views/concen/users/new_invite.html.haml +15 -0
  54. data/app/views/concen/users/new_reset_password.html.haml +15 -0
  55. data/app/views/concen/visits/visit_recorder_js.erb +13 -0
  56. data/app/views/layouts/concen/_additional_header_links.haml +0 -0
  57. data/app/views/layouts/concen/_header.html.haml +18 -0
  58. data/app/views/layouts/concen/_iphone.html.haml +6 -0
  59. data/app/views/layouts/concen/application.html.haml +48 -0
  60. data/app/views/layouts/concen/maintenance.html.haml +0 -0
  61. data/config/routes.rb +64 -0
  62. data/lib/concen.rb +11 -0
  63. data/lib/concen/engine.rb +14 -0
  64. data/lib/concen/railties/page.rake +12 -0
  65. data/lib/concen/railties/setup.rake +23 -0
  66. data/lib/concen/version.rb +3 -0
  67. metadata +246 -0
@@ -0,0 +1,25 @@
1
+ module Concen
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery
4
+
5
+ layout "concen/application"
6
+
7
+ before_filter :set_concen
8
+
9
+ helper_method :current_concen_user, :authenticate_concen_user
10
+
11
+ protected
12
+
13
+ def set_concen
14
+ @concen = true
15
+ end
16
+
17
+ def current_concen_user
18
+ @current_concen_user ||= User.where(:auth_token => cookies[:auth_token]).first if cookies[:auth_token]
19
+ end
20
+
21
+ def authenticate_concen_user
22
+ redirect_to concen_signin_path unless current_concen_user
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,75 @@
1
+ module Concen
2
+ class GridFilesController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ def new
6
+ @page = Page.find(params[:page_id])
7
+ @grid_file = @page.grid_files.build
8
+ end
9
+
10
+ def create
11
+ @page = Page.find(params[:page_id])
12
+ @grid_file = @page.grid_files.build
13
+ filename = params[:filename]
14
+ if ["css", "js"].include?(params[:file_type])
15
+ unless MIME::Types.type_for(filename).first.to_s.include?(params[:file_type])
16
+ filename << "." + params[:file_type]
17
+ end
18
+ end
19
+ if @grid_file.store("", filename)
20
+ content = render_to_string(:partial => "concen/pages/files")
21
+ render :json => {:success => true, :content => content}
22
+ else
23
+ render :json => {:success => false}
24
+ end
25
+ end
26
+
27
+ def edit
28
+ @page = Page.find(params[:page_id])
29
+ @grid_file = @page.grid_files.find(params[:id])
30
+ end
31
+
32
+ def update
33
+ @page = Page.find(params[:page_id])
34
+ @grid_file = @page.grid_files.find(params[:id])
35
+ if @grid_file.store(params[:concen_grid_file_page], @grid_file.original_filename)
36
+ redirect_to edit_concen_page_grid_file_path(@page, @grid_file)
37
+ else
38
+ render :edit
39
+ end
40
+ end
41
+
42
+ def destroy
43
+ @page = Page.find(params[:page_id])
44
+ @grid_file = @page.grid_files.find(params[:id])
45
+ respond_to do |format|
46
+ if @grid_file.destroy
47
+ format.html { redirect_to edit_concen_page_path(@page) }
48
+ format.json { render :json => {:success => true} }
49
+ else
50
+ format.html { redirect_to edit_concen_page_path(@page) }
51
+ format.json { render :json => {:success => false} }
52
+ end
53
+ end
54
+ end
55
+
56
+ def upload
57
+ # logger.info { "----#{env['rack.input']}" }
58
+ # logger.info { "----#{env['HTTP_X_FILE_NAME']}" }
59
+ # logger.info { "----#{env['CONTENT_TYPE']}" }
60
+ @page = Page.find(params[:page_id])
61
+ @grid_file = @page.grid_files.build
62
+ if env["rack.input"]
63
+ file = env["rack.input"]
64
+ filename = CGI::unescape(env["HTTP_X_FILE_NAME"])
65
+ else
66
+ file = params[:qqfile].read
67
+ filename = params[:qqfile].original_filename
68
+ end
69
+ if @grid_file.store(file, filename)
70
+ content = render_to_string(:partial => "concen/pages/files")
71
+ render :json => {:success => true, :content => content}
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,95 @@
1
+ module Concen
2
+ class PagesController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ before_filter :authenticate_concen_user
6
+
7
+ def index
8
+ @page_title = "Pages"
9
+ @page = Page.where(:level => 0).first
10
+ end
11
+
12
+ def new
13
+ if params[:parent_id]
14
+ @page = Page.find(params[:parent_id]).children.build
15
+ else
16
+ @page = Page.new
17
+ end
18
+ @page.level = params[:level].to_i if params[:level]
19
+ end
20
+
21
+ def create
22
+ @page = Page.new(params[:concen_page])
23
+ @page.authors = [current_concen_user.username]
24
+ if @page.save
25
+ redirect_to(edit_concen_page_path(@page), :notice => "Page was successfully created.")
26
+ else
27
+ render :new
28
+ end
29
+ end
30
+
31
+ def edit
32
+ @page = Page.find(params[:id])
33
+ unless current_concen_user.full_control || @page.authors_as_user.include?(current_concen_user)
34
+ flash[:notice] = "Only author can edit page."
35
+ redirect_to concen_pages_path
36
+ end
37
+ end
38
+
39
+ def update
40
+ @page = Page.find(params[:id])
41
+ if current_concen_user.full_control || @page.authors_as_user.include?(current_concen_user)
42
+ if @page.update_attributes(params[:concen_page])
43
+ redirect_to(edit_concen_page_path(@page), :notice => "Page was successfully created.")
44
+ else
45
+ render :edit
46
+ end
47
+ else
48
+ render :edit, :notice => "Only author can modify page content."
49
+ end
50
+ end
51
+
52
+ def destroy
53
+ if current_concen_user.full_control || @page.authors_as_user.include?(current_concen_user)
54
+ @page = Page.find(params[:id])
55
+ @page.destroy
56
+ redirect_to concen_pages_path
57
+ else
58
+ flash[:notice] = "Only author can delete page."
59
+ redirect_to concen_pages_path
60
+ end
61
+ end
62
+
63
+ def sort
64
+ if params[:page]
65
+ if current_concen_user.full_control
66
+ child_count = {}
67
+ params[:page].each do |key, value|
68
+ if value == "root"
69
+ root = Page.find(key)
70
+ root.parent_id = nil
71
+ root.level = 0
72
+ root.save
73
+ else
74
+ child = Page.find(key)
75
+ parent = Page.find(value)
76
+ child.parent_id = parent.id
77
+ child.level = parent.level + 1
78
+ if child_count[value]
79
+ child.position = child_count[value] + 1
80
+ child_count[value] += 1
81
+ else
82
+ child.position = 1
83
+ child_count[value] = 1
84
+ end
85
+ child.save
86
+ end
87
+ end
88
+ render :json => {:success => true}
89
+ else
90
+ render :json => {:success => false, :message => "Only user with full control can sort pages."}
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,35 @@
1
+ module Concen
2
+ class PerformancesController < ApplicationController
3
+ def show
4
+ @page_title = "Performance"
5
+ end
6
+
7
+ def responses
8
+ @stats = {}
9
+ @stats[:total_runtime] = Response.where(:created_at.gte => Time.now - 1.hour).asc(:created_at).map do |response|
10
+ [(response.created_at.utc.to_f + response.created_at.utc_offset)*1000, response.total_runtime]
11
+ end
12
+ @stats[:view_runtime] = Response.where(:created_at.gte => Time.now - 1.hour).asc(:created_at).map do |response|
13
+ if response.respond_to?("view_runtime")
14
+ [(response.created_at.utc.to_f + response.created_at.utc_offset)*1000, response.view_runtime]
15
+ end
16
+ end
17
+ @stats[:mongo_runtime] = Response.where(:created_at.gte => Time.now - 1.hour).asc(:created_at).map do |response|
18
+ if response.respond_to?("mongo_runtime")
19
+ [(response.created_at.utc.to_f + response.created_at.utc_offset)*1000, response.mongo_runtime]
20
+ end
21
+ end
22
+
23
+ respond_to do |format|
24
+ format.json { render :json => @stats }
25
+ end
26
+ end
27
+
28
+ def runtimes
29
+ @runtimes_stats = Response.aggregate_average_runtime(:type => params[:type])
30
+ respond_to do |format|
31
+ format.html { render :partial => "concen/performances/runtimes" }
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,30 @@
1
+ module Concen
2
+ class SessionsController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ def new
6
+ if User.all.any?
7
+ render
8
+ else
9
+ redirect_to new_concen_user_path
10
+ end
11
+ end
12
+
13
+ def create
14
+ user = User.where(:username => /#{params[:username]}/i).first
15
+
16
+ if user && user.authenticate(params[:password])
17
+ cookies.permanent[:auth_token] = user.auth_token
18
+ redirect_to root_path, :notice => "You have successfully signed in!"
19
+ else
20
+ flash.now.alert = "Invalid email or password"
21
+ render "new"
22
+ end
23
+ end
24
+
25
+ def destroy
26
+ cookies.delete(:auth_token)
27
+ redirect_to root_path, :notice => "You have successfully signed out!"
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,63 @@
1
+ module Concen
2
+ class StatusesController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ before_filter :authenticate_concen_user
6
+
7
+ def show
8
+ @page_title = "Status"
9
+ render
10
+ end
11
+
12
+ def counts
13
+ respond_to do |format|
14
+ format.json {
15
+ render :json => {:pages => Page.count, :users => User.count}
16
+ }
17
+ end
18
+ end
19
+
20
+ def server
21
+ processor_stat = []
22
+ memory_stat = []
23
+ @server_stats = {}
24
+ if RUBY_PLATFORM.downcase.include?("darwin")
25
+ top = `top -l 1 -pid 0`.split(/\n+/)
26
+ if top.present?
27
+ processor_stat = top[3].scan(/[0-9]+\.\d+/)
28
+ memory_stat = top[6].scan(/[0-9]\d+/)
29
+ @server_stats = {
30
+ :processor => {:user => processor_stat[0], :sys => processor_stat[1], :idle => processor_stat[2]},
31
+ :memory => {:wired => memory_stat[0], :active => memory_stat[1], :inactive => memory_stat[2], :used => memory_stat[3], :free => memory_stat[4]}
32
+ }
33
+ end
34
+ elsif RUBY_PLATFORM.downcase.include?("linux")
35
+ top = `top -b -n 1 -p 0`.split(/\n+/)
36
+ if top.present?
37
+ processor_stat = top[2].scan(/[0-9]+\.\d+/)
38
+ memory_stat = top[3].scan(/[0-9]\d+/)
39
+ @server_stats = {
40
+ :processor => {:user => processor_stat[0], :sys => processor_stat[1], :idle => processor_stat[3]},
41
+ :memory => {:total => memory_stat[0].to_i/1024, :used => memory_stat[1].to_i/1024, :free => memory_stat[2].to_i/1024}
42
+ }
43
+ end
44
+ end
45
+ uptime_array = `uptime`.split("up")[1].strip.split("user")[0].split(","); uptime_array.delete_at(uptime_array.length - 1)
46
+ if uptime_array.present?
47
+ uptime = uptime_array.join(",")
48
+ @server_stats[:uptime] = uptime
49
+ end
50
+
51
+ @mongodb_stats = Mongoid.database.stats
52
+
53
+ begin
54
+ @mongodb_grid_fs_stats = Mongoid.database.collection("fs.chunks").stats["storageSize"]
55
+ rescue
56
+ @mongodb_grid_fs_stats = 0
57
+ end
58
+ respond_to do |format|
59
+ format.html { render :partial => "concen/statuses/server" }
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,43 @@
1
+ module Concen
2
+ class TrafficsController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ before_filter :authenticate_concen_user
6
+
7
+ # Supports OS X and Linux, require top command.
8
+ # @current_month_visits = Statistic.visits_for_current :month
9
+ # Real time visits
10
+ # Historical statistics
11
+ # Month: visits
12
+ def show
13
+ @page_title = "Traffic"
14
+ end
15
+
16
+ def visits_counts
17
+ if @stats = Visit::Page.aggregate_count_by_time(:hour => params[:hour], :precision => "millisecond")
18
+ # Readjust timestamp because flot graph doesn't handle time zone.
19
+ @stats.map! do |s|
20
+ time = Time.zone.at s[0]/1000
21
+ [(time.utc.to_i + time.utc_offset)*1000, s[1]]
22
+ end
23
+ end
24
+ respond_to do |format|
25
+ format.json { render :json => @stats }
26
+ end
27
+ end
28
+
29
+ def pages
30
+ @pages_stats = Visit::Page.aggregate_count_by_url(:limit => 6)
31
+ respond_to do |format|
32
+ format.html { render :partial => "concen/traffics/pages" }
33
+ end
34
+ end
35
+
36
+ def referrals
37
+ @referrals_stats = Visit::Referral.aggregate_count_by_domain(:limit => 6)
38
+ respond_to do |format|
39
+ format.html { render :partial => "concen/traffics/referrals" }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,118 @@
1
+ module Concen
2
+ class UsersController < ApplicationController
3
+ layout "concen/application"
4
+
5
+ before_filter :authenticate_concen_user, :except => [:new, :edit, :update, :create, :new_reset_password, :reset_password]
6
+
7
+ def index
8
+ @page_title = "Users"
9
+ @users = User.all
10
+ end
11
+
12
+ def new
13
+ if User.all.any?
14
+ redirect_to root_path
15
+ else
16
+ @user = User.new
17
+ end
18
+ end
19
+
20
+ def create
21
+ if !User.all.any? || (current_concen_user && current_concen_user.full_control)
22
+ @user = User.new(params[:concen_user])
23
+ @user.full_control = true
24
+ if @user.save
25
+ redirect_to(concen_users_path, :notice => "User was successfully created.")
26
+ else
27
+ render :new
28
+ end
29
+ end
30
+ end
31
+
32
+ def edit
33
+ if params[:password_reset_token]
34
+ @user = User.where(:password_reset_token => params[:password_reset_token]).first
35
+ elsif params[:invitation_token]
36
+ @user = User.where(:invitation_token => params[:invitation_token]).first
37
+ else
38
+ @page_title = "Settings"
39
+ @user = current_concen_user
40
+ end
41
+ redirect_to concen_signin_path unless @user
42
+ end
43
+
44
+ def update
45
+ if params[:concen_user][:password_reset_token]
46
+ @user = User.where(:password_reset_token => params[:concen_user][:password_reset_token]).first
47
+ authenticated = true if @user.password_reset_sent_at > 2.hours.ago
48
+ elsif params[:concen_user][:invitation_token]
49
+ @user = User.where(:invitation_token => params[:concen_user][:invitation_token]).first
50
+ authenticated = true if @user.invitation_sent_at > 24.hours.ago
51
+ else
52
+ @user = current_concen_user
53
+ authenticated = true if @user.authenticate(params[:concen_user].delete(:current_password))
54
+ end
55
+ if @user && authenticated
56
+ if @user.update_attributes(params[:concen_user])
57
+ redirect_to edit_concen_user_path @user
58
+ else
59
+ render :edit
60
+ end
61
+ else
62
+ flash.now.alert = "Invalid password."
63
+ render :edit
64
+ end
65
+ end
66
+
67
+ def destroy
68
+ if current_concen_user.full_control
69
+ @user = User.find(params[:id])
70
+ @user.destroy
71
+ redirect_to concen_users_path
72
+ else
73
+ flash[:notice] = "Only user with full control can delete a user."
74
+ redirect_to concen_users_path
75
+ end
76
+ end
77
+
78
+ def toggle_attribute
79
+ respond_to do |format|
80
+ if current_concen_user.full_control
81
+ @user = User.find(params[:id])
82
+ @user.write_attribute(params[:attribute].to_sym, !@user.read_attribute(params[:attribute].to_sym))
83
+ @user.save
84
+ format.json { render :json => {:success => true} }
85
+ else
86
+ format.json { render :json => {:success => false, :message => "Only user with full control can toggle attribute."} }
87
+ end
88
+ end
89
+ end
90
+
91
+ def new_invite
92
+ if current_concen_user.full_control
93
+ @user = User.new
94
+ else
95
+ redirect_to(concen_users_path, :notice => "Only user with full control can invite.")
96
+ end
97
+ end
98
+
99
+ def invite
100
+ if current_concen_user.full_control
101
+ @user = User.send_invitation params[:concen_user][:email]
102
+ redirect_to concen_users_path, :notice => "Invitation has been sent."
103
+ else
104
+ redirect_to concen_users_path, :notice => "Only user with full control can invite."
105
+ end
106
+ end
107
+
108
+ def new_reset_password
109
+ @user = User.new
110
+ end
111
+
112
+ def reset_password
113
+ @user = User.where(:email => params[:concen_user][:email]).first
114
+ @user.send_password_reset
115
+ redirect_to concen_signin_path, :notice => "Password reset instruction has been sent."
116
+ end
117
+ end
118
+ end