diff --git a/app/contexts/project_update_context.rb b/app/contexts/project_update_context.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e28d43d0e81cf4a222080cf2e596dc17cf77186b
--- /dev/null
+++ b/app/contexts/project_update_context.rb
@@ -0,0 +1,21 @@
+class ProjectUpdateContext < BaseContext
+  def execute(role = :default)
+    namespace_id = params[:project].delete(:namespace_id)
+
+    if namespace_id.present?
+      if namespace_id == Namespace.global_id
+        if project.namespace.present?
+          # Transfer to global namespace from anyone
+          project.transfer(nil)
+        end
+      elsif namespace_id.to_i != project.namespace_id
+        # Transfer to someone namespace
+        namespace = Namespace.find(namespace_id)
+        project.transfer(namespace)
+      end
+    end
+
+    project.update_attributes(params[:project], as: role)
+  end
+end
+
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index c3a419afd0f52564ff132f0bfa38730680675195..e61f94f8cf3a5bb2e490e513017a24c95953beb2 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -24,13 +24,9 @@ class Admin::ProjectsController < AdminController
   end
 
   def update
-    owner_id = params[:project].delete(:owner_id)
+    status = ProjectUpdateContext.new(project, current_user, params).execute(:admin)
 
-    if owner_id
-      @project.owner = User.find(owner_id)
-    end
-
-    if @project.update_attributes(params[:project], as: :admin)
+    if status
       redirect_to [:admin, @project], notice: 'Project was successfully updated.'
     else
       render action: "edit"
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 2be9a54da527e9d67f7b8bb830720393bacb78cc..66f2e87de3eba5fc479532e9111de463defa7193 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -2,6 +2,7 @@ class ApplicationController < ActionController::Base
   before_filter :authenticate_user!
   before_filter :reject_blocked!
   before_filter :set_current_user_for_observers
+  before_filter :add_abilities
   before_filter :dev_tools if Rails.env == 'development'
 
   protect_from_forgery
@@ -65,11 +66,17 @@ class ApplicationController < ActionController::Base
   def project
     id = params[:project_id] || params[:id]
 
-    @project ||= current_user.projects.find_with_namespace(id)
-    @project || render_404
+    @project = Project.find_with_namespace(id)
+
+    if @project and can?(current_user, :read_project, @project)
+      @project
+    else
+      @project = nil
+      render_404
+    end
   end
 
-  def add_project_abilities
+  def add_abilities
     abilities << Ability
   end
 
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 4f874a9654a81e7038ccd7a7a96a85ad85f67524..e01b586a394e78589f2f966559a6b04fd3e2d470 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -5,7 +5,7 @@ class DashboardController < ApplicationController
   before_filter :event_filter, only: :index
 
   def index
-    @groups = Group.where(id: current_user.projects.pluck(:namespace_id))
+    @groups = current_user.accessed_groups
     @projects = @projects.page(params[:page]).per(30)
     @events = Event.in_projects(current_user.project_ids)
     @events = @event_filter.apply_filter(@events)
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index c969f41ebda6e7a6105ca869fd485435a905b096..6fd5de8abf9044082f90bdfa6075ba9d8638d535 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -4,7 +4,6 @@ class GroupsController < ApplicationController
 
   before_filter :group
   before_filter :projects
-  before_filter :add_project_abilities
 
   def show
     @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0)
@@ -45,7 +44,7 @@ class GroupsController < ApplicationController
   end
 
   def people
-    @users = group.users.all
+    @users = group.users
   end
 
   protected
@@ -55,7 +54,11 @@ class GroupsController < ApplicationController
   end
 
   def projects
-    @projects ||= current_user.projects_sorted_by_activity.where(namespace_id: @group.id)
+    @projects ||= if can?(current_user, :manage_group, @group)
+                    @group.projects.all
+                  else
+                    current_user.projects_sorted_by_activity.where(namespace_id: @group.id)
+                  end
   end
 
   def project_ids
diff --git a/app/controllers/project_resource_controller.rb b/app/controllers/project_resource_controller.rb
index d297bba635fa4e3031a8dc84582c4e8368953d9b..81bc3a91bd1ab07d1ed2c4752208745b8d83b64f 100644
--- a/app/controllers/project_resource_controller.rb
+++ b/app/controllers/project_resource_controller.rb
@@ -1,5 +1,3 @@
 class ProjectResourceController < ApplicationController
   before_filter :project
-  # Authorize
-  before_filter :add_project_abilities
 end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index ed3406918215aec4c9d717f1fc2a37bbd3e5b559..a6e7f1f93fb9f937092277c807e540548ee6e444 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -34,20 +34,10 @@ class ProjectsController < ProjectResourceController
   end
 
   def update
-    if params[:project].has_key?(:namespace_id)
-      namespace_id = params[:project].delete(:namespace_id)
-      if namespace_id == Namespace.global_id and project.namespace.present?
-        # Transfer to global namespace from anyone
-        project.transfer(nil)
-      elsif namespace_id.present? and namespace_id.to_i != project.namespace_id
-        # Transfer to someone namespace
-        namespace = Namespace.find(namespace_id)
-        project.transfer(namespace)
-      end
-    end
+    status = ProjectUpdateContext.new(project, current_user, params).execute
 
     respond_to do |format|
-      if project.update_attributes(params[:project])
+      if status
         flash[:notice] = 'Project was successfully updated.'
         format.html { redirect_to edit_project_path(project), notice: 'Project was successfully updated.' }
         format.js
diff --git a/app/models/ability.rb b/app/models/ability.rb
index e55e7709372063c1d3144beb491120c7dc90c6fb..96d3ac6dd514123294d8d4d5b17264d0b6ab62b5 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -15,7 +15,37 @@ class Ability
     def project_abilities(user, project)
       rules = []
 
-      rules << [
+      # Rules based on role in project
+      if project.master_access_for?(user)
+        # TODO: replace with master rules.
+        # Only allow project administration for owners
+        rules << project_admin_rules
+
+      elsif project.dev_access_for?(user)
+        rules << project_dev_rules
+
+      elsif project.report_access_for?(user)
+        rules << project_report_rules
+
+      elsif project.guest_access_for?(user)
+        rules << project_guest_rules
+      end
+
+      # If user own project namespace (Ex. group owner or account owner)
+      if project.namespace && project.namespace.owner == user
+        rules << project_admin_rules
+      end
+
+      # If user was set as direct project owner
+      if project.owner == user
+        rules << project_admin_rules
+      end
+
+      rules.flatten
+    end
+
+    def project_guest_rules
+      [
         :read_project,
         :read_wiki,
         :read_issue,
@@ -27,28 +57,30 @@ class Ability
         :write_project,
         :write_issue,
         :write_note
-      ] if project.guest_access_for?(user)
+      ]
+    end
 
-      rules << [
+    def project_report_rules
+      project_guest_rules + [
         :download_code,
         :write_merge_request,
         :write_snippet
-      ] if project.report_access_for?(user)
+      ]
+    end
 
-      rules << [
+    def project_dev_rules
+      project_report_rules + [
         :write_wiki,
         :push_code
-      ] if project.dev_access_for?(user)
-
-      rules << [
-        :push_code_to_protected_branches
-      ] if project.master_access_for?(user)
+      ]
+    end
 
-      rules << [
+    def project_master_rules
+      project_dev_rules + [
+        :push_code_to_protected_branches,
         :modify_issue,
         :modify_snippet,
         :modify_merge_request,
-        :admin_project,
         :admin_issue,
         :admin_milestone,
         :admin_snippet,
@@ -57,9 +89,13 @@ class Ability
         :admin_note,
         :accept_mr,
         :admin_wiki
-      ] if project.master_access_for?(user) || project.owner == user
+      ]
+    end
 
-      rules.flatten
+    def project_admin_rules
+      project_master_rules + [
+        :admin_project
+      ]
     end
 
     def group_abilities user, group
diff --git a/app/models/group.rb b/app/models/group.rb
index 66267c569575a6ff0e5d43699fed892acf02a215..b668f5560ab1ca9a7761d7ed133b517f29a2a5aa 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -13,7 +13,9 @@
 
 class Group < Namespace
   def users
-    User.joins(:users_projects).where(users_projects: {project_id: project_ids}).uniq
+    users = User.joins(:users_projects).where(users_projects: {project_id: project_ids})
+    users = users << owner
+    users.uniq
   end
 
   def human_name
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 5762bfc57cb1f65d23a0507f7ae53764895e8ee7..e1c24de949a2a029c947d7119b6a6fb5fb7447ad 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -53,12 +53,14 @@ class Namespace < ActiveRecord::Base
   end
 
   def move_dir
-    old_path = File.join(Gitlab.config.git_base_path, path_was)
-    new_path = File.join(Gitlab.config.git_base_path, path)
-    if File.exists?(new_path)
-      raise "Already exists"
+    if path_changed?
+      old_path = File.join(Gitlab.config.git_base_path, path_was)
+      new_path = File.join(Gitlab.config.git_base_path, path)
+      if File.exists?(new_path)
+        raise "Already exists"
+      end
+      system("mv #{old_path} #{new_path}")
     end
-    system("mv #{old_path} #{new_path}")
   end
 
   def rm_dir
diff --git a/app/models/project.rb b/app/models/project.rb
index 0c74c0bd878539f324ab0195c04a7aa716218aab..8df662db9a0cd983d5080c12d6a83ec913c82423 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -29,7 +29,7 @@ class Project < ActiveRecord::Base
   attr_accessible :name, :path, :description, :default_branch, :issues_enabled,
                   :wall_enabled, :merge_requests_enabled, :wiki_enabled, as: [:default, :admin]
 
-  attr_accessible :namespace_id, as: :admin
+  attr_accessible :namespace_id, :owner_id, as: :admin
 
   attr_accessor :error_code
 
diff --git a/app/models/user.rb b/app/models/user.rb
index 43163404e854f8681f165ce5856875bb0f60280f..d43e3cbb6b6dbe3e7a84bf5be12c54eb8242d040 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -123,4 +123,11 @@ class User < ActiveRecord::Base
       self.password = self.password_confirmation = Devise.friendly_token.first(8)
     end
   end
+
+  def accessed_groups
+    @accessed_groups ||= begin
+                           groups = Group.where(id: self.projects.pluck(:namespace_id)).all
+                           groups + self.groups
+                         end
+  end
 end
diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml
index eb12c61f71ab01f6864ee279482d635c4bed902a..110ff04a5bdafc53ba8420f385240e542df20a2e 100644
--- a/app/views/admin/projects/_form.html.haml
+++ b/app/views/admin/projects/_form.html.haml
@@ -22,7 +22,7 @@
     - unless project.new_record?
       .clearfix
         = f.label :namespace_id
-        .input= f.select :namespace_id, namespaces_options, {}, {class: 'chosen'}
+        .input= f.select :namespace_id, namespaces_options(@project.namespace_id), {}, {class: 'chosen'}
 
       .clearfix
         = f.label :owner_id
diff --git a/app/views/errors/access_denied.html.haml b/app/views/errors/access_denied.html.haml
index a6e4f0b9498fdd6faedae6537a46eb1bfdf2b9f4..f2d082cb77defd275ead59eba0b1ac71cd9e5905 100644
--- a/app/views/errors/access_denied.html.haml
+++ b/app/views/errors/access_denied.html.haml
@@ -1,4 +1,4 @@
-%h1 403
+%h1.http_status_code 403
 %h3.page_title Access Denied
 %hr
 %p You are not allowed to access this page.
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 72d7ad9a5920fd2574f27eae8533f619e38e3201..0c2eb150f4218c6671f8bb6916a7fad804a455f1 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -10,7 +10,7 @@
     - if @events.any?
       .content_list= render @events
     - else
-      %h4.nothing_here_message Projects activity will be displayed here
+      %p.nothing_here_message Projects activity will be displayed here
     .loading.hide
   .side
     = render "projects", projects: @projects
diff --git a/db/fixtures/development/010_groups.rb b/db/fixtures/development/010_groups.rb
new file mode 100644
index 0000000000000000000000000000000000000000..09371b007519c08b657d6a38dd99f1f9345e65b0
--- /dev/null
+++ b/db/fixtures/development/010_groups.rb
@@ -0,0 +1,11 @@
+Group.seed(:id, [
+  { id: 100, name: "Gitlab", path: 'gitlab', owner_id: 1},
+  { id: 101, name: "Rails", path: 'rails', owner_id: 1 },
+  { id: 102, name: "KDE", path: 'kde', owner_id: 1 }
+])
+
+Project.seed(:id, [
+  { id: 10, name: "kdebase", path: "kdebase", owner_id: 1, namespace_id: 102 },
+  { id: 11, name: "kdelibs", path: "kdelibs", owner_id: 1, namespace_id: 102 },
+  { id: 12, name: "amarok",  path: "amarok",  owner_id: 1, namespace_id: 102 }
+])
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 884726266cb170fc3299f56f4743df0b7a1b1f78..108bc303540b905119049dcdf97f2a5b14b7a609 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -24,7 +24,7 @@ describe Group do
   it { should validate_presence_of :owner }
 
   describe :users do
-    it { group.users.should == [] }
+    it { group.users.should == [group.owner] }
   end
 
   describe :human_name do
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 1f1d66150fbca09e88a77818056e36013ebe20cd..d0de4a7b7fb0eafa6a57c39f870f767530f0deff 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -55,9 +55,10 @@ describe Namespace do
   describe :move_dir do
     before do
       @namespace = create :namespace
+      @namespace.stub(path_changed?: true)
     end
 
-    it "should raise error when called directly" do
+    it "should raise error when dirtory exists" do
       expect { @namespace.move_dir }.to raise_error("Already exists")
     end