diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a2e22a670a31ed44910c6b11edc0e72daf154a5d
--- /dev/null
+++ b/app/controllers/projects/snippets_controller.rb
@@ -0,0 +1,92 @@
+class SnippetsController < ProjectResourceController
+  before_filter :module_enabled
+  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]
+
+  # Allow destroy snippet
+  before_filter :authorize_admin_snippet!, only: [:destroy]
+
+  respond_to :html
+
+  def index
+    @snippets = @project.snippets.fresh.non_expired
+  end
+
+  def new
+    @snippet = @project.snippets.new
+  end
+
+  def create
+    @snippet = @project.snippets.new(params[:snippet])
+    @snippet.author = current_user
+    @snippet.save
+
+    if @snippet.valid?
+      redirect_to [@project, @snippet]
+    else
+      respond_with(@snippet)
+    end
+  end
+
+  def edit
+  end
+
+  def update
+    @snippet.update_attributes(params[:snippet])
+
+    if @snippet.valid?
+      redirect_to [@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_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_snippet!
+    return render_404 unless can?(current_user, :modify_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
+  end
+end
diff --git a/db/migrate/20130323174317_add_private_to_snippets.rb b/db/migrate/20130323174317_add_private_to_snippets.rb
new file mode 100644
index 0000000000000000000000000000000000000000..427b530464d3427362dd7c9a552e535052ade895
--- /dev/null
+++ b/db/migrate/20130323174317_add_private_to_snippets.rb
@@ -0,0 +1,5 @@
+class AddPrivateToSnippets < ActiveRecord::Migration
+  def change
+    add_column :snippets, :private, :boolean
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index e4349ac4bf79633e68cdb1e107d54953a0930156..a48b85c153e84312394c3d92bf139c5695bdc905 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20130318212250) do
+ActiveRecord::Schema.define(:version => 20130323174317) do
 
   create_table "events", :force => true do |t|
     t.string   "target_type"
@@ -190,6 +190,7 @@ ActiveRecord::Schema.define(:version => 20130318212250) do
     t.datetime "updated_at", :null => false
     t.string   "file_name"
     t.datetime "expires_at"
+    t.boolean  "private"
   end
 
   add_index "snippets", ["created_at"], :name => "index_snippets_on_created_at"