Commit b9d989dc authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'Andrew8xx8-gist'

parents 211e435a 213e117a
class Projects::ApplicationController < ApplicationController
before_filter :authorize_admin_team_member!
protected
def user_team
@team ||= UserTeam.find_by_path(params[:id])
end
before_filter :project
before_filter :repository
end
class Projects::SnippetsController < Projects::ApplicationController
before_filter :module_enabled
before_filter :snippet, only: [:show, :edit, :destroy, :update, :raw]
# Allow read any snippet
before_filter :authorize_read_project_snippet!
# Allow write(create) snippet
before_filter :authorize_write_project_snippet!, only: [:new, :create]
# Allow modify snippet
before_filter :authorize_modify_project_snippet!, only: [:edit, :update]
# Allow destroy snippet
before_filter :authorize_admin_project_snippet!, only: [:destroy]
layout 'project_resource'
respond_to :html
def index
@snippets = @project.snippets.fresh.non_expired
end
def new
@snippet = @project.snippets.build
end
def create
@snippet = @project.snippets.build(params[:project_snippet])
@snippet.author = current_user
if @snippet.save
redirect_to project_snippet_path(@project, @snippet)
else
respond_with(@snippet)
end
end
def edit
end
def update
if @snippet.update_attributes(params[:project_snippet])
redirect_to project_snippet_path(@project, @snippet)
else
respond_with(@snippet)
end
end
def show
@note = @project.notes.new(noteable: @snippet)
@target_type = :snippet
@target_id = @snippet.id
end
def destroy
return access_denied! unless can?(current_user, :admin_project_snippet, @snippet)
@snippet.destroy
redirect_to project_snippets_path(@project)
end
def raw
send_data(
@snippet.content,
type: "text/plain",
disposition: 'inline',
filename: @snippet.file_name
)
end
protected
def snippet
@snippet ||= @project.snippets.find(params[:id])
end
def authorize_modify_project_snippet!
return render_404 unless can?(current_user, :modify_project_snippet, @snippet)
end
def authorize_admin_project_snippet!
return render_404 unless can?(current_user, :admin_project_snippet, @snippet)
end
def module_enabled
return render_404 unless @project.snippets_enabled
end
end
class Projects::TeamsController < Projects::ApplicationController
before_filter :authorize_admin_team_member!
def available
@teams = current_user.is_admin? ? UserTeam.scoped : current_user.user_teams
@teams = @teams.without_project(project)
......@@ -24,4 +26,9 @@ class Projects::TeamsController < Projects::ApplicationController
redirect_to project_team_index_path(project)
end
protected
def user_team
@team ||= UserTeam.find_by_path(params[:id])
end
end
class SnippetsController < ProjectResourceController
before_filter :module_enabled
class SnippetsController < ApplicationController
before_filter :snippet, only: [:show, :edit, :destroy, :update, :raw]
# Allow read any snippet
before_filter :authorize_read_snippet!
# Allow write(create) snippet
before_filter :authorize_write_snippet!, only: [:new, :create]
# Allow modify snippet
before_filter :authorize_modify_snippet!, only: [:edit, :update]
......@@ -17,22 +10,38 @@ class SnippetsController < ProjectResourceController
respond_to :html
def index
@snippets = @project.snippets.fresh.non_expired
@snippets = Snippet.public.fresh.non_expired.page(params[:page]).per(20)
end
def user_index
@user = User.find_by_username(params[:username])
@snippets = @current_user.snippets.fresh.non_expired
@snippets = case params[:scope]
when 'public' then
@snippets.public
when 'private' then
@snippets.private
else
@snippets
end
@snippets = @snippets.page(params[:page]).per(20)
end
def new
@snippet = @project.snippets.new
@snippet = PersonalSnippet.new
end
def create
@snippet = @project.snippets.new(params[:snippet])
@snippet = PersonalSnippet.new(params[:personal_snippet])
@snippet.author = current_user
@snippet.save
if @snippet.valid?
redirect_to [@project, @snippet]
if @snippet.save
redirect_to snippet_path(@snippet)
else
respond_with(@snippet)
respond_with @snippet
end
end
......@@ -40,27 +49,22 @@ class SnippetsController < ProjectResourceController
end
def update
@snippet.update_attributes(params[:snippet])
if @snippet.valid?
redirect_to [@project, @snippet]
if @snippet.update_attributes(params[:personal_snippet])
redirect_to snippet_path(@snippet)
else
respond_with(@snippet)
respond_with @snippet
end
end
def show
@note = @project.notes.new(noteable: @snippet)
@target_type = :snippet
@target_id = @snippet.id
end
def destroy
return access_denied! unless can?(current_user, :admin_snippet, @snippet)
return access_denied! unless can?(current_user, :admin_personal_snippet, @snippet)
@snippet.destroy
redirect_to project_snippets_path(@project)
redirect_to snippets_path
end
def raw
......@@ -75,18 +79,14 @@ class SnippetsController < ProjectResourceController
protected
def snippet
@snippet ||= @project.snippets.find(params[:id])
@snippet ||= PersonalSnippet.find(params[:id])
end
def authorize_modify_snippet!
return render_404 unless can?(current_user, :modify_snippet, @snippet)
return render_404 unless can?(current_user, :modify_personal_snippet, @snippet)
end
def authorize_admin_snippet!
return render_404 unless can?(current_user, :admin_snippet, @snippet)
end
def module_enabled
return render_404 unless @project.snippets_enabled
return render_404 unless can?(current_user, :admin_personal_snippet, @snippet)
end
end
......@@ -73,7 +73,7 @@ module TabHelper
end
def project_tab_class
return "active" if current_page?(controller: "projects", action: :edit, id: @project)
return "active" if current_page?(controller: "/projects", action: :edit, id: @project)
if ['services', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name
"active"
......
......@@ -7,7 +7,8 @@ class Ability
when "Project" then project_abilities(user, subject)
when "Issue" then issue_abilities(user, subject)
when "Note" then note_abilities(user, subject)
when "Snippet" then snippet_abilities(user, subject)
when "ProjectSnippet" then project_snippet_abilities(user, subject)
when "PersonalSnippet" then personal_snippet_abilities(user, subject)
when "MergeRequest" then merge_request_abilities(user, subject)
when "Group", "Namespace" then group_abilities(user, subject)
when "UserTeam" then user_team_abilities(user, subject)
......@@ -54,7 +55,7 @@ class Ability
:read_wiki,
:read_issue,
:read_milestone,
:read_snippet,
:read_project_snippet,
:read_team_member,
:read_merge_request,
:read_note,
......@@ -67,8 +68,8 @@ class Ability
def project_report_rules
project_guest_rules + [
:download_code,
:write_snippet,
:fork_project
:fork_project,
:write_project_snippet
]
end
......@@ -84,11 +85,11 @@ class Ability
project_dev_rules + [
:push_code_to_protected_branches,
:modify_issue,
:modify_snippet,
:modify_project_snippet,
:modify_merge_request,
:admin_issue,
:admin_milestone,
:admin_snippet,
:admin_project_snippet,
:admin_team_member,
:admin_merge_request,
:admin_note,
......@@ -135,8 +136,7 @@ class Ability
rules.flatten
end
[:issue, :note, :snippet, :merge_request].each do |name|
[:issue, :note, :project_snippet, :personal_snippet, :merge_request].each do |name|
define_method "#{name}_abilities" do |user, subject|
if subject.author == user
[
......
......@@ -241,6 +241,10 @@ class Event < ActiveRecord::Base
target.noteable_type == "Commit"
end
def note_project_snippet?
target.noteable_type == "Snippet"
end
def note_target
target.noteable
end
......
......@@ -159,4 +159,10 @@ class Note < ActiveRecord::Base
"wall"
end
end
# FIXME: Hack for polymorphic associations with STI
# For more information wisit http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations
def noteable_type=(sType)
super(sType.to_s.classify.constantize.base_class.to_s)
end
end
# == Schema Information
#
# Table name: snippets
#
# id :integer not null, primary key
# title :string(255)
# content :text
# author_id :integer not null
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# file_name :string(255)
# expires_at :datetime
# type :string(255)
# private :boolean
class PersonalSnippet < Snippet
end
......@@ -57,7 +57,7 @@ class Project < ActiveRecord::Base
has_many :milestones, dependent: :destroy
has_many :users_projects, dependent: :destroy
has_many :notes, dependent: :destroy
has_many :snippets, dependent: :destroy
has_many :snippets, dependent: :destroy, class_name: "ProjectSnippet"
has_many :hooks, dependent: :destroy, class_name: "ProjectHook"
has_many :protected_branches, dependent: :destroy
has_many :user_team_project_relationships, dependent: :destroy
......
# == Schema Information
#
# Table name: snippets
#
# id :integer not null, primary key
# title :string(255)
# content :text
# author_id :integer not null
# project_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# file_name :string(255)
# expires_at :datetime
# type :string(255)
# private :boolean
class ProjectSnippet < Snippet
belongs_to :project
belongs_to :author, class_name: "User"
validates :project, presence: true
# Scopes
scope :fresh, -> { order("created_at DESC") }
scope :non_expired, -> { where(["expires_at IS NULL OR expires_at > ?", Time.current]) }
scope :expired, -> { where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) }
end
......@@ -11,29 +11,31 @@
# updated_at :datetime not null
# file_name :string(255)
# expires_at :datetime
#
# type :string(255)
# private :boolean
class Snippet < ActiveRecord::Base
include Linguist::BlobHelper
attr_accessible :title, :content, :file_name, :expires_at
attr_accessible :title, :content, :file_name, :expires_at, :private
belongs_to :project
belongs_to :author, class_name: "User"
has_many :notes, as: :noteable, dependent: :destroy
delegate :name, :email, to: :author, prefix: true, allow_nil: true
validates :author, presence: true
validates :project, presence: true
validates :title, presence: true, length: { within: 0..255 }
validates :file_name, presence: true, length: { within: 0..255 }
validates :content, presence: true
# Scopes
scope :fresh, -> { order("created_at DESC") }
scope :non_expired, -> { where(["expires_at IS NULL OR expires_at > ?", Time.current]) }
scope :public, -> { where(private: false) }
scope :private, -> { where(private: true) }
scope :fresh, -> { order("created_at DESC") }
scope :expired, -> { where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) }
scope :non_expired, -> { where(["expires_at IS NULL OR expires_at > ?", Time.current]) }
def self.content_types
[
......
......@@ -78,6 +78,7 @@ class User < ActiveRecord::Base
has_many :team_projects, through: :user_team_project_relationships
# Projects
has_many :snippets, dependent: :destroy, foreign_key: :author_id, class_name: "Snippet"
has_many :users_projects, dependent: :destroy
has_many :issues, dependent: :destroy, foreign_key: :author_id
has_many :notes, dependent: :destroy, foreign_key: :author_id
......
......@@ -5,6 +5,10 @@
- if event.note_commit?
= event.note_target_type
= link_to event.note_short_commit_id, project_commit_path(event.project, event.note_commit_id), class: "commit_short_id"
- if event.note_project_snippet?
= link_to project_snippet_path(event.project, event.note_target) do
%strong
#{event.note_target_type} ##{truncate event.note_target_id}
- else
= link_to [event.project, event.note_target] do
%strong
......
......@@ -18,6 +18,9 @@
%li
= link_to public_root_path, title: "Public area", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do
%i.icon-globe
%li
= link_to snippets_path, title: "Snippets area", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do
%i.icon-paste
- if current_user.is_admin?
%li
= link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do
......
!!! 5
%html{ lang: "en"}
= render "layouts/head", title: "Snipepts"
%body{class: "#{app_theme} application"}
= render "layouts/head_panel", title: "Snippets"
= render "layouts/flash"
%nav.main-nav
.container
%ul
= nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
= link_to root_path, title: "Back to dashboard" do
%i.icon-home
= nav_link(path: 'snippet#new') do
= link_to new_snippet_path do
New snippet
= nav_link(path: 'snippets#user_index') do
= link_to user_snippets_path(@current_user) do
My snippets
= nav_link(path: 'snippets#index') do
= link_to snippets_path do
Discover snippets
.container
.content= yield
.file_holder
.file_title
%i.icon-file
%strong= @snippet.file_name
%span.options
= link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-tiny", target: "_blank"
.file_content.code
- unless @snippet.content.empty?
%div{class: user_color_scheme_class}
= raw @snippet.colorize(formatter: :gitlab)
- else
%p.nothing_here_message Empty file
%h3.page_title
= @snippet.new_record? ? "New Snippet" : "Edit Snippet ##{@snippet.id}"
%hr
.snippet-form-holder
= form_for [@project, @snippet], as: :project_snippet, url: url do |f|
-if @snippet.errors.any?
.alert.alert-error
%ul
- @snippet.errors.full_messages.each do |msg|
%li= msg
.clearfix
= f.label :title
.input= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true
.clearfix
= f.label "Lifetime"
.input= f.select :expires_at, lifetime_select_options, {}, {class: 'chosen span2'}
.clearfix
.file-editor
= f.label :file_name, "File"
.input
.file_holder.snippet
.file_title
= f.text_field :file_name, placeholder: "example.rb", class: 'snippet-file-name', required: true
.file_content.code
%pre#editor= @snippet.content
= f.hidden_field :content, class: 'snippet-file-content'
.form-actions
= f.submit 'Save', class: "btn-save btn"
= link_to "Cancel", project_snippets_path(@project), class: " btn"
- unless @snippet.new_record?
.pull-right= link_to 'Destroy', project_snippet_path(@project, @snippet), confirm: 'Are you sure?', method: :delete, class: "btn pull-right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
:javascript
var editor = ace.edit("editor");
$(".snippet-form-holder form").submit(function(){
$(".snippet-file-content").val(editor.getValue());
});
%tr
%td
= image_tag gravatar_icon(snippet.author_email), class: "avatar s24"
%a{href: project_snippet_path(snippet.project, snippet)}
%strong= truncate(snippet.title, length: 60)
%td
= snippet.file_name
%td
%span.cgray
- if snippet.expires_at
= snippet.expires_at.to_date.to_s(:short)
- else
Never
= render "projects/snippets/form", url: project_snippet_path(@project, @snippet)
%h3.page_title
Snippets
%small share code pastes with others out of git repository
- if can? current_user, :write_project_snippet, @project
= link_to new_project_snippet_path(@project), class: "btn btn-small add_new pull-right", title: "New Snippet" do
Add new snippet
%br
%table
%thead
%tr
%th Title
%th File Name
%th Expires At
= render partial: "projects/snippets/snippet", collection: @snippets
- if @snippets.empty?
%tr
%td{colspan: 3}
%h3.nothing_here_message Nothing here.
= render "projects/snippets/form", url: project_snippets_path(@project, @snippet)
%h3.page_title
= @snippet.title
%small= @snippet.file_name
- if can?(current_user, :admin_project_snippet, @project) || @snippet.author == current_user
= link_to "Edit", edit_project_snippet_path(@project, @snippet), class: "btn btn-small pull-right", title: 'Edit Snippet'
%br
%div= render 'projects/snippets/blob'
%div#notes= render "notes/notes_with_form"
......@@ -3,7 +3,7 @@
%i.icon-file
%strong= @snippet.file_name
%span.options
= link_to "raw", raw_project_snippet_path(@project, @snippet), class: "btn btn-tiny", target: "_blank"
= link_to "raw", raw_snippet_path(@snippet), class: "btn btn-tiny", target: "_blank"
.file_content.code
- unless @snippet.content.empty?
%div{class: user_color_scheme_class}
......
......@@ -2,7 +2,7 @@
= @snippet.new_record? ? "New Snippet" : "Edit Snippet ##{@snippet.id}"
%hr
.snippet-form-holder
= form_for [@project, @snippet] do |f|
= form_for @snippet, as: :personal_snippet, url: url do |f|
-if @snippet.errors.any?
.alert.alert-error
%ul
......@@ -12,6 +12,9 @@
.clearfix
= f.label :title
.input= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true
.clearfix
= f.label "Private?"
.input= f.check_box :private, {class: ''}
.clearfix
= f.label "Lifetime"
.input= f.select :expires_at, lifetime_select_options, {}, {class: 'chosen span2'}
......@@ -28,9 +31,9 @@
.form-actions
= f.submit 'Save', class: "btn-save btn"
= link_to "Cancel", project_snippets_path(@project), class: " btn"
= link_to "Cancel", snippets_path(@project), class: " btn"
- unless @snippet.new_record?
.pull-right= link_to 'Destroy', [@project, @snippet], confirm: 'Removed snippet cannot be restored! Are you sure?', method: :delete, class: "btn pull-right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
.pull-right= link_to 'Destroy', snippet_path(@snippet), confirm: 'Removed snippet cannot be restored! Are you sure?', method: :delete, class: "btn pull-right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
:javascript
......
%tr
%td
- if snippet.private?
%i.icon-lock
- else
%i.icon-globe
= image_tag gravatar_icon(snippet.author_email), class: "avatar s24"
%a{href: project_snippet_path(snippet.project, snippet)}
%strong= truncate(snippet.title, length: 60)
- if snippet.project_id?
%a{href: project_snippet_path(snippet.project, snippet)}
%strong= truncate(snippet.title, length: 60)
- else
%a{href: snippet_path(snippet)}
%strong= truncate(snippet.title, length: 60)
%td
= snippet.file_name
%td
......@@ -11,3 +19,6 @@
= snippet.expires_at.to_date.to_s(:short)
- else
Never
%td
- if snippet.project_id?
= link_to snippet.project.name, project_path(snippet.project)
%table
%thead
%tr
%th Title
%th File Name
%th Expires At
%th Project
= render partial: 'snippet', collection: @snippets
- if @snippets.empty?
%tr
%td{colspan: 4}
%h3.nothing_here_message Nothing here.
= paginate @snippets
= render "snippets/form"
= render "snippets/form", url: snippet_path(@snippet)
%h3.page_title
Snippets
Public snippets
%small share code pastes with others out of git repository
= link_to new_snippet_path, class: "btn btn-small add_new pull-right", title: "New Snippet" do
Add new snippet
%hr
.row
.span12
= render 'snippets'
- if can? current_user, :write_snippet, @project
= link_to new_project_snippet_path(@project), class: "btn btn-small add_new pull-right", title: "New Snippet" do
Add new snippet
%br
%table
%thead
%tr
%th Title
%th File Name
%th Expires At
= render @snippets
- if @snippets.empty?
%tr