Commit ce8eba89135c901fd4f04f1b2385bdbd23f48766
Exists in
master
and in
4 other branches
Merge branch 'wiki'
Conflicts: app/views/layouts/_project_menu.html.haml
Showing
22 changed files
with
294 additions
and
17 deletions
Show diff stats
app/assets/stylesheets/main.scss
app/assets/stylesheets/projects.css.scss
@@ -0,0 +1,68 @@ | @@ -0,0 +1,68 @@ | ||
1 | +class WikisController < ApplicationController | ||
2 | + before_filter :project | ||
3 | + before_filter :add_project_abilities | ||
4 | + before_filter :authorize_read_wiki! | ||
5 | + before_filter :authorize_write_wiki!, :except => [:show, :destroy] | ||
6 | + before_filter :authorize_admin_wiki!, :only => :destroy | ||
7 | + layout "project" | ||
8 | + | ||
9 | + def show | ||
10 | + if params[:old_page_id] | ||
11 | + @wiki = @project.wikis.find(params[:old_page_id]) | ||
12 | + else | ||
13 | + @wiki = @project.wikis.where(:slug => params[:id]).order("created_at").last | ||
14 | + end | ||
15 | + respond_to do |format| | ||
16 | + if @wiki | ||
17 | + format.html | ||
18 | + else | ||
19 | + @wiki = @project.wikis.new(:slug => params[:id]) | ||
20 | + format.html { render "edit" } | ||
21 | + end | ||
22 | + end | ||
23 | + end | ||
24 | + | ||
25 | + def edit | ||
26 | + @wiki = @project.wikis.where(:slug => params[:id]).order("created_at").last | ||
27 | + @wiki = Wiki.regenerate_from @wiki | ||
28 | + end | ||
29 | + | ||
30 | + def create | ||
31 | + @wiki = @project.wikis.new(params[:wiki]) | ||
32 | + @wiki.user = current_user | ||
33 | + | ||
34 | + respond_to do |format| | ||
35 | + if @wiki.save | ||
36 | + format.html { redirect_to [@project, @wiki], notice: 'Wiki was successfully updated.' } | ||
37 | + else | ||
38 | + format.html { render action: "edit" } | ||
39 | + end | ||
40 | + end | ||
41 | + end | ||
42 | + | ||
43 | + def history | ||
44 | + @wikis = @project.wikis.where(:slug => params[:id]).order("created_at") | ||
45 | + end | ||
46 | + | ||
47 | + def destroy | ||
48 | + @wikis = @project.wikis.where(:slug => params[:id]).delete_all | ||
49 | + | ||
50 | + respond_to do |format| | ||
51 | + format.html { redirect_to project_wiki_path(@project, :index), notice: "Page was successfully deleted" } | ||
52 | + end | ||
53 | + end | ||
54 | + | ||
55 | + protected | ||
56 | + | ||
57 | + def authorize_read_wiki! | ||
58 | + can?(current_user, :read_wiki, @project) | ||
59 | + end | ||
60 | + | ||
61 | + def authorize_write_wiki! | ||
62 | + can?(current_user, :write_wiki, @project) | ||
63 | + end | ||
64 | + | ||
65 | + def authorize_admin_wiki! | ||
66 | + can?(current_user, :admin_wiki, @project) | ||
67 | + end | ||
68 | +end |
app/models/ability.rb
@@ -5,6 +5,7 @@ class Ability | @@ -5,6 +5,7 @@ class Ability | ||
5 | when "Issue" then issue_abilities(object, subject) | 5 | when "Issue" then issue_abilities(object, subject) |
6 | when "Note" then note_abilities(object, subject) | 6 | when "Note" then note_abilities(object, subject) |
7 | when "Snippet" then snippet_abilities(object, subject) | 7 | when "Snippet" then snippet_abilities(object, subject) |
8 | + when "Wiki" then wiki_abilities(object, subject) | ||
8 | else [] | 9 | else [] |
9 | end | 10 | end |
10 | end | 11 | end |
@@ -14,35 +15,40 @@ class Ability | @@ -14,35 +15,40 @@ class Ability | ||
14 | 15 | ||
15 | rules << [ | 16 | rules << [ |
16 | :read_project, | 17 | :read_project, |
18 | + :read_wiki, | ||
17 | :read_issue, | 19 | :read_issue, |
18 | :read_snippet, | 20 | :read_snippet, |
19 | :read_team_member, | 21 | :read_team_member, |
20 | :read_merge_request, | 22 | :read_merge_request, |
21 | - :read_note | ||
22 | - ] if project.allow_read_for?(user) | ||
23 | - | ||
24 | - rules << [ | 23 | + :read_note, |
25 | :write_project, | 24 | :write_project, |
26 | :write_issue, | 25 | :write_issue, |
27 | :write_snippet, | 26 | :write_snippet, |
28 | :write_merge_request, | 27 | :write_merge_request, |
29 | :write_note | 28 | :write_note |
30 | - ] if project.allow_write_for?(user) | 29 | + ] if project.guest_access_for?(user) |
30 | + | ||
31 | + rules << [ | ||
32 | + :download_code, | ||
33 | + ] if project.report_access_for?(user) | ||
34 | + | ||
35 | + rules << [ | ||
36 | + :write_wiki | ||
37 | + ] if project.dev_access_for?(user) | ||
31 | 38 | ||
32 | rules << [ | 39 | rules << [ |
33 | :modify_issue, | 40 | :modify_issue, |
34 | :modify_snippet, | 41 | :modify_snippet, |
42 | + :modify_wiki, | ||
35 | :admin_project, | 43 | :admin_project, |
36 | :admin_issue, | 44 | :admin_issue, |
37 | :admin_snippet, | 45 | :admin_snippet, |
38 | :admin_team_member, | 46 | :admin_team_member, |
39 | :admin_merge_request, | 47 | :admin_merge_request, |
40 | - :admin_note | ||
41 | - ] if project.allow_admin_for?(user) | 48 | + :admin_note, |
49 | + :admin_wiki | ||
50 | + ] if project.master_access_for?(user) | ||
42 | 51 | ||
43 | - rules << [ | ||
44 | - :download_code, | ||
45 | - ] if project.allow_pull_for?(user) | ||
46 | 52 | ||
47 | rules.flatten | 53 | rules.flatten |
48 | end | 54 | end |
app/models/project.rb
@@ -12,6 +12,7 @@ class Project < ActiveRecord::Base | @@ -12,6 +12,7 @@ class Project < ActiveRecord::Base | ||
12 | has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key" | 12 | has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key" |
13 | has_many :web_hooks, :dependent => :destroy | 13 | has_many :web_hooks, :dependent => :destroy |
14 | has_many :protected_branches, :dependent => :destroy | 14 | has_many :protected_branches, :dependent => :destroy |
15 | + has_many :wikis, :dependent => :destroy | ||
15 | 16 | ||
16 | acts_as_taggable | 17 | acts_as_taggable |
17 | 18 | ||
@@ -232,16 +233,20 @@ class Project < ActiveRecord::Base | @@ -232,16 +233,20 @@ class Project < ActiveRecord::Base | ||
232 | !users_projects.where(:user_id => user.id).empty? | 233 | !users_projects.where(:user_id => user.id).empty? |
233 | end | 234 | end |
234 | 235 | ||
235 | - def allow_write_for?(user) | 236 | + def guest_access_for?(user) |
236 | !users_projects.where(:user_id => user.id).empty? | 237 | !users_projects.where(:user_id => user.id).empty? |
237 | end | 238 | end |
238 | 239 | ||
239 | - def allow_admin_for?(user) | ||
240 | - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id | 240 | + def report_access_for?(user) |
241 | + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty? | ||
241 | end | 242 | end |
242 | 243 | ||
243 | - def allow_pull_for?(user) | ||
244 | - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty? | 244 | + def dev_access_for?(user) |
245 | + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty? | ||
246 | + end | ||
247 | + | ||
248 | + def master_access_for?(user) | ||
249 | + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id | ||
245 | end | 250 | end |
246 | 251 | ||
247 | def root_ref | 252 | def root_ref |
@@ -0,0 +1,33 @@ | @@ -0,0 +1,33 @@ | ||
1 | +class Wiki < ActiveRecord::Base | ||
2 | + belongs_to :project | ||
3 | + belongs_to :user | ||
4 | + | ||
5 | + validates :content, :title, :user_id, :presence => true | ||
6 | + validates :title, :length => 1..250 | ||
7 | + | ||
8 | + before_update :set_slug | ||
9 | + | ||
10 | + | ||
11 | + def to_param | ||
12 | + slug | ||
13 | + end | ||
14 | + | ||
15 | + protected | ||
16 | + | ||
17 | + def set_slug | ||
18 | + self.slug = self.title.parameterize | ||
19 | + end | ||
20 | + | ||
21 | + class << self | ||
22 | + def regenerate_from wiki | ||
23 | + regenerated_field = [:slug, :content, :title] | ||
24 | + | ||
25 | + new_wiki = Wiki.new | ||
26 | + regenerated_field.each do |field| | ||
27 | + new_wiki.send("#{field}=", wiki.send(field)) | ||
28 | + end | ||
29 | + new_wiki | ||
30 | + end | ||
31 | + | ||
32 | + end | ||
33 | +end |
app/views/layouts/_project_menu.html.haml
@@ -12,7 +12,6 @@ | @@ -12,7 +12,6 @@ | ||
12 | = link_to project_issues_filter_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do | 12 | = link_to project_issues_filter_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do |
13 | Issues | 13 | Issues |
14 | %span.count= @project.issues.opened.count | 14 | %span.count= @project.issues.opened.count |
15 | - | ||
16 | - if @project.merge_requests_enabled | 15 | - if @project.merge_requests_enabled |
17 | = link_to project_merge_requests_path(@project), :class => (controller.controller_name == "merge_requests") ? "current" : nil do | 16 | = link_to project_merge_requests_path(@project), :class => (controller.controller_name == "merge_requests") ? "current" : nil do |
18 | Merge Requests | 17 | Merge Requests |
@@ -21,3 +20,7 @@ | @@ -21,3 +20,7 @@ | ||
21 | - if @project.wall_enabled | 20 | - if @project.wall_enabled |
22 | = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do | 21 | = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do |
23 | Wall | 22 | Wall |
23 | + | ||
24 | + - if @project.wiki_enabled | ||
25 | + = link_to project_wiki_path(@project, :index), :class => (controller.controller_name == "wikis") ? "current" : nil do | ||
26 | + Wiki |
app/views/projects/_form.html.haml
@@ -41,6 +41,10 @@ | @@ -41,6 +41,10 @@ | ||
41 | .clearfix | 41 | .clearfix |
42 | = f.label :wall_enabled, "Wall" | 42 | = f.label :wall_enabled, "Wall" |
43 | .input= f.check_box :wall_enabled | 43 | .input= f.check_box :wall_enabled |
44 | + | ||
45 | + .clearfix | ||
46 | + = f.label :wiki_enabled, "Wiki" | ||
47 | + .input= f.check_box :wiki_enabled | ||
44 | 48 | ||
45 | .clearfix | 49 | .clearfix |
46 | = f.label :description | 50 | = f.label :description |
@@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
1 | += form_for [@project, @wiki] do |f| | ||
2 | + -if @wiki.errors.any? | ||
3 | + #error_explanation | ||
4 | + %h2= "#{pluralize(@wiki.errors.count, "error")} prohibited this wiki from being saved:" | ||
5 | + %ul | ||
6 | + - @wiki.errors.full_messages.each do |msg| | ||
7 | + %li= msg | ||
8 | + | ||
9 | + .clearfix | ||
10 | + = f.label :title | ||
11 | + .input= f.text_field :title, :class => :xxlarge | ||
12 | + = f.hidden_field :slug | ||
13 | + .clearfix | ||
14 | + = f.label :content | ||
15 | + .input= f.text_area :content, :class => :xxlarge | ||
16 | + .actions | ||
17 | + = f.submit 'Save', :class => "primary btn" | ||
18 | + = link_to "Cancel", project_wiki_path(@project, :index), :class => "btn" |
@@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
1 | +%h2 Versions | ||
2 | +%table | ||
3 | + %thead | ||
4 | + %tr | ||
5 | + %th # | ||
6 | + %th last edit | ||
7 | + %th created by | ||
8 | + %tbody | ||
9 | + - @wikis.each_with_index do |wiki_page, i| | ||
10 | + %tr | ||
11 | + %td= i + 1 | ||
12 | + %td | ||
13 | + = link_to wiki_page.created_at.to_s(:short), project_wiki_path(@project, wiki_page, :old_page_id => wiki_page.id) | ||
14 | + ( | ||
15 | + = time_ago_in_words(wiki_page.created_at) | ||
16 | + ago | ||
17 | + ) | ||
18 | + %td= wiki_page.user.name | ||
19 | + |
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +%h3 | ||
2 | + = @wiki.title | ||
3 | + = link_to edit_project_wiki_path(@project, @wiki), :class => "right btn small" do | ||
4 | + Edit | ||
5 | + - if can? current_user, :write_wiki, @project | ||
6 | + = link_to history_project_wiki_path(@project, @wiki), :class => "right btn small" do | ||
7 | + History | ||
8 | +%hr | ||
9 | + | ||
10 | += markdown_to_html @wiki.content | ||
11 | + | ||
12 | +%p.time Last edited by #{@wiki.user.name}, in #{time_ago_in_words @wiki.created_at} | ||
13 | +- if can? current_user, :write_wiki, @project | ||
14 | + = link_to project_wiki_path(@project, @wiki), :confirm => "Are you sure you want to delete this page?", :method => :delete do | ||
15 | + Delete this page |
config/routes.rb
1 | Gitlab::Application.routes.draw do | 1 | Gitlab::Application.routes.draw do |
2 | 2 | ||
3 | + | ||
3 | # Optionally, enable Resque here | 4 | # Optionally, enable Resque here |
4 | require 'resque/server' | 5 | require 'resque/server' |
5 | mount Resque::Server.new, at: '/info/resque' | 6 | mount Resque::Server.new, at: '/info/resque' |
@@ -55,6 +56,12 @@ Gitlab::Application.routes.draw do | @@ -55,6 +56,12 @@ Gitlab::Application.routes.draw do | ||
55 | get "files" | 56 | get "files" |
56 | end | 57 | end |
57 | 58 | ||
59 | + resources :wikis, :only => [:show, :edit, :destroy, :create] do | ||
60 | + member do | ||
61 | + get "history" | ||
62 | + end | ||
63 | + end | ||
64 | + | ||
58 | resource :repository do | 65 | resource :repository do |
59 | member do | 66 | member do |
60 | get "branches" | 67 | get "branches" |
db/migrate/20120219140810_add_wiki_enabled_to_project.rb
0 → 100644
db/schema.rb
@@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
11 | # | 11 | # |
12 | # It's strongly recommended to check this file into your version control system. | 12 | # It's strongly recommended to check this file into your version control system. |
13 | 13 | ||
14 | -ActiveRecord::Schema.define(:version => 20120216085842) do | 14 | +ActiveRecord::Schema.define(:version => 20120219193300) do |
15 | 15 | ||
16 | create_table "issues", :force => true do |t| | 16 | create_table "issues", :force => true do |t| |
17 | t.string "title" | 17 | t.string "title" |
@@ -80,6 +80,7 @@ ActiveRecord::Schema.define(:version => 20120216085842) do | @@ -80,6 +80,7 @@ ActiveRecord::Schema.define(:version => 20120216085842) do | ||
80 | t.boolean "issues_enabled", :default => true, :null => false | 80 | t.boolean "issues_enabled", :default => true, :null => false |
81 | t.boolean "wall_enabled", :default => true, :null => false | 81 | t.boolean "wall_enabled", :default => true, :null => false |
82 | t.boolean "merge_requests_enabled", :default => true, :null => false | 82 | t.boolean "merge_requests_enabled", :default => true, :null => false |
83 | + t.boolean "wiki_enabled", :default => true, :null => false | ||
83 | end | 84 | end |
84 | 85 | ||
85 | create_table "protected_branches", :force => true do |t| | 86 | create_table "protected_branches", :force => true do |t| |
@@ -158,4 +159,14 @@ ActiveRecord::Schema.define(:version => 20120216085842) do | @@ -158,4 +159,14 @@ ActiveRecord::Schema.define(:version => 20120216085842) do | ||
158 | t.datetime "updated_at" | 159 | t.datetime "updated_at" |
159 | end | 160 | end |
160 | 161 | ||
162 | + create_table "wikis", :force => true do |t| | ||
163 | + t.string "title" | ||
164 | + t.text "content" | ||
165 | + t.integer "project_id" | ||
166 | + t.datetime "created_at", :null => false | ||
167 | + t.datetime "updated_at", :null => false | ||
168 | + t.string "slug" | ||
169 | + t.integer "user_id" | ||
170 | + end | ||
171 | + | ||
161 | end | 172 | end |
spec/factories.rb
@@ -59,3 +59,8 @@ end | @@ -59,3 +59,8 @@ end | ||
59 | Factory.add(:web_hook, WebHook) do |obj| | 59 | Factory.add(:web_hook, WebHook) do |obj| |
60 | obj.url = Faker::Internet.url | 60 | obj.url = Faker::Internet.url |
61 | end | 61 | end |
62 | + | ||
63 | +Factory.add(:wikis, WebHook) do |obj| | ||
64 | + obj.title = Faker::Lorem.sentence | ||
65 | + obj.content = Faker::Lorem.sentence | ||
66 | +end |
@@ -0,0 +1,35 @@ | @@ -0,0 +1,35 @@ | ||
1 | +require 'spec_helper' | ||
2 | + | ||
3 | +describe "Wiki" do | ||
4 | + let(:project) { Factory :project } | ||
5 | + | ||
6 | + before do | ||
7 | + login_as :user | ||
8 | + project.add_access(@user, :read, :write) | ||
9 | + end | ||
10 | + | ||
11 | + describe "Add pages" do | ||
12 | + before do | ||
13 | + visit project_wiki_path(project, :index) | ||
14 | + end | ||
15 | + | ||
16 | + it "should see form" do | ||
17 | + page.should have_content("Editing page") | ||
18 | + end | ||
19 | + | ||
20 | + it "should see added page" do | ||
21 | + fill_in "Title", :with => 'Test title' | ||
22 | + fill_in "Content", :with => '[link test](test)' | ||
23 | + click_on "Save" | ||
24 | + | ||
25 | + page.should have_content("Test title") | ||
26 | + page.should have_content("link test") | ||
27 | + | ||
28 | + click_link "link test" | ||
29 | + | ||
30 | + page.should have_content("Editing page") | ||
31 | + end | ||
32 | + | ||
33 | + end | ||
34 | + | ||
35 | +end |