railswiki 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +185 -0
  4. data/Rakefile +24 -0
  5. data/app/assets/config/railswiki_manifest.js +2 -0
  6. data/app/assets/javascripts/railswiki/application.js +13 -0
  7. data/app/assets/javascripts/railswiki/histories.js +2 -0
  8. data/app/assets/javascripts/railswiki/invites.js +2 -0
  9. data/app/assets/javascripts/railswiki/pages.js +2 -0
  10. data/app/assets/javascripts/railswiki/sessions.js +2 -0
  11. data/app/assets/javascripts/railswiki/uploaded_files.js +2 -0
  12. data/app/assets/javascripts/railswiki/users.js +2 -0
  13. data/app/assets/stylesheets/railswiki/application.css +15 -0
  14. data/app/assets/stylesheets/railswiki/histories.css +4 -0
  15. data/app/assets/stylesheets/railswiki/invites.css +4 -0
  16. data/app/assets/stylesheets/railswiki/pages.scss +55 -0
  17. data/app/assets/stylesheets/railswiki/sessions.css +4 -0
  18. data/app/assets/stylesheets/railswiki/uploaded_files.scss +54 -0
  19. data/app/assets/stylesheets/railswiki/users.css +4 -0
  20. data/app/controllers/railswiki/application_controller.rb +126 -0
  21. data/app/controllers/railswiki/histories_controller.rb +48 -0
  22. data/app/controllers/railswiki/invites_controller.rb +61 -0
  23. data/app/controllers/railswiki/pages_controller.rb +141 -0
  24. data/app/controllers/railswiki/sessions_controller.rb +75 -0
  25. data/app/controllers/railswiki/uploaded_files_controller.rb +100 -0
  26. data/app/controllers/railswiki/users_controller.rb +55 -0
  27. data/app/helpers/railswiki/application_helper.rb +26 -0
  28. data/app/helpers/railswiki/histories_helper.rb +4 -0
  29. data/app/helpers/railswiki/invites_helper.rb +4 -0
  30. data/app/helpers/railswiki/pages_helper.rb +76 -0
  31. data/app/helpers/railswiki/sessions_helper.rb +4 -0
  32. data/app/helpers/railswiki/title_helper.rb +7 -0
  33. data/app/helpers/railswiki/uploaded_files_helper.rb +4 -0
  34. data/app/helpers/railswiki/users_helper.rb +4 -0
  35. data/app/helpers/railswiki/wiki_helper.rb +189 -0
  36. data/app/jobs/railswiki/application_job.rb +4 -0
  37. data/app/mailers/railswiki/application_mailer.rb +6 -0
  38. data/app/models/railswiki/application_record.rb +5 -0
  39. data/app/models/railswiki/history.rb +14 -0
  40. data/app/models/railswiki/invite.rb +20 -0
  41. data/app/models/railswiki/page.rb +56 -0
  42. data/app/models/railswiki/uploaded_file.rb +32 -0
  43. data/app/models/railswiki/user.rb +27 -0
  44. data/app/uploaders/railswiki/file_uploader.rb +56 -0
  45. data/app/views/layouts/railswiki/application.html.erb +25 -0
  46. data/app/views/railswiki/histories/index.html.erb +33 -0
  47. data/app/views/railswiki/histories/show.html.erb +17 -0
  48. data/app/views/railswiki/invites/_form.html.erb +38 -0
  49. data/app/views/railswiki/invites/index.html.erb +39 -0
  50. data/app/views/railswiki/invites/new.html.erb +7 -0
  51. data/app/views/railswiki/invites/show.html.erb +34 -0
  52. data/app/views/railswiki/pages/_form.html.erb +144 -0
  53. data/app/views/railswiki/pages/edit.html.erb +8 -0
  54. data/app/views/railswiki/pages/history.html.erb +11 -0
  55. data/app/views/railswiki/pages/index.html.erb +72 -0
  56. data/app/views/railswiki/pages/new.html.erb +7 -0
  57. data/app/views/railswiki/pages/show.html.erb +36 -0
  58. data/app/views/railswiki/sessions/no_invite.erb +7 -0
  59. data/app/views/railswiki/sessions/not_authorized.html.erb +12 -0
  60. data/app/views/railswiki/uploaded_files/_form.html.erb +31 -0
  61. data/app/views/railswiki/uploaded_files/_inline.html.erb +5 -0
  62. data/app/views/railswiki/uploaded_files/edit.html.erb +8 -0
  63. data/app/views/railswiki/uploaded_files/file_dialog.html.erb +11 -0
  64. data/app/views/railswiki/uploaded_files/image_dialog.html.erb +11 -0
  65. data/app/views/railswiki/uploaded_files/index.html.erb +36 -0
  66. data/app/views/railswiki/uploaded_files/new.html.erb +7 -0
  67. data/app/views/railswiki/uploaded_files/show.html.erb +29 -0
  68. data/app/views/railswiki/users/_form.html.erb +29 -0
  69. data/app/views/railswiki/users/edit.html.erb +8 -0
  70. data/app/views/railswiki/users/index.html.erb +37 -0
  71. data/app/views/railswiki/users/show.html.erb +59 -0
  72. data/app/views/shared/_formatting.md.erb +29 -0
  73. data/app/views/shared/_histories.html.erb +21 -0
  74. data/app/views/shared/_layout.html.erb +17 -0
  75. data/app/views/shared/_menu.html.erb +15 -0
  76. data/app/views/shared/_meta.html.erb +1 -0
  77. data/app/views/shared/_notices.html.erb +3 -0
  78. data/app/views/shared/_roles.html.erb +12 -0
  79. data/app/views/shared/_search.md.erb +5 -0
  80. data/config/initializers/carrierwave.rb +6 -0
  81. data/config/initializers/omniauth.rb +16 -0
  82. data/config/initializers/session_store.rb +1 -0
  83. data/config/routes.rb +25 -0
  84. data/db/migrate/20170420000841_create_railswiki_pages.rb +10 -0
  85. data/db/migrate/20170420010111_add_sessions_table.rb +12 -0
  86. data/db/migrate/20170420010147_create_railswiki_users.rb +14 -0
  87. data/db/migrate/20170420021039_add_lowercase_title_to_page.rb +5 -0
  88. data/db/migrate/20170420021840_create_railswiki_histories.rb +11 -0
  89. data/db/migrate/20170420235420_add_email_and_image_to_user.rb +8 -0
  90. data/db/migrate/20170421000333_add_last_login_to_user.rb +5 -0
  91. data/db/migrate/20170421010945_add_role_to_user.rb +7 -0
  92. data/db/migrate/20170421020932_create_railswiki_uploaded_files.rb +10 -0
  93. data/db/migrate/20170421030140_add_title_to_uploaded_file.rb +5 -0
  94. data/db/migrate/20170517224700_create_railswiki_invites.rb +12 -0
  95. data/db/migrate/20170517234452_add_role_to_invite.rb +5 -0
  96. data/db/migrate/20170622033540_set_all_mysql_tables_to_utf8.rb +54 -0
  97. data/lib/railswiki.rb +5 -0
  98. data/lib/railswiki/engine.rb +14 -0
  99. data/lib/railswiki/version.rb +3 -0
  100. data/lib/tasks/railswiki_tasks.rake +4 -0
  101. metadata +255 -0
@@ -0,0 +1,48 @@
1
+ require_dependency "railswiki/application_controller"
2
+
3
+ module Railswiki
4
+ class HistoriesController < ApplicationController
5
+ before_action :set_history, only: [:show, :destroy]
6
+
7
+ before_action :require_histories_list_permission, only: [:index]
8
+ before_action :require_history_delete_permission, only: [:destroy]
9
+
10
+ # GET /histories
11
+ def index
12
+ @histories = History.all
13
+ end
14
+
15
+ # GET /histories/1
16
+ def show
17
+ respond_to do |format|
18
+ format.html
19
+ format.json { render json: @history.expose_json }
20
+ end
21
+ end
22
+
23
+ # DELETE /histories/1
24
+ def destroy
25
+ @history.transaction do
26
+ @history.destroy!
27
+ @history.page.reload
28
+
29
+ latest_version = @history.page.histories.order(created_at: :desc).first
30
+ if latest_version.present?
31
+ @history.page.update_attributes!(latest_version_id: latest_version.id)
32
+ else
33
+ # We can't have a page with no history
34
+ @history.page.destroy!
35
+ end
36
+
37
+ redirect_to @history.page, notice: 'History was successfully destroyed.'
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ # Use callbacks to share common setup or constraints between actions.
44
+ def set_history
45
+ @history = History.find(params[:id])
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,61 @@
1
+ require_dependency "railswiki/application_controller"
2
+
3
+ module Railswiki
4
+ class InvitesController < ApplicationController
5
+ include ApplicationHelper
6
+
7
+ before_action :set_invite, only: [:show, :destroy]
8
+ before_action :require_invites_list_permission, only: [:index]
9
+ before_action :require_invite_create_permission, only: [:new, :create]
10
+ before_action :require_invite_delete_permission, only: [:destroy]
11
+
12
+ # GET /invites
13
+ def index
14
+ @invites = Invite.all
15
+ end
16
+
17
+ # GET /invites/1
18
+ def show
19
+ respond_to do |format|
20
+ format.html
21
+ end
22
+ end
23
+
24
+ # GET /invites/new
25
+ def new
26
+ @invite = Invite.new
27
+ @invite.inviting_user = current_user
28
+ @invite.role = User::ROLE_EDITOR
29
+ end
30
+
31
+ # POST /invites
32
+ def create
33
+ @invite = Invite.new(invite_params)
34
+ @invite.inviting_user = current_user
35
+
36
+ if @invite.save
37
+ redirect_to @invite, notice: 'Invite was successfully created.'
38
+ else
39
+ render :new
40
+ end
41
+ end
42
+
43
+ # DELETE /invites/1
44
+ def destroy
45
+ @invite.destroy
46
+ redirect_to invites_url, notice: 'Invite was successfully destroyed.'
47
+ end
48
+
49
+ private
50
+
51
+ # Use callbacks to share common setup or constraints between actions.
52
+ def set_invite
53
+ @invite = Invite.find(params[:id])
54
+ end
55
+
56
+ # Only allow a trusted parameter "white list" through.
57
+ def invite_params
58
+ params.require(:invite).permit(:email, :role)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,141 @@
1
+ require_dependency "railswiki/application_controller"
2
+
3
+ module Railswiki
4
+ class PagesController < ApplicationController
5
+ include PagesHelper
6
+ include ApplicationHelper
7
+
8
+ before_action :set_page, only: [:show, :edit, :update, :destroy, :history]
9
+ before_action :require_pages_list_permission, only: [:index]
10
+ before_action :require_page_edit_permission, only: [:edit, :update]
11
+ before_action :require_page_create_permission, only: [:new, :create]
12
+ before_action :require_page_delete_permission, only: [:destroy]
13
+ before_action :require_page_history_permission, only: [:history]
14
+
15
+ # GET /pages
16
+ def index
17
+ @special_pages = []
18
+ @pages = Page.search(params[:search])
19
+ if params[:search]
20
+ # if we're searching, and there's only one link, redirect to the first result
21
+ if @pages.count == 1
22
+ redirect_to wiki_path(@pages.first)
23
+ end
24
+ else
25
+ # if we're not searching, display all the Special pages too
26
+ @special_pages = special_pages.reject { |page| @pages.map(&:title).include?(page.title) }
27
+ end
28
+ end
29
+
30
+ # GET /pages/1
31
+ def show
32
+ respond_to do |format|
33
+ format.html
34
+ format.json { render json: @page.expose_json }
35
+ end
36
+ end
37
+
38
+ # GET /pages/1/history
39
+ def history
40
+ require_special_pages_permission if is_special_page?(@page)
41
+
42
+ @histories = @page.histories
43
+ respond_to do |format|
44
+ format.html
45
+ format.json { render json: @histories.map { |history| history.expose_json } }
46
+ end
47
+ end
48
+
49
+ # GET /pages/new
50
+ def new
51
+ @page = Page.new
52
+ @page.title = params[:title].gsub(/_/, " ") if params[:title]
53
+
54
+ require_special_pages_permission if is_special_page?(@page)
55
+
56
+ # Preload Special: pages with their default content
57
+ special_page = special_pages.select { |page| page.title == @page.title }.first
58
+ if special_page
59
+ @page.default_content = special_page.content
60
+ end
61
+ end
62
+
63
+ # GET /pages/1/edit
64
+ def edit
65
+ end
66
+
67
+ # POST /pages
68
+ def create
69
+ @page = Page.new(page_params)
70
+
71
+ require_special_pages_permission if is_special_page?(@page)
72
+
73
+ @page.transaction do
74
+ if @page.save
75
+ update_content
76
+ redirect_to wiki_path(@page), notice: 'Page was successfully created.'
77
+ else
78
+ render :new
79
+ end
80
+ end
81
+ end
82
+
83
+ # PATCH/PUT /pages/1
84
+ def update
85
+ require_special_pages_permission if is_special_page?(@page)
86
+
87
+ @page.transaction do
88
+ if @page.update(page_params)
89
+ update_content
90
+ redirect_to wiki_path(@page), notice: 'Page was successfully updated.'
91
+ else
92
+ render :edit
93
+ end
94
+ end
95
+ end
96
+
97
+ # DELETE /pages/1
98
+ def destroy
99
+ require_special_pages_permission if is_special_page?(@page)
100
+
101
+ @page.destroy
102
+ redirect_to pages_url, notice: 'Page was successfully destroyed.'
103
+ end
104
+
105
+ private
106
+
107
+ # Use callbacks to share common setup or constraints between actions.
108
+ def set_page
109
+ title = params[:id] || params[:page_id] || params[:path]
110
+ raise ActiveRecord::RecordNotFound, "Unknown page request" unless title
111
+
112
+ @page = select_page(title)
113
+
114
+ unless @page
115
+ if user_can?(:create_page)
116
+ return redirect_to new_page_path(title: title)
117
+ else
118
+ if title == "Home"
119
+ @page = special_page("Welcome")
120
+ else
121
+ raise ActiveRecord::RecordNotFound, "Could not find page '#{title}'"
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ def update_content
128
+ # Create a new history
129
+ history = @page.histories.create!({
130
+ author: current_user,
131
+ body: params.require(:page)[:content]
132
+ })
133
+ @page.update_attributes! latest_version_id: history.id
134
+ end
135
+
136
+ # Only allow a trusted parameter "white list" through.
137
+ def page_params
138
+ params.require(:page).permit(:title, :latest_version_id)
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,75 @@
1
+ require_dependency "railswiki/application_controller"
2
+
3
+ module Railswiki
4
+ class SessionsController < ApplicationController
5
+ def create
6
+ User.transaction do
7
+ notice = []
8
+
9
+ auth = request.env["omniauth.auth"]
10
+ user = User.where(:provider => auth["provider"], :uid => auth["uid"]).first_or_initialize(
11
+ :refresh_token => auth["credentials"]["refresh_token"],
12
+ :access_token => auth["credentials"]["token"],
13
+ :expires => auth["credentials"]["expires_at"],
14
+ :name => auth["info"]["name"],
15
+ :email => auth["info"]["email"],
16
+ :image_url => auth["info"]["image"],
17
+ )
18
+ url = session[:return_to] || root_path
19
+ session[:return_to] = nil
20
+ url = root_path if url.eql?('/logout')
21
+
22
+ if user.new_record?
23
+ if User.count == 0
24
+ user.role = User::ROLE_ADMIN
25
+ notice << "As the first user, you have been automatically assigned admin privileges."
26
+ else
27
+ # this user must have been invited
28
+ invite = find_invite(user)
29
+ if invite
30
+ user.role = invite.role
31
+ user.save!
32
+ invite.update_attributes!({
33
+ invited_user: user,
34
+ accepted_at: Time.now,
35
+ })
36
+
37
+ notice << "Invite accepted as a #{invite.role || "user"}."
38
+ else
39
+ return redirect_to sessions_no_invite_path
40
+ end
41
+ end
42
+ end
43
+
44
+ if user.save
45
+ session[:user_id] = user.id
46
+ user.update_attributes! last_login: Time.now
47
+ notice << "Signed in!"
48
+
49
+ redirect_to url, :notice => notice.join("\n")
50
+ else
51
+ raise "Failed to login: #{user.errors.full_messages.join(", ")}"
52
+ end
53
+ end
54
+ end
55
+
56
+ def not_authorized
57
+ render status: :unauthorized
58
+ end
59
+
60
+ def no_invite
61
+ render status: :forbidden
62
+ end
63
+
64
+ def destroy
65
+ session[:user_id] = nil
66
+ redirect_to root_url, :notice => "Signed out!"
67
+ end
68
+
69
+ private
70
+
71
+ def find_invite(user)
72
+ Invite.where(email: user.email, accepted_at: nil).first
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,100 @@
1
+ require_dependency "railswiki/application_controller"
2
+
3
+ module Railswiki
4
+ class UploadedFilesController < ApplicationController
5
+ before_action :set_uploaded_file, only: [:show, :edit, :update, :destroy]
6
+
7
+ before_action :require_files_list_permission, only: [:index]
8
+ before_action :require_file_edit_permission, only: [:edit, :update]
9
+ before_action :require_file_create_permission, only: [:new, :create]
10
+ before_action :require_file_delete_permission, only: [:destroy]
11
+
12
+ # GET /uploaded_files
13
+ def index
14
+ @uploaded_files = UploadedFile.all
15
+ end
16
+
17
+ # GET /uploaded_files/image_dialog
18
+ def image_dialog
19
+ @uploaded_files = UploadedFile.all.select { |file| file.is_image? }
20
+ render layout: false
21
+ end
22
+
23
+ # GET /uploaded_files/file_dialog
24
+ def file_dialog
25
+ @uploaded_files = UploadedFile.all.reject { |file| file.is_image? }
26
+ render layout: false
27
+ end
28
+
29
+ # GET /uploaded_files/1
30
+ def show
31
+ end
32
+
33
+ # GET /uploaded_files/1/download
34
+ def download
35
+ @uploaded_file = UploadedFile.where(title: params[:title]).first
36
+ unless @uploaded_file
37
+ raise ActiveRecord::RecordNotFound, "Could not find file '#{params[:title]}'"
38
+ end
39
+ redirect_to @uploaded_file.file_url
40
+ end
41
+
42
+ # GET /uploaded_files/new
43
+ def new
44
+ @uploaded_file = UploadedFile.new
45
+ @uploaded_file.user = current_user
46
+ @uploaded_file.title = "#{Time.now}"
47
+ end
48
+
49
+ # GET /uploaded_files/1/edit
50
+ def edit
51
+ @uploaded_file.user = current_user
52
+ end
53
+
54
+ # POST /uploaded_files
55
+ def create
56
+ @uploaded_file = UploadedFile.new(uploaded_file_params)
57
+ @uploaded_file.user = current_user
58
+ @uploaded_file.title = "#{Time.now}"
59
+
60
+ if @uploaded_file.save
61
+ @uploaded_file.update_attributes! title: @uploaded_file.file_identifier
62
+
63
+ redirect_to @uploaded_file, notice: 'Uploaded file was successfully created.'
64
+ else
65
+ render :new
66
+ end
67
+ end
68
+
69
+ # PATCH/PUT /uploaded_files/1
70
+ def update
71
+ @uploaded_file.user = current_user
72
+ @uploaded_file.title = "#{Time.now}"
73
+
74
+ if @uploaded_file.update(uploaded_file_params)
75
+ @uploaded_file.update_attributes! title: @uploaded_file.file_identifier
76
+
77
+ redirect_to @uploaded_file, notice: 'Uploaded file was successfully updated.'
78
+ else
79
+ render :edit
80
+ end
81
+ end
82
+
83
+ # DELETE /uploaded_files/1
84
+ def destroy
85
+ @uploaded_file.destroy
86
+ redirect_to uploaded_files_url, notice: 'Uploaded file was successfully destroyed.'
87
+ end
88
+
89
+ private
90
+ # Use callbacks to share common setup or constraints between actions.
91
+ def set_uploaded_file
92
+ @uploaded_file = UploadedFile.find(params[:id])
93
+ end
94
+
95
+ # Only allow a trusted parameter "white list" through.
96
+ def uploaded_file_params
97
+ params.require(:uploaded_file).permit(:file, :title)
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,55 @@
1
+ require_dependency "railswiki/application_controller"
2
+
3
+ module Railswiki
4
+ class UsersController < ApplicationController
5
+ before_action :set_user, only: [:show, :edit, :update, :destroy]
6
+
7
+ before_action :require_users_list_permission, only: [:index]
8
+ before_action :require_user_edit_permission, only: [:edit, :update]
9
+ before_action :require_user_delete_permission, only: [:destroy]
10
+
11
+ # GET /users
12
+ def index
13
+ @users = User.all
14
+ end
15
+
16
+ # GET /users/1
17
+ def show
18
+ respond_to do |format|
19
+ format.html
20
+ format.json { render json: @user.expose_json }
21
+ end
22
+ end
23
+
24
+ # GET /users/1/edit
25
+ def edit
26
+ end
27
+
28
+ # PATCH/PUT /users/1
29
+ def update
30
+ if @user.update(user_params)
31
+ redirect_to @user, notice: 'User was successfully updated.'
32
+ else
33
+ render :edit
34
+ end
35
+ end
36
+
37
+ # DELETE /pages/1
38
+ def destroy
39
+ @user.destroy
40
+ redirect_to users_url, notice: 'User was successfully destroyed.'
41
+ end
42
+
43
+ private
44
+
45
+ # Use callbacks to share common setup or constraints between actions.
46
+ def set_user
47
+ @user = User.find(params[:id])
48
+ end
49
+
50
+ # Only allow a trusted parameter "white list" through.
51
+ def user_params
52
+ params.require(:user).permit(:name, :email, :role)
53
+ end
54
+ end
55
+ end