railswiki 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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