diff --git a/Gemfile.lock b/Gemfile.lock
index e9be030a8fa1840617d53fcf91481bdc65a1d6bb..62285e69b3fc9c5e87b3c7c2dec8d613bb48b40a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -106,7 +106,7 @@ GEM
       devise (~> 3.2)
     diff-lcs (1.2.5)
     diffy (3.0.3)
-    docile (1.1.1)
+    docile (1.1.5)
     dotenv (0.9.0)
     dropzonejs-rails (0.4.14)
       rails (> 3.1)
@@ -471,7 +471,7 @@ GEM
       redis (>= 3.0.4)
       redis-namespace (>= 1.3.1)
     simple_oauth (0.1.9)
-    simplecov (0.8.2)
+    simplecov (0.9.0)
       docile (~> 1.1.0)
       multi_json
       simplecov-html (~> 0.8.0)
diff --git a/app/assets/javascripts/admin.js.coffee b/app/assets/javascripts/admin.js.coffee
index 6634bb6cc34c1e39eebd7732aefa7a94dee12a8a..a333eed87f24e465ba7e56fb9575207eba6b23d5 100644
--- a/app/assets/javascripts/admin.js.coffee
+++ b/app/assets/javascripts/admin.js.coffee
@@ -46,10 +46,10 @@ class Admin
       modal.hide()
       $('.change-owner-link').show()
 
-    $('li.users_project').bind 'ajax:success', ->
+    $('li.project_member').bind 'ajax:success', ->
       Turbolinks.visit(location.href)
 
-    $('li.users_group').bind 'ajax:success', ->
+    $('li.group_member').bind 'ajax:success', ->
       Turbolinks.visit(location.href)
 
 @Admin = Admin
diff --git a/app/assets/javascripts/groups.js.coffee b/app/assets/javascripts/groups.js.coffee
index 49d6605980b6aaefec873825d601810962d51c04..4b1000f9a6a3e037e771285f5db632d6b869aa28 100644
--- a/app/assets/javascripts/groups.js.coffee
+++ b/app/assets/javascripts/groups.js.coffee
@@ -1,6 +1,6 @@
 class GroupMembers
   constructor: ->
-    $('li.users_group').bind 'ajax:success', ->
+    $('li.group_member').bind 'ajax:success', ->
       $(this).fadeOut()
 
 @GroupMembers = GroupMembers
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 0388997ec69a3945711d41e53615703de8862273..e6d0c9323c1fd4d5792526534cbf042ffeb1d3e2 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -8,7 +8,7 @@ class Admin::GroupsController < Admin::ApplicationController
   end
 
   def show
-    @members = @group.members.order("group_access DESC").page(params[:members_page]).per(30)
+    @members = @group.members.order("access_level DESC").page(params[:members_page]).per(30)
     @projects = @group.projects.page(params[:projects_page]).per(30)
   end
 
@@ -40,7 +40,7 @@ class Admin::GroupsController < Admin::ApplicationController
   end
 
   def project_teams_update
-    @group.add_users(params[:user_ids].split(','), params[:group_access])
+    @group.add_users(params[:user_ids].split(','), params[:access_level])
 
     redirect_to [:admin, @group], notice: 'Users were successfully added.'
   end
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index 1c7c09d0cd46af0d147de6897e9e171d12c5e1de..2f0d344802f2caf0e283b24daafd4974da7b4ab4 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -16,10 +16,10 @@ class Admin::ProjectsController < Admin::ApplicationController
 
   def show
     if @group
-      @group_members = @group.members.order("group_access DESC").page(params[:group_members_page]).per(30)
+      @group_members = @group.members.order("access_level DESC").page(params[:group_members_page]).per(30)
     end
 
-    @project_members = @project.users_projects.page(params[:project_members_page]).per(30)
+    @project_members = @project.project_members.page(params[:project_members_page]).per(30)
   end
 
   def transfer
diff --git a/app/controllers/users_groups_controller.rb b/app/controllers/groups/group_members_controller.rb
similarity index 73%
rename from app/controllers/users_groups_controller.rb
rename to app/controllers/groups/group_members_controller.rb
index a35a12a866bb8bafe50cacbd8dca81900ddcd2dc..63c05d4f33b12192540263c52d29e4b6d0b63c68 100644
--- a/app/controllers/users_groups_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -1,4 +1,4 @@
-class UsersGroupsController < ApplicationController
+class Groups::GroupMembersController < ApplicationController
   before_filter :group
 
   # Authorize
@@ -7,18 +7,18 @@ class UsersGroupsController < ApplicationController
   layout 'group'
 
   def create
-    @group.add_users(params[:user_ids].split(','), params[:group_access])
+    @group.add_users(params[:user_ids].split(','), params[:access_level])
 
     redirect_to members_group_path(@group), notice: 'Users were successfully added.'
   end
 
   def update
-    @member = @group.users_groups.find(params[:id])
+    @member = @group.group_members.find(params[:id])
     @member.update_attributes(member_params)
   end
 
   def destroy
-    @users_group = @group.users_groups.find(params[:id])
+    @users_group = @group.group_members.find(params[:id])
     if can?(current_user, :destroy, @users_group)  # May fail if last owner.
       @users_group.destroy
       respond_to do |format|
@@ -43,6 +43,6 @@ class UsersGroupsController < ApplicationController
   end
 
   def member_params
-    params.require(:users_group).permit(:group_access, :user_id)
+    params.require(:group_member).permit(:access_level, :user_id)
   end
 end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index ddde90d3ee0c10f9dedd762801c3b92549fb4005..36222758eb24611ef6f8facd34c989afcdc30ee3 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -65,15 +65,15 @@ class GroupsController < ApplicationController
 
   def members
     @project = group.projects.find(params[:project_id]) if params[:project_id]
-    @members = group.users_groups
+    @members = group.group_members
 
     if params[:search].present?
       users = group.users.search(params[:search]).to_a
       @members = @members.where(user_id: users)
     end
 
-    @members = @members.order('group_access DESC').page(params[:page]).per(50)
-    @users_group = UsersGroup.new
+    @members = @members.order('access_level DESC').page(params[:page]).per(50)
+    @users_group = GroupMember.new
   end
 
   def edit
diff --git a/app/controllers/profiles/groups_controller.rb b/app/controllers/profiles/groups_controller.rb
index 9a4d088651e42a855d8f0d268aa92dc64d5f3084..ce9dd50df67ebb525f0def5956e5ab1fa20f49ec 100644
--- a/app/controllers/profiles/groups_controller.rb
+++ b/app/controllers/profiles/groups_controller.rb
@@ -2,11 +2,11 @@ class Profiles::GroupsController < ApplicationController
   layout "profile"
 
   def index
-    @user_groups = current_user.users_groups.page(params[:page]).per(20)
+    @user_groups = current_user.group_members.page(params[:page]).per(20)
   end
 
   def leave
-    @users_group = group.users_groups.where(user_id: current_user.id).first
+    @users_group = group.group_members.where(user_id: current_user.id).first
     if can?(current_user, :destroy, @users_group)
       @users_group.destroy
       redirect_to(profile_groups_path, info: "You left #{group.name} group.")
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index 5c492aeb49d1a7043fb2569f353092a31fcef4fe..638d1f9789bed61dcd3a2abb93abe218f795f332 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -3,8 +3,8 @@ class Profiles::NotificationsController < ApplicationController
 
   def show
     @notification = current_user.notification
-    @users_projects = current_user.users_projects
-    @users_groups = current_user.users_groups
+    @project_members = current_user.project_members
+    @group_members = current_user.group_members
   end
 
   def update
@@ -14,13 +14,13 @@ class Profiles::NotificationsController < ApplicationController
                current_user.notification_level = params[:notification_level]
                current_user.save
              elsif type == 'group'
-               users_group = current_user.users_groups.find(params[:notification_id])
+               users_group = current_user.group_members.find(params[:notification_id])
                users_group.notification_level = params[:notification_level]
                users_group.save
              else
-               users_project = current_user.users_projects.find(params[:notification_id])
-               users_project.notification_level = params[:notification_level]
-               users_project.save
+               project_member = current_user.project_members.find(params[:notification_id])
+               project_member.notification_level = params[:notification_level]
+               project_member.save
              end
   end
 end
diff --git a/app/controllers/projects/team_members_controller.rb b/app/controllers/projects/team_members_controller.rb
index 1de5bac9ee827d3ecc3f0663af96181c9a018e7c..7bb799eba64584de61014cc6f0f08d9a6c435e20 100644
--- a/app/controllers/projects/team_members_controller.rb
+++ b/app/controllers/projects/team_members_controller.rb
@@ -6,17 +6,17 @@ class Projects::TeamMembersController < Projects::ApplicationController
 
   def index
     @group = @project.group
-    @users_projects = @project.users_projects.order('project_access DESC')
+    @project_members = @project.project_members.order('access_level DESC')
   end
 
   def new
-    @user_project_relation = project.users_projects.new
+    @user_project_relation = project.project_members.new
   end
 
   def create
     users = User.where(id: params[:user_ids].split(','))
 
-    @project.team << [users, params[:project_access]]
+    @project.team << [users, params[:access_level]]
 
     if params[:redirect_to]
       redirect_to params[:redirect_to]
@@ -26,7 +26,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
   end
 
   def update
-    @user_project_relation = project.users_projects.find_by(user_id: member)
+    @user_project_relation = project.project_members.find_by(user_id: member)
     @user_project_relation.update_attributes(member_params)
 
     unless @user_project_relation.valid?
@@ -36,7 +36,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
   end
 
   def destroy
-    @user_project_relation = project.users_projects.find_by(user_id: member)
+    @user_project_relation = project.project_members.find_by(user_id: member)
     @user_project_relation.destroy
 
     respond_to do |format|
@@ -46,7 +46,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
   end
 
   def leave
-    project.users_projects.find_by(user_id: current_user).destroy
+    project.project_members.find_by(user_id: current_user).destroy
 
     respond_to do |format|
       format.html { redirect_to :back }
@@ -69,6 +69,6 @@ class Projects::TeamMembersController < Projects::ApplicationController
   end
 
   def member_params
-    params.require(:team_member).permit(:user_id, :project_access)
+    params.require(:project_member).permit(:user_id, :access_level)
   end
 end
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index 26898bad493283c69308770ac095a60534cb41fa..c81bb51583af82d3a012f21a025d31bd2444e933 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -19,10 +19,8 @@ class ProjectsFinder
         # Return ALL group projects
         group.projects
       else
-        projects_members = UsersProject.where(
-          project_id: group.projects,
-          user_id: current_user
-        )
+        projects_members = ProjectMember.in_projects(group.projects).
+          with_user(current_user)
 
         if projects_members.any?
           # User is a project member
@@ -34,7 +32,7 @@ class ProjectsFinder
           #
           group.projects.where(
             "projects.id IN (?) OR projects.visibility_level IN (?)",
-            projects_members.pluck(:project_id),
+            projects_members.pluck(:source_id),
             Project.public_and_internal_levels
           )
         else
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index c2c9301cc170a5f5d372ff7861e17219b8a44e51..07938b8065d819f9a2e5dad92ea503ae4bedb4aa 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -187,13 +187,6 @@ module ApplicationHelper
     end
   end
 
-  def first_line(str)
-    lines = str.split("\n")
-    line = lines.first
-    line += "..." if lines.size > 1
-    line
-  end
-
   def broadcast_message
     BroadcastMessage.current
   end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index a4f93689a7b7040cca976ca64b103121557f5bdf..6f738764b0e5f5e239a70d970393cc3ee524129d 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -136,7 +136,7 @@ module EventsHelper
   end
 
   def event_note(text)
-    text = first_line(text)
+    text = first_line_in_markdown(text)
     text = truncate(text, length: 150)
     sanitize(markdown(text), tags: %w(a img b pre p))
   end
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index e4aa90154fb4ebd299be3216962b591be437eb50..d269323542f5731787868488d1f42c1708d73606 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -51,6 +51,14 @@ module GitlabMarkdownHelper
     @markdown.render(text).html_safe
   end
 
+  def first_line_in_markdown(text)
+    line = text.split("\n").detect do |i|
+      i.present? && markdown(i).present?
+    end
+    line += '...' unless line.nil?
+    line
+  end
+
   def render_wiki_content(wiki_page)
     if wiki_page.format == :markdown
       markdown(wiki_page.content)
diff --git a/app/mailers/emails/groups.rb b/app/mailers/emails/groups.rb
index 1654fc55bca8c57cc1167bd3e7628d7d73c9b563..8c09389985e2f54219c6fb76931a12fcecbdacdd 100644
--- a/app/mailers/emails/groups.rb
+++ b/app/mailers/emails/groups.rb
@@ -1,7 +1,7 @@
 module Emails
   module Groups
     def group_access_granted_email(user_group_id)
-      @membership = UsersGroup.find(user_group_id)
+      @membership = GroupMember.find(user_group_id)
       @group = @membership.group
       @target_url = group_url(@group)
       mail(to: @membership.user.email,
diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
index 6b13a1d746d35cf20533b4d2237ee80f5d48e89c..d6edfd7059ff46f66bbad1a493554c100d6e0b31 100644
--- a/app/mailers/emails/projects.rb
+++ b/app/mailers/emails/projects.rb
@@ -1,10 +1,10 @@
 module Emails
   module Projects
     def project_access_granted_email(user_project_id)
-      @users_project = UsersProject.find user_project_id
-      @project = @users_project.project
+      @project_member = ProjectMember.find user_project_id
+      @project = @project_member.project
       @target_url = project_url(@project)
-      mail(to: @users_project.user.email,
+      mail(to: @project_member.user.email,
            subject: subject("Access to project was granted"))
     end
 
diff --git a/app/models/ability.rb b/app/models/ability.rb
index f1d57de63bb00bfeff8c8d71a75d47d581d1951c..716a23a4284189af00b6c636d4e32f12da548617 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -14,7 +14,7 @@ class Ability
       when "MergeRequest" then merge_request_abilities(user, subject)
       when "Group" then group_abilities(user, subject)
       when "Namespace" then namespace_abilities(user, subject)
-      when "UsersGroup" then users_group_abilities(user, subject)
+      when "GroupMember" then users_group_abilities(user, subject)
       else []
       end.concat(global_abilities(user))
     end
diff --git a/app/models/concerns/notifiable.rb b/app/models/concerns/notifiable.rb
index 722f375e71dce0b2b8ea568f87bb4a1cd9f7967b..d7dcd97911dd4825987855a38d5723e6550180d4 100644
--- a/app/models/concerns/notifiable.rb
+++ b/app/models/concerns/notifiable.rb
@@ -1,6 +1,6 @@
 # == Notifiable concern
 #
-# Contains notification functionality shared between UsersProject and UsersGroup
+# Contains notification functionality
 #
 module Notifiable
   extend ActiveSupport::Concern
diff --git a/app/models/group.rb b/app/models/group.rb
index 66239f7fe6f233320a65059247fa489de11f259a..b8ed3b8ac73bffb61499d65098da8dc6c4ddaa31 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -17,8 +17,8 @@ require 'carrierwave/orm/activerecord'
 require 'file_size_validator'
 
 class Group < Namespace
-  has_many :users_groups, dependent: :destroy
-  has_many :users, through: :users_groups
+  has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember'
+  has_many :users, through: :group_members
 
   validate :avatar_type, if: ->(user) { user.avatar_changed? }
   validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
@@ -30,22 +30,22 @@ class Group < Namespace
   end
 
   def owners
-    @owners ||= users_groups.owners.map(&:user)
+    @owners ||= group_members.owners.map(&:user)
   end
 
-  def add_users(user_ids, group_access)
+  def add_users(user_ids, access_level)
     user_ids.compact.each do |user_id|
-      user = self.users_groups.find_or_initialize_by(user_id: user_id)
-      user.update_attributes(group_access: group_access)
+      user = self.group_members.find_or_initialize_by(user_id: user_id)
+      user.update_attributes(access_level: access_level)
     end
   end
 
-  def add_user(user, group_access)
-    self.users_groups.create(user_id: user.id, group_access: group_access)
+  def add_user(user, access_level)
+    self.group_members.create(user_id: user.id, access_level: access_level)
   end
 
   def add_owner(user)
-    self.add_user(user, UsersGroup::OWNER)
+    self.add_user(user, Gitlab::Access::OWNER)
   end
 
   def has_owner?(user)
@@ -61,7 +61,7 @@ class Group < Namespace
   end
 
   def members
-    users_groups
+    group_members
   end
 
   def avatar_type
diff --git a/app/models/project_hook.rb b/app/models/hooks/project_hook.rb
similarity index 100%
rename from app/models/project_hook.rb
rename to app/models/hooks/project_hook.rb
diff --git a/app/models/service_hook.rb b/app/models/hooks/service_hook.rb
similarity index 100%
rename from app/models/service_hook.rb
rename to app/models/hooks/service_hook.rb
diff --git a/app/models/system_hook.rb b/app/models/hooks/system_hook.rb
similarity index 100%
rename from app/models/system_hook.rb
rename to app/models/hooks/system_hook.rb
diff --git a/app/models/web_hook.rb b/app/models/hooks/web_hook.rb
similarity index 100%
rename from app/models/web_hook.rb
rename to app/models/hooks/web_hook.rb
diff --git a/app/models/member.rb b/app/models/member.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7dc13c18bf32f444705bee9493dd484ecd03d705
--- /dev/null
+++ b/app/models/member.rb
@@ -0,0 +1,20 @@
+class Member < ActiveRecord::Base
+  include Notifiable
+  include Gitlab::Access
+
+  belongs_to :user
+  belongs_to :source, polymorphic: true
+
+  validates :user, presence: true
+  validates :source, presence: true
+  validates :user_id, uniqueness: { scope: [:source_type, :source_id], message: "already exists in source" }
+  validates :access_level, inclusion: { in: Gitlab::Access.all_values }, presence: true
+
+  scope :guests, -> { where(access_level: GUEST) }
+  scope :reporters, -> { where(access_level: REPORTER) }
+  scope :developers, -> { where(access_level: DEVELOPER) }
+  scope :masters,  -> { where(access_level: MASTER) }
+  scope :owners,  -> { where(access_level: OWNER) }
+
+  delegate :name, :username, :email, to: :user, prefix: true
+end
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e72393c42786ea10de7fb6a02f315fba9f173024
--- /dev/null
+++ b/app/models/members/group_member.rb
@@ -0,0 +1,43 @@
+class GroupMember < Member
+  SOURCE_TYPE = 'Namespace'
+
+  belongs_to :group, class_name: 'Group', foreign_key: 'source_id'
+
+  # Make sure group member points only to group as it source
+  default_value_for :source_type, SOURCE_TYPE
+  default_value_for :notification_level, Notification::N_GLOBAL
+  validates_format_of :source_type, with: /\ANamespace\z/
+  default_scope { where(source_type: SOURCE_TYPE) }
+
+  scope :with_group, ->(group) { where(source_id: group.id) }
+  scope :with_user, ->(user) { where(user_id: user.id) }
+
+  after_create :notify_create
+  after_update :notify_update
+
+  def self.access_level_roles
+    Gitlab::Access.options_with_owner
+  end
+
+  def group
+    source
+  end
+
+  def access_field
+    access_level
+  end
+
+  def notify_create
+    notification_service.new_group_member(self)
+  end
+
+  def notify_update
+    if access_level_changed?
+      notification_service.update_group_member(self)
+    end
+  end
+
+  def notification_service
+    NotificationService.new
+  end
+end
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f14900ad3e638364672e264c1ce43275eaeb34fe
--- /dev/null
+++ b/app/models/members/project_member.rb
@@ -0,0 +1,137 @@
+class ProjectMember < Member
+  SOURCE_TYPE = 'Project'
+
+  include Gitlab::ShellAdapter
+
+  belongs_to :project, class_name: 'Project', foreign_key: 'source_id'
+
+
+  # Make sure project member points only to project as it source
+  default_value_for :source_type, SOURCE_TYPE
+  default_value_for :notification_level, Notification::N_GLOBAL
+  validates_format_of :source_type, with: /\AProject\z/
+  default_scope { where(source_type: SOURCE_TYPE) }
+
+  after_create :post_create_hook
+  after_update :post_update_hook
+  after_destroy :post_destroy_hook
+
+  scope :in_project, ->(project) { where(source_id: project.id) }
+  scope :in_projects, ->(projects) { where(source_id: projects.pluck(:id)) }
+  scope :with_user, ->(user) { where(user_id: user.id) }
+
+  class << self
+
+    # Add users to project teams with passed access option
+    #
+    # access can be an integer representing a access code
+    # or symbol like :master representing role
+    #
+    # Ex.
+    #   add_users_into_projects(
+    #     project_ids,
+    #     user_ids,
+    #     ProjectMember::MASTER
+    #   )
+    #
+    #   add_users_into_projects(
+    #     project_ids,
+    #     user_ids,
+    #     :master
+    #   )
+    #
+    def add_users_into_projects(project_ids, user_ids, access)
+      access_level = if roles_hash.has_key?(access)
+                       roles_hash[access]
+                     elsif roles_hash.values.include?(access.to_i)
+                       access
+                     else
+                       raise "Non valid access"
+                     end
+
+      ProjectMember.transaction do
+        project_ids.each do |project_id|
+          user_ids.each do |user_id|
+            member = ProjectMember.new(access_level: access_level, user_id: user_id)
+            member.source_id = project_id
+            member.save
+          end
+        end
+      end
+
+      true
+    rescue
+      false
+    end
+
+    def truncate_teams(project_ids)
+      ProjectMember.transaction do
+        members = ProjectMember.where(source_id: project_ids)
+        members.each do |member|
+          member.destroy
+        end
+      end
+
+      true
+    rescue
+      false
+    end
+
+    def truncate_team project
+      truncate_teams [project.id]
+    end
+
+    def roles_hash
+      Gitlab::Access.sym_options
+    end
+
+    def access_roles
+      Gitlab::Access.options
+    end
+  end
+
+  def access_field
+    access_level
+  end
+
+  def owner?
+    project.owner == user
+  end
+
+  def post_create_hook
+    Event.create(
+      project_id: self.project.id,
+      action: Event::JOINED,
+      author_id: self.user.id
+    )
+
+    notification_service.new_team_member(self) unless owner?
+    system_hook_service.execute_hooks_for(self, :create)
+  end
+
+  def post_update_hook
+    notification_service.update_team_member(self) if self.access_level_changed?
+  end
+
+  def post_destroy_hook
+    Event.create(
+      project_id: self.project.id,
+      action: Event::LEFT,
+      author_id: self.user.id
+    )
+
+    system_hook_service.execute_hooks_for(self, :destroy)
+  end
+
+  def notification_service
+    NotificationService.new
+  end
+
+  def system_hook_service
+    SystemHooksService.new
+  end
+
+  def project
+    source
+  end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 114e40983f8b6f10f2e0a7a1a101732281d42ff8..0adedaa8dcddebabba2c65bded62336dcee7bb3d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -79,8 +79,8 @@ class Project < ActiveRecord::Base
   has_many :snippets,           dependent: :destroy, class_name: "ProjectSnippet"
   has_many :hooks,              dependent: :destroy, class_name: "ProjectHook"
   has_many :protected_branches, dependent: :destroy
-  has_many :users_projects, dependent: :destroy
-  has_many :users, through: :users_projects
+  has_many :project_members, dependent: :destroy, as: :source, class_name: 'ProjectMember'
+  has_many :users, through: :project_members
   has_many :deploy_keys_projects, dependent: :destroy
   has_many :deploy_keys, through: :deploy_keys_projects
   has_many :users_star_projects, dependent: :destroy
@@ -353,12 +353,12 @@ class Project < ActiveRecord::Base
 
   def team_member_by_name_or_email(name = nil, email = nil)
     user = users.where("name like ? or email like ?", name, email).first
-    users_projects.where(user: user) if user
+    project_members.where(user: user) if user
   end
 
   # Get Team Member record by user id
   def team_member_by_id(user_id)
-    users_projects.find_by(user_id: user_id)
+    project_members.find_by(user_id: user_id)
   end
 
   def name_with_namespace
@@ -555,7 +555,7 @@ class Project < ActiveRecord::Base
   end
 
   def project_member(user)
-    users_projects.where(user_id: user).first
+    project_members.where(user_id: user).first
   end
 
   def default_branch
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 0bbbd3d00e8b35cde453aa3aed9f4007254c3d86..e2af10c6899817d8d0187777ae7e9eea4bdbbd46 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -32,12 +32,12 @@ class ProjectTeam
   end
 
   def find_tm(user_id)
-    tm = project.users_projects.find_by(user_id: user_id)
+    tm = project.project_members.find_by(user_id: user_id)
 
     # If user is not in project members
     # we should check for group membership
     if group && !tm
-      tm = group.users_groups.find_by(user_id: user_id)
+      tm = group.group_members.find_by(user_id: user_id)
     end
 
     tm
@@ -52,7 +52,7 @@ class ProjectTeam
   end
 
   def add_users_ids(user_ids, access)
-    UsersProject.add_users_into_projects(
+    ProjectMember.add_users_into_projects(
       [project.id],
       user_ids,
       access
@@ -61,7 +61,7 @@ class ProjectTeam
 
   # Remove all users from project team
   def truncate
-    UsersProject.truncate_team(project)
+    ProjectMember.truncate_team(project)
   end
 
   def users
@@ -91,8 +91,8 @@ class ProjectTeam
   def import(source_project)
     target_project = project
 
-    source_team = source_project.users_projects.to_a
-    target_user_ids = target_project.users_projects.pluck(:user_id)
+    source_team = source_project.project_members.to_a
+    target_user_ids = target_project.project_members.pluck(:user_id)
 
     source_team.reject! do |tm|
       # Skip if user already present in team
@@ -102,11 +102,11 @@ class ProjectTeam
     source_team.map! do |tm|
       new_tm = tm.dup
       new_tm.id = nil
-      new_tm.project_id = target_project.id
+      new_tm.source = target_project
       new_tm
     end
 
-    UsersProject.transaction do
+    ProjectMember.transaction do
       source_team.each do |tm|
         tm.save
       end
@@ -135,10 +135,10 @@ class ProjectTeam
 
   def max_tm_access(user_id)
     access = []
-    access << project.users_projects.find_by(user_id: user_id).try(:access_field)
+    access << project.project_members.find_by(user_id: user_id).try(:access_field)
 
     if group
-      access << group.users_groups.find_by(user_id: user_id).try(:access_field)
+      access << group.group_members.find_by(user_id: user_id).try(:access_field)
     end
 
     access.compact.max
@@ -147,8 +147,8 @@ class ProjectTeam
   private
 
   def fetch_members(level = nil)
-    project_members = project.users_projects
-    group_members = group ? group.users_groups : []
+    project_members = project.project_members
+    group_members = group ? group.group_members : []
 
     if level
       project_members = project_members.send(level)
diff --git a/app/models/user.rb b/app/models/user.rb
index 15e56a62a68ddc6327b0dd58131c8f0524a94795..ed3eba4cdf0a22076e3a5bcb06f645d998222e3b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -81,21 +81,23 @@ class User < ActiveRecord::Base
   has_many :emails, dependent: :destroy
 
   # Groups
-  has_many :users_groups, dependent: :destroy
-  has_many :groups, through: :users_groups
-  has_many :owned_groups, -> { where users_groups: { group_access: UsersGroup::OWNER } }, through: :users_groups, source: :group
-  has_many :masters_groups, -> { where users_groups: { group_access: UsersGroup::MASTER } }, through: :users_groups, source: :group
+  has_many :members, dependent: :destroy
+  has_many :project_members, source: 'ProjectMember'
+  has_many :group_members, source: 'GroupMember'
+  has_many :groups, through: :group_members
+  has_many :owned_groups, -> { where members: { access_level: Gitlab::Access::OWNER } }, through: :group_members, source: :group
+  has_many :masters_groups, -> { where members: { access_level: Gitlab::Access::MASTER } }, through: :group_members, source: :group
 
   # Projects
   has_many :groups_projects,          through: :groups, source: :projects
   has_many :personal_projects,        through: :namespace, source: :projects
-  has_many :projects,                 through: :users_projects
+  has_many :projects,                 through: :project_members
   has_many :created_projects,         foreign_key: :creator_id, class_name: 'Project'
   has_many :users_star_projects, dependent: :destroy
   has_many :starred_projects, through: :users_star_projects, source: :project
 
   has_many :snippets,                 dependent: :destroy, foreign_key: :author_id, class_name: "Snippet"
-  has_many :users_projects,           dependent: :destroy
+  has_many :project_members,          dependent: :destroy, class_name: 'ProjectMember'
   has_many :issues,                   dependent: :destroy, foreign_key: :author_id
   has_many :notes,                    dependent: :destroy, foreign_key: :author_id
   has_many :merge_requests,           dependent: :destroy, foreign_key: :author_id
@@ -140,7 +142,7 @@ class User < ActiveRecord::Base
   state_machine :state, initial: :active do
     after_transition any => :blocked do |user, transition|
       # Remove user from all projects and
-      user.users_projects.find_each do |membership|
+      user.project_members.find_each do |membership|
         # skip owned resources
         next if membership.project.owner == user
 
@@ -148,7 +150,7 @@ class User < ActiveRecord::Base
       end
 
       # Remove user from all groups
-      user.users_groups.find_each do |membership|
+      user.group_members.find_each do |membership|
         # skip owned resources
         next if membership.group.last_owner?(user)
 
@@ -175,7 +177,7 @@ class User < ActiveRecord::Base
   scope :in_team, ->(team){ where(id: team.member_ids) }
   scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
   scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
-  scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)') }
+  scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members)') }
   scope :ldap, -> { where(provider:  'ldap') }
 
   scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active  }
@@ -295,7 +297,7 @@ class User < ActiveRecord::Base
 
   # Team membership in authorized projects
   def tm_in_authorized_projects
-    UsersProject.where(project_id: authorized_projects.map(&:id), user_id: self.id)
+    ProjectMember.where(source_id: authorized_projects.map(&:id), user_id: self.id)
   end
 
   def is_admin?
diff --git a/app/models/users_group.rb b/app/models/users_group.rb
deleted file mode 100644
index 270f968ef61c11f7eed47fa10edad559ffc63471..0000000000000000000000000000000000000000
--- a/app/models/users_group.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# == Schema Information
-#
-# Table name: users_groups
-#
-#  id                 :integer          not null, primary key
-#  group_access       :integer          not null
-#  group_id           :integer          not null
-#  user_id            :integer          not null
-#  created_at         :datetime
-#  updated_at         :datetime
-#  notification_level :integer          default(3), not null
-#
-
-class UsersGroup < ActiveRecord::Base
-  include Notifiable
-  include Gitlab::Access
-
-  def self.group_access_roles
-    Gitlab::Access.options_with_owner
-  end
-
-  belongs_to :user
-  belongs_to :group
-
-  scope :guests, -> { where(group_access: GUEST) }
-  scope :reporters, -> { where(group_access: REPORTER) }
-  scope :developers, -> { where(group_access: DEVELOPER) }
-  scope :masters,  -> { where(group_access: MASTER) }
-  scope :owners,  -> { where(group_access: OWNER) }
-
-  scope :with_group, ->(group) { where(group_id: group.id) }
-  scope :with_user, ->(user) { where(user_id: user.id) }
-
-  after_create :notify_create
-  after_update :notify_update
-
-  validates :group_access, inclusion: { in: UsersGroup.group_access_roles.values }, presence: true
-  validates :user_id, presence: true
-  validates :group_id, presence: true
-  validates :user_id, uniqueness: { scope: [:group_id], message: "already exists in group" }
-
-  delegate :name, :username, :email, to: :user, prefix: true
-
-  def access_field
-    group_access
-  end
-
-  def notify_create
-    notification_service.new_group_member(self)
-  end
-
-  def notify_update
-    if group_access_changed?
-      notification_service.update_group_member(self)
-    end
-  end
-
-  def notification_service
-    NotificationService.new
-  end
-end
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
deleted file mode 100644
index 60bdf7a3cfb15278b6d4d2dbba6d0b3b7633d138..0000000000000000000000000000000000000000
--- a/app/models/users_project.rb
+++ /dev/null
@@ -1,152 +0,0 @@
-# == Schema Information
-#
-# Table name: users_projects
-#
-#  id                 :integer          not null, primary key
-#  user_id            :integer          not null
-#  project_id         :integer          not null
-#  created_at         :datetime
-#  updated_at         :datetime
-#  project_access     :integer          default(0), not null
-#  notification_level :integer          default(3), not null
-#
-
-class UsersProject < ActiveRecord::Base
-  include Gitlab::ShellAdapter
-  include Notifiable
-  include Gitlab::Access
-
-  belongs_to :user
-  belongs_to :project
-
-  validates :user, presence: true
-  validates :user_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
-  validates :project_access, inclusion: { in: Gitlab::Access.values }, presence: true
-  validates :project, presence: true
-
-  delegate :name, :username, :email, to: :user, prefix: true
-
-  scope :guests, -> { where(project_access: GUEST) }
-  scope :reporters, -> { where(project_access: REPORTER) }
-  scope :developers, -> { where(project_access: DEVELOPER) }
-  scope :masters,  -> { where(project_access: MASTER) }
-
-  scope :in_project, ->(project) { where(project_id: project.id) }
-  scope :in_projects, ->(projects) { where(project_id: projects.map { |p| p.id }) }
-  scope :with_user, ->(user) { where(user_id: user.id) }
-
-  after_create :post_create_hook
-  after_update :post_update_hook
-  after_destroy :post_destroy_hook
-
-  class << self
-
-    # Add users to project teams with passed access option
-    #
-    # access can be an integer representing a access code
-    # or symbol like :master representing role
-    #
-    # Ex.
-    #   add_users_into_projects(
-    #     project_ids,
-    #     user_ids,
-    #     UsersProject::MASTER
-    #   )
-    #
-    #   add_users_into_projects(
-    #     project_ids,
-    #     user_ids,
-    #     :master
-    #   )
-    #
-    def add_users_into_projects(project_ids, user_ids, access)
-      project_access = if roles_hash.has_key?(access)
-                         roles_hash[access]
-                       elsif roles_hash.values.include?(access.to_i)
-                         access
-                       else
-                         raise "Non valid access"
-                       end
-
-      UsersProject.transaction do
-        project_ids.each do |project_id|
-          user_ids.each do |user_id|
-            users_project = UsersProject.new(project_access: project_access, user_id: user_id)
-            users_project.project_id = project_id
-            users_project.save
-          end
-        end
-      end
-
-      true
-    rescue
-      false
-    end
-
-    def truncate_teams(project_ids)
-      UsersProject.transaction do
-        users_projects = UsersProject.where(project_id: project_ids)
-        users_projects.each do |users_project|
-          users_project.destroy
-        end
-      end
-
-      true
-    rescue
-      false
-    end
-
-    def truncate_team project
-      truncate_teams [project.id]
-    end
-
-    def roles_hash
-      Gitlab::Access.sym_options
-    end
-
-    def access_roles
-      Gitlab::Access.options
-    end
-  end
-
-  def access_field
-    project_access
-  end
-
-  def owner?
-    project.owner == user
-  end
-
-  def post_create_hook
-    Event.create(
-      project_id: self.project.id,
-      action: Event::JOINED,
-      author_id: self.user.id
-    )
-
-    notification_service.new_team_member(self) unless owner?
-    system_hook_service.execute_hooks_for(self, :create)
-  end
-
-  def post_update_hook
-    notification_service.update_team_member(self) if self.project_access_changed?
-  end
-
-  def post_destroy_hook
-    Event.create(
-      project_id: self.project.id,
-      action: Event::LEFT,
-      author_id: self.user.id
-    )
-
-    system_hook_service.execute_hooks_for(self, :destroy)
-  end
-
-  def notification_service
-    NotificationService.new
-  end
-
-  def system_hook_service
-    SystemHooksService.new
-  end
-end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 36d33e0d7ca85988a97f4fb4d4ce3ab2adba4213..fe39f83b400286cb481ef9dbb9c834180283df32 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -157,12 +157,12 @@ class NotificationService
     end
   end
 
-  def new_team_member(users_project)
-    mailer.project_access_granted_email(users_project.id)
+  def new_team_member(project_member)
+    mailer.project_access_granted_email(project_member.id)
   end
 
-  def update_team_member(users_project)
-    mailer.project_access_granted_email(users_project.id)
+  def update_team_member(project_member)
+    mailer.project_access_granted_email(project_member.id)
   end
 
   def new_group_member(users_group)
@@ -186,20 +186,20 @@ class NotificationService
 
   # Get project users with WATCH notification level
   def project_watchers(project)
-    project_members = users_project_notification(project)
+    project_members = project_member_notification(project)
 
-    users_with_project_level_global = users_project_notification(project, Notification::N_GLOBAL)
+    users_with_project_level_global = project_member_notification(project, Notification::N_GLOBAL)
     users_with_group_level_global = users_group_notification(project, Notification::N_GLOBAL)
     users = users_with_global_level_watch([users_with_project_level_global, users_with_group_level_global].flatten.uniq)
 
-    users_with_project_setting = select_users_project_setting(project, users_with_project_level_global, users)
+    users_with_project_setting = select_project_member_setting(project, users_with_project_level_global, users)
     users_with_group_setting = select_users_group_setting(project, project_members, users_with_group_level_global, users)
 
     User.where(id: users_with_project_setting.concat(users_with_group_setting).uniq).to_a
   end
 
-  def users_project_notification(project, notification_level=nil)
-    project_members = project.users_projects
+  def project_member_notification(project, notification_level=nil)
+    project_members = project.project_members
 
     if notification_level
       project_members.where(notification_level: notification_level).pluck(:user_id)
@@ -210,7 +210,7 @@ class NotificationService
 
   def users_group_notification(project, notification_level)
     if project.group
-      project.group.users_groups.where(notification_level: notification_level).pluck(:user_id)
+      project.group.group_members.where(notification_level: notification_level).pluck(:user_id)
     else
       []
     end
@@ -224,8 +224,8 @@ class NotificationService
   end
 
   # Build a list of users based on project notifcation settings
-  def select_users_project_setting(project, global_setting, users_global_level_watch)
-    users = users_project_notification(project, Notification::N_WATCH)
+  def select_project_member_setting(project, global_setting, users_global_level_watch)
+    users = project_member_notification(project, Notification::N_WATCH)
 
     # If project setting is global, add to watch list if global setting is watch
     global_setting.each do |user_id|
@@ -267,10 +267,10 @@ class NotificationService
     users.reject do |user|
       next user.notification.disabled? unless project
 
-      tm = project.users_projects.find_by(user_id: user.id)
+      tm = project.project_members.find_by(user_id: user.id)
 
       if !tm && project.group
-        tm = project.group.users_groups.find_by(user_id: user.id)
+        tm = project.group.group_members.find_by(user_id: user.id)
       end
 
       # reject users who globally disabled notification and has no membership
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 2bfb0f28d958b40184b29d88f333f52e686273f0..12386792aabd3a047e066fb52944c0bc52971196 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -42,10 +42,7 @@ module Projects
         system_hook_service.execute_hooks_for(@project, :create)
 
         unless @project.group
-          @project.users_projects.create(
-            project_access: UsersProject::MASTER,
-            user: current_user
-          )
+          @project.team << [current_user, :master]
         end
 
         @project.update_column(:last_activity_at, @project.created_at)
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index 66f0a02f0af230c0c5b39ac37ad87500da661fcd..a59311bf942da43bdea4c04524ba2e43ca117be4 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -27,7 +27,7 @@ module Projects
             #First save the DB entries as they can be rolled back if the repo fork fails
             project.build_forked_project_link(forked_to_project_id: project.id, forked_from_project_id: @from_project.id)
             if project.save
-              project.users_projects.create(project_access: UsersProject::MASTER, user: current_user)
+              project.team << [current_user, :master]
             end
             #Now fork the repo
             unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path)
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index bfc725e5eb5daee5580f41b15978769a4437a4bd..a6b68749a711328cb4bb12e8e9e87fec028959ff 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -50,14 +50,14 @@ class SystemHooksService
         email: model.email,
         user_id: model.id
       })
-    when UsersProject
+    when ProjectMember
       data.merge!({
         project_name: model.project.name,
         project_path: model.project.path,
-        project_id: model.project_id,
+        project_id: model.project.id,
         user_name: model.user.name,
         user_email: model.user.email,
-        project_access: model.human_access,
+        access_level: model.human_access,
         project_visibility: Project.visibility_levels.key(model.project.visibility_level_field).downcase
       })
     end
@@ -65,7 +65,7 @@ class SystemHooksService
 
   def build_event_name(model, event)
     case model
-    when UsersProject
+    when ProjectMember
       return "user_add_to_team"      if event == :create
       return "user_remove_from_team" if event == :destroy
     else
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 8634f46053d1d29c610a15890f85c21257e8b5b0..d59d2a23179ccc8207de602dad3f7040938cec3e 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -62,7 +62,7 @@
           %div
             = users_select_tag(:user_ids, multiple: true)
           %div.prepend-top-10
-            = select_tag :group_access, options_for_select(UsersGroup.group_access_roles), class: "project-access-select select2"
+            = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2"
           %hr
           = submit_tag 'Add users into group', class: "btn btn-create"
     .panel.panel-default
@@ -70,7 +70,7 @@
         %h3.panel-title
           Members
           %span.badge
-            #{@group.users_groups.count}
+            #{@group.group_members.count}
       %ul.well-list.group-users-list
         - @members.each do |member|
           - user = member.user
@@ -80,7 +80,7 @@
                 = link_to user.name, admin_user_path(user)
             %span.pull-right.light
               = member.human_access
-              = link_to group_users_group_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
+              = link_to group_group_members_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
                 %i.icon-minus.icon-white
       .panel-footer
         = paginate @members, param_name: 'members_page', theme: 'gitlab'
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 66a72449f40fcbbb45d3e68a17f72c4cf82c01af..8413f0cb7f93ffb7913aa366b4021de15cb4621e 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -95,13 +95,13 @@
       .panel.panel-default
         .panel-heading
           %strong #{@group.name}
-          group members (#{@group.users_groups.count})
+          group members (#{@group.group_members.count})
           .pull-right
             = link_to admin_group_path(@group), class: 'btn btn-small' do
               %i.icon-edit
         %ul.well-list
           - @group_members.each do |member|
-            = render 'users_groups/users_group', member: member, show_controls: false
+            = render 'groups/group_members/group_member', member: member, show_controls: false
         .panel-footer
           = paginate @group_members, param_name: 'group_members_page', theme: 'gitlab'
 
@@ -115,17 +115,17 @@
             %i.icon-edit
             Manage Access
       %ul.well-list.team_members
-        - @project_members.each do |users_project|
-          - user = users_project.user
-          %li.users_project
+        - @project_members.each do |project_member|
+          - user = project_member.user
+          %li.project_member
             .list-item-name
               %strong
                 = link_to user.name, admin_user_path(user)
             .pull-right
-              - if users_project.owner?
+              - if project_member.owner?
                 %span.light Owner
               - else
-                %span.light= users_project.human_access
+                %span.light= project_member.human_access
                 = link_to project_team_member_path(@project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, remote: true, class: "btn btn-small btn-remove" do
                   %i.icon-remove
       .panel-footer
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index f60d40b53348fcd3e44466a76fa870cf48fdcd7e..a172d12edb17381fe00f3dd38b4eb36ced78ee99 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -159,13 +159,13 @@
         = render 'users/profile', user: @user
 
   #groups.tab-pane
-    - if @user.users_groups.present?
+    - if @user.group_members.present?
       .panel.panel-default
         .panel-heading Groups:
         %ul.well-list
-          - @user.users_groups.each do |user_group|
+          - @user.group_members.each do |user_group|
             - group = user_group.group
-            %li.users_group
+            %li.group_member
               %span{class: ("list-item-name" unless user_group.owner?)}
                 %strong= link_to group.name, admin_group_path(group)
               .pull-right
@@ -197,7 +197,7 @@
           %ul.well-list
             - @joined_projects.sort_by(&:name_with_namespace).each do |project|
               - tm = project.team.find_tm(@user.id)
-              %li.users_project
+              %li.project_member
                 .list-item-name
                   = link_to admin_project_path(project), class: dom_class(project) do
                     = project.name_with_namespace
diff --git a/app/views/events/_event_issue.atom.haml b/app/views/events/_event_issue.atom.haml
index 030c961c3554767ace16bd949eea59e83068d653..eba2b63797a8135b8cf2248b0cbad23d4b692925 100644
--- a/app/views/events/_event_issue.atom.haml
+++ b/app/views/events/_event_issue.atom.haml
@@ -1,2 +1,3 @@
 %div{xmlns: "http://www.w3.org/1999/xhtml"}
-  = markdown issue.description
+  - if issue.description.present?
+    = markdown issue.description
diff --git a/app/views/events/_event_merge_request.atom.haml b/app/views/events/_event_merge_request.atom.haml
index ab3a485e908c2bcd3df932a2ea40e0701bc0278a..0aea2d17d6531179d3b75c76a256ee63f348f4a1 100644
--- a/app/views/events/_event_merge_request.atom.haml
+++ b/app/views/events/_event_merge_request.atom.haml
@@ -1,2 +1,3 @@
 %div{xmlns: "http://www.w3.org/1999/xhtml"}
-  = markdown merge_request.description
+  - if merge_request.description.present?
+    = markdown merge_request.description
diff --git a/app/views/groups/_new_group_member.html.haml b/app/views/groups/_new_group_member.html.haml
index 3ab9276c541ea55bb4fd3ad791157e326d6b1ae2..e590ddbf931feb9aa1c6a0891ef6cb7cc23f2ed4 100644
--- a/app/views/groups/_new_group_member.html.haml
+++ b/app/views/groups/_new_group_member.html.haml
@@ -1,11 +1,11 @@
-= form_for @users_group, url: group_users_groups_path(@group), html: { class: 'form-horizontal users-group-form' } do |f|
+= form_for @users_group, url: group_group_members_path(@group), html: { class: 'form-horizontal users-group-form' } do |f|
   .form-group
     = f.label :user_ids, "People", class: 'control-label'
     .col-sm-10= users_select_tag(:user_ids, multiple: true, class: 'input-large')
 
   .form-group
-    = f.label :group_access, "Group Access", class: 'control-label'
-    .col-sm-10= select_tag :group_access, options_for_select(UsersGroup.group_access_roles, @users_group.group_access), class: "project-access-select select2"
+    = f.label :access_level, "Group Access", class: 'control-label'
+    .col-sm-10= select_tag :access_level, options_for_select(GroupMember.access_level_roles, @users_group.access_level), class: "project-access-select select2"
 
   .form-actions
     = f.submit 'Add users into group', class: "btn btn-create"
diff --git a/app/views/users_groups/_users_group.html.haml b/app/views/groups/group_members/_group_member.html.haml
similarity index 78%
rename from app/views/users_groups/_users_group.html.haml
rename to app/views/groups/group_members/_group_member.html.haml
index ad363eaba23c0f2df49bed1128e24b36d4b00a5b..099e50a384ee837b311dda53decc647631907fa0 100644
--- a/app/views/users_groups/_users_group.html.haml
+++ b/app/views/groups/group_members/_group_member.html.haml
@@ -21,11 +21,11 @@
             = link_to leave_profile_group_path(@group), data: { confirm: leave_group_message(@group.name)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
               %i.icon-minus.icon-white
           - else
-            = link_to group_users_group_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
+            = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
               %i.icon-minus.icon-white
 
     .edit-member.hide.js-toggle-content
       = form_for [@group, member], remote: true do |f|
         .alert.prepend-top-20
-          = f.select :group_access, options_for_select(UsersGroup.group_access_roles, member.group_access)
+          = f.select :access_level, options_for_select(GroupMember.access_level_roles, member.access_level)
           = f.submit 'Save', class: 'btn btn-save btn-small'
diff --git a/app/views/users_groups/update.js.haml b/app/views/groups/group_members/update.js.haml
similarity index 100%
rename from app/views/users_groups/update.js.haml
rename to app/views/groups/group_members/update.js.haml
diff --git a/app/views/groups/members.html.haml b/app/views/groups/members.html.haml
index 19819c96124f027c2fab4cb0bf2e6ec1957a0535..ebf407d4ef18f7ad995fd6a051947c0e48175fb6 100644
--- a/app/views/groups/members.html.haml
+++ b/app/views/groups/members.html.haml
@@ -32,7 +32,7 @@
       (#{@members.total_count})
   %ul.well-list
     - @members.each do |member|
-      = render 'users_groups/users_group', member: member, show_roles: show_roles, show_controls: true
+      = render 'groups/group_members/group_member', member: member, show_roles: show_roles, show_controls: true
 = paginate @members, theme: 'gitlab'
 
 :coffeescript
diff --git a/app/views/notify/project_access_granted_email.html.haml b/app/views/notify/project_access_granted_email.html.haml
index ce34f825358a45c4e1def28363bba54fbe2c791a..4596205f39bc55dbff7115ca778e41ff3a416af3 100644
--- a/app/views/notify/project_access_granted_email.html.haml
+++ b/app/views/notify/project_access_granted_email.html.haml
@@ -1,5 +1,5 @@
 %p
-  = "You have been granted #{@users_project.human_access} access to project"
+  = "You have been granted #{@project_member.human_access} access to project"
 %p
   = link_to project_url(@project) do
     = @project.name_with_namespace
diff --git a/app/views/notify/project_access_granted_email.text.erb b/app/views/notify/project_access_granted_email.text.erb
index 66c57def37564f1d3bc041da9751dd4abc5c9092..de24feb802f6dc2542ce366863424ee7cd24747c 100644
--- a/app/views/notify/project_access_granted_email.text.erb
+++ b/app/views/notify/project_access_granted_email.text.erb
@@ -1,4 +1,4 @@
 
-You have been granted <%= @users_project.human_access %> access to project <%= @project.name_with_namespace %>
+You have been granted <%= @project_member.human_access %> access to project <%= @project.name_with_namespace %>
 
 <%= url_for(project_url(@project)) %>
diff --git a/app/views/profiles/notifications/_settings.html.haml b/app/views/profiles/notifications/_settings.html.haml
index 218d51d31afd28c26a7123062a81cf26247d2151..940c553d1ba4f210068241176246315f66545b69 100644
--- a/app/views/profiles/notifications/_settings.html.haml
+++ b/app/views/profiles/notifications/_settings.html.haml
@@ -6,7 +6,7 @@
       = notification_icon(notification)
 
   %span.str-truncated
-    - if membership.kind_of? UsersGroup
+    - if membership.kind_of? GroupMember
       = link_to membership.group.name, membership.group
     - else
       = link_to_project(membership.project)
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index efe9c03219065548ebae1dfc78661fcaf8c08483..f84de4430ccae6c96ea594de95a33ffe4bec3f0b 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -39,13 +39,13 @@
   .col-md-6
     %h4 Groups:
     %ul.bordered-list
-      - @users_groups.each do |users_group|
+      - @group_members.each do |users_group|
         - notification = Notification.new(users_group)
         = render 'settings', type: 'group', membership: users_group, notification: notification
 
   .col-md-6
     %h4 Projects:
     %ul.bordered-list
-      - @users_projects.each do |users_project|
-        - notification = Notification.new(users_project)
-        = render 'settings', type: 'project', membership: users_project, notification: notification
+      - @project_members.each do |project_member|
+        - notification = Notification.new(project_member)
+        = render 'settings', type: 'project', membership: project_member, notification: notification
diff --git a/app/views/projects/team_members/_form.html.haml b/app/views/projects/team_members/_form.html.haml
index 5998e4c6b42babadacfbc8ceaaaa8d101ba8983c..2bf61fa12bb1c26c17b62f7c5f6aea33573aeeb9 100644
--- a/app/views/projects/team_members/_form.html.haml
+++ b/app/views/projects/team_members/_form.html.haml
@@ -1,7 +1,7 @@
 %h3.page-title
   New project member(s)
 
-= form_for @user_project_relation, as: :team_member, url: project_team_members_path(@project), html: { class: "form-horizontal users-project-form" } do |f|
+= form_for @user_project_relation, as: :project_member, url: project_team_members_path(@project), html: { class: "form-horizontal users-project-form" } do |f|
   -if @user_project_relation.errors.any?
     .alert.alert-danger
       %ul
@@ -16,8 +16,8 @@
 
   %p 2. Set access level for them
   .form-group
-    = f.label :project_access, "Project Access", class: 'control-label'
-    .col-sm-10= select_tag :project_access, options_for_select(Gitlab::Access.options, @user_project_relation.project_access), class: "project-access-select select2"
+    = f.label :access_level, "Project Access", class: 'control-label'
+    .col-sm-10= select_tag :access_level, options_for_select(Gitlab::Access.options, @user_project_relation.access_level), class: "project-access-select select2"
 
   .form-actions
     = f.submit 'Add users', class: "btn btn-create"
diff --git a/app/views/projects/team_members/_group_members.html.haml b/app/views/projects/team_members/_group_members.html.haml
index 83c4b6f87d5250fba9028c50357e88a07bfb7e4a..77ffab89f37a2790c2a6e411616683fe2d1015e6 100644
--- a/app/views/projects/team_members/_group_members.html.haml
+++ b/app/views/projects/team_members/_group_members.html.haml
@@ -1,4 +1,4 @@
-- group_users_count = @group.users_groups.count
+- group_users_count = @group.group_members.count
 .panel.panel-default
   .panel-heading
     %strong #{@group.name}
@@ -7,8 +7,8 @@
       = link_to members_group_path(@group), class: 'btn btn-small' do
         %i.icon-edit
   %ul.well-list
-    - @group.users_groups.order('group_access DESC').limit(20).each do |member|
-      = render 'users_groups/users_group', member: member, show_controls: false
+    - @group.group_members.order('access_level DESC').limit(20).each do |member|
+      = render 'groups/group_members/group_member', member: member, show_controls: false
     - if group_users_count > 20
       %li
         and #{group_users_count - 20} more. For full list visit #{link_to 'group members page', members_group_path(@group)}
diff --git a/app/views/projects/team_members/_team_member.html.haml b/app/views/projects/team_members/_team_member.html.haml
index d93bb44ab963159dda376be1365559cc91d90aa6..79b786654170df0640535e5054e2baaec0b99773 100644
--- a/app/views/projects/team_members/_team_member.html.haml
+++ b/app/views/projects/team_members/_team_member.html.haml
@@ -4,8 +4,8 @@
     - if current_user_can_admin_project
       - unless @project.personal? && user == current_user
         .pull-left
-          = form_for(member, as: :team_member, url: project_team_member_path(@project, member.user)) do |f|
-            = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2 trigger-submit"
+          = form_for(member, as: :project_member, url: project_team_member_path(@project, member.user)) do |f|
+            = f.select :access_level, options_for_select(ProjectMember.access_roles, member.access_level), {}, class: "medium project-access-select span2 trigger-submit"
           &nbsp;
         = link_to project_team_member_path(@project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from team' do
           %i.icon-minus.icon-white
diff --git a/app/views/projects/team_members/index.html.haml b/app/views/projects/team_members/index.html.haml
index ddb3b9d4a9d0ef5f214a6137a7c5c2456958ce15..ecb7c689e8ab9d882339ade2ee076ce369799597 100644
--- a/app/views/projects/team_members/index.html.haml
+++ b/app/views/projects/team_members/index.html.haml
@@ -11,6 +11,6 @@
 %p.light
   Read more about project permissions
   %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
-= render "team", members: @users_projects
+= render "team", members: @project_members
 - if @group
   = render "group_members"
diff --git a/app/views/projects/tree/_readme.html.haml b/app/views/projects/tree/_readme.html.haml
index 9d0292059d6307ab7a2f2e9e0dbad4201730083a..ec2701af0eba47a243d34b3d6c578a8e02759848 100644
--- a/app/views/projects/tree/_readme.html.haml
+++ b/app/views/projects/tree/_readme.html.haml
@@ -1,6 +1,7 @@
 %article.readme-holder#README
-  %h4.readme-file-title
-    %i.icon-file
-    = readme.name
+  = link_to '#README' do
+    %h4.readme-file-title
+      %i.icon-file
+      = readme.name
   .wiki
     = render_readme(readme)
diff --git a/config/application.rb b/config/application.rb
index 68dce05fc599d012f2467979a174991b996e13ec..99dfafdb786517c1ef2e9f0a38d4c8d34f2b0ec2 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -12,7 +12,12 @@ module Gitlab
     # -- all .rb files in that directory are automatically loaded.
 
     # Custom directories with classes and modules you want to be autoloadable.
-    config.autoload_paths += %W(#{config.root}/lib #{config.root}/app/finders #{config.root}/app/models/concerns #{config.root}/app/models/project_services)
+    config.autoload_paths += %W(#{config.root}/lib
+                                #{config.root}/app/finders
+                                #{config.root}/app/models/hooks
+                                #{config.root}/app/models/concerns
+                                #{config.root}/app/models/project_services
+                                #{config.root}/app/models/members)
 
     # Only load the plugins named here, in the order given (default is alphabetical).
     # :all can be used as a placeholder for all plugins not explicitly named.
diff --git a/config/routes.rb b/config/routes.rb
index ce66ea999514bae5f7d648c07be40e3ce3b2d3d7..39ab9f4265ace0cab725dd6395532099f5edc1b1 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -161,9 +161,8 @@ Gitlab::Application.routes.draw do
       get :projects
     end
 
-    resources :users_groups, only: [:create, :update, :destroy]
-
     scope module: :groups do
+      resources :group_members, only: [:create, :update, :destroy]
       resource :avatar, only: [:destroy]
       resources :milestones
     end
diff --git a/db/fixtures/development/06_teams.rb b/db/fixtures/development/06_teams.rb
index dfbe75fd20eb2728bdb49b5e3077e71ba220b8f4..3e8cdcd67b4a66ab88eb6927453d98782b85bfa2 100644
--- a/db/fixtures/development/06_teams.rb
+++ b/db/fixtures/development/06_teams.rb
@@ -1,7 +1,7 @@
 Gitlab::Seeder.quiet do
   Group.all.each do |group|
     User.all.sample(4).each do |user|
-      if group.add_users([user.id], UsersGroup.group_access_roles.values.sample)
+      if group.add_users([user.id], Gitlab::Access.values.sample)
         print '.'
       else
         print 'F'
@@ -11,7 +11,7 @@ Gitlab::Seeder.quiet do
 
   Project.all.each do |project|
     User.all.sample(4).each do |user|
-      if project.team << [user, UsersProject.access_roles.values.sample]
+      if project.team << [user, Gitlab::Access.values.sample]
         print '.'
       else
         print 'F'
diff --git a/db/migrate/20140914113604_add_members_table.rb b/db/migrate/20140914113604_add_members_table.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d311f3033ee65d75156391b27cfecffb6a02785e
--- /dev/null
+++ b/db/migrate/20140914113604_add_members_table.rb
@@ -0,0 +1,19 @@
+class AddMembersTable < ActiveRecord::Migration
+  def change
+    create_table :members do |t|
+      t.integer :access_level, null: false
+      t.integer :source_id,    null: false
+      t.string  :source_type,  null: false
+      t.integer :user_id,      null: false
+      t.integer :notification_level, null: false
+      t.string  :type
+
+      t.timestamps
+    end
+
+    add_index :members, :type
+    add_index :members, :user_id
+    add_index :members, :access_level
+    add_index :members, [:source_id, :source_type]
+  end
+end
diff --git a/db/migrate/20140914145549_migrate_to_new_members_model.rb b/db/migrate/20140914145549_migrate_to_new_members_model.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2a5a49c724a8c555e05a3a15511d2235e17f7bef
--- /dev/null
+++ b/db/migrate/20140914145549_migrate_to_new_members_model.rb
@@ -0,0 +1,11 @@
+class MigrateToNewMembersModel < ActiveRecord::Migration
+  def up
+    execute "INSERT INTO members ( user_id, source_id, source_type, access_level, notification_level, type ) SELECT user_id, group_id, 'Namespace', group_access, notification_level, 'GroupMember' FROM users_groups"
+    execute "INSERT INTO members ( user_id, source_id, source_type, access_level, notification_level, type ) SELECT user_id, project_id, 'Project', project_access, notification_level, 'ProjectMember' FROM users_projects"
+  end
+
+  def down
+    Member.delete_all
+  end
+end
+
diff --git a/db/migrate/20140914173417_remove_old_member_tables.rb b/db/migrate/20140914173417_remove_old_member_tables.rb
new file mode 100644
index 0000000000000000000000000000000000000000..408b9551dbb466bdbf30284b741b8dfe2ed805c2
--- /dev/null
+++ b/db/migrate/20140914173417_remove_old_member_tables.rb
@@ -0,0 +1,26 @@
+class RemoveOldMemberTables < ActiveRecord::Migration
+  def up
+    drop_table :users_groups
+    drop_table :users_projects
+  end
+
+  def down
+    create_table :users_groups do |t|
+      t.integer :group_access, null: false
+      t.integer :group_id, null: false
+      t.integer :user_id, null: false
+      t.integer :notification_level, null: false, default: 3
+
+      t.timestamps
+    end
+
+    create_table :users_projects do |t|
+      t.integer :project_access, null: false
+      t.integer :project_id, null: false
+      t.integer :user_id, null: false
+      t.integer :notification_level, null: false, default: 3
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index e9b3713557d36957bd7e7abdb8c7767faf3f53c0..4e249caa022c25e89b0572e7169ec6892630fe87 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20140907220153) do
+ActiveRecord::Schema.define(version: 20140914173417) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -130,6 +130,22 @@ ActiveRecord::Schema.define(version: 20140907220153) do
 
   add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree
 
+  create_table "members", force: true do |t|
+    t.integer  "access_level",       null: false
+    t.integer  "source_id",          null: false
+    t.string   "source_type",        null: false
+    t.integer  "user_id",            null: false
+    t.integer  "notification_level", null: false
+    t.string   "type"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  add_index "members", ["access_level"], name: "index_members_on_access_level", using: :btree
+  add_index "members", ["source_id", "source_type"], name: "index_members_on_source_id_and_source_type", using: :btree
+  add_index "members", ["type"], name: "index_members_on_type", using: :btree
+  add_index "members", ["user_id"], name: "index_members_on_user_id", using: :btree
+
   create_table "merge_request_diffs", force: true do |t|
     t.string   "state"
     t.text     "st_commits"
@@ -363,30 +379,6 @@ ActiveRecord::Schema.define(version: 20140907220153) do
   add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
   add_index "users", ["username"], name: "index_users_on_username", using: :btree
 
-  create_table "users_groups", force: true do |t|
-    t.integer  "group_access",                   null: false
-    t.integer  "group_id",                       null: false
-    t.integer  "user_id",                        null: false
-    t.datetime "created_at"
-    t.datetime "updated_at"
-    t.integer  "notification_level", default: 3, null: false
-  end
-
-  add_index "users_groups", ["user_id"], name: "index_users_groups_on_user_id", using: :btree
-
-  create_table "users_projects", force: true do |t|
-    t.integer  "user_id",                        null: false
-    t.integer  "project_id",                     null: false
-    t.datetime "created_at"
-    t.datetime "updated_at"
-    t.integer  "project_access",     default: 0, null: false
-    t.integer  "notification_level", default: 3, null: false
-  end
-
-  add_index "users_projects", ["project_access"], name: "index_users_projects_on_project_access", using: :btree
-  add_index "users_projects", ["project_id"], name: "index_users_projects_on_project_id", using: :btree
-  add_index "users_projects", ["user_id"], name: "index_users_projects_on_user_id", using: :btree
-
   create_table "users_star_projects", force: true do |t|
     t.integer  "project_id", null: false
     t.integer  "user_id",    null: false
diff --git a/features/steps/admin/groups.rb b/features/steps/admin/groups.rb
index 9c1bcfefb9c2157dfb33826d7d0f11020a7cd7a1..d761584ad9396eb6b912df17c8d88e73a0e6d39f 100644
--- a/features/steps/admin/groups.rb
+++ b/features/steps/admin/groups.rb
@@ -40,7 +40,7 @@ class AdminGroups < Spinach::FeatureSteps
     user = User.find_by(name: "John Doe")
     select2(user.id, from: "#user_ids", multiple: true)
     within "#new_team_member" do
-      select "Reporter", from: "group_access"
+      select "Reporter", from: "access_level"
     end
     click_button "Add users into group"
   end
diff --git a/features/steps/dashboard/event_filters.rb b/features/steps/dashboard/event_filters.rb
index d0fe5c9b64b056125e5833f8e9fdf33cfd12a30f..801ea400a7a6474aa222e4a9fa9e2cc14f953b56 100644
--- a/features/steps/dashboard/event_filters.rb
+++ b/features/steps/dashboard/event_filters.rb
@@ -82,6 +82,4 @@ class EventFilters < Spinach::FeatureSteps
   When 'I click "merge" event filter' do
     click_link("merged_event_filter")
   end
-
 end
-
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index c3ee42f112766db5443358e20d8cf116f2c894b7..d0ec503f47bdf182f9138a209df2a8fe80d608f7 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -32,7 +32,7 @@ class Groups < Spinach::FeatureSteps
     click_link 'Add members'
     within ".users-group-form" do
       select2(user.id, from: "#user_ids", multiple: true)
-      select "Reporter", from: "group_access"
+      select "Reporter", from: "access_level"
     end
     click_button "Add users into group"
   end
diff --git a/features/steps/project/browse_files.rb b/features/steps/project/browse_files.rb
index d5e44f796ca28845fe8df0c85423aab62b659ae3..9ea9c7cf1388e06917634bfbc2e5c6d2da1e0762 100644
--- a/features/steps/project/browse_files.rb
+++ b/features/steps/project/browse_files.rb
@@ -77,7 +77,9 @@ class ProjectBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I click on readme file' do
-    click_link 'README.md'
+    within '.tree-table' do
+      click_link 'README.md'
+    end
   end
 
   step 'I see Browse file link' do
diff --git a/features/steps/project/markdown_render.rb b/features/steps/project/markdown_render.rb
index 1885649891e6f9b8e74477817fb13f2a16e2fce8..83572718f39d505d71a6a359d50cf1e0bc79e36d 100644
--- a/features/steps/project/markdown_render.rb
+++ b/features/steps/project/markdown_render.rb
@@ -79,9 +79,17 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps
   end
 
   And 'I navigate to the doc/api/README' do
-    click_link "doc"
-    click_link "api"
-    click_link "README.md"
+    within '.tree-table' do
+      click_link "doc"
+    end
+
+    within '.tree-table' do
+      click_link "api"
+    end
+
+    within '.tree-table' do
+      click_link "README.md"
+    end
   end
 
   And 'I see correct file rendered' do
diff --git a/features/steps/project/team_management.rb b/features/steps/project/team_management.rb
index ffc5016529f1efdd8a1f56b7b19324b0ddf86521..76a0671721e085eee29bf76a3048d1e37e0e29f2 100644
--- a/features/steps/project/team_management.rb
+++ b/features/steps/project/team_management.rb
@@ -23,8 +23,8 @@ class ProjectTeamManagement < Spinach::FeatureSteps
     user = User.find_by(name: "Mike")
 
     select2(user.id, from: "#user_ids", multiple: true)
-    within "#new_team_member" do
-      select "Reporter", from: "project_access"
+    within "#new_project_member" do
+      select "Reporter", from: "access_level"
     end
     click_button "Add users"
   end
@@ -44,7 +44,7 @@ class ProjectTeamManagement < Spinach::FeatureSteps
   And 'I change "Sam" role to "Reporter"' do
     user = User.find_by(name: "Sam")
     within "#user_#{user.id}" do
-      select "Reporter", from: "team_member_project_access"
+      select "Reporter", from: "project_member_access_level"
     end
   end
 
diff --git a/features/support/env.rb b/features/support/env.rb
index 22f28987fe363f9da6c34c21213740ecaec460eb..4b76faab56461c548ff59dc52c7653ac5f209f6b 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -1,20 +1,20 @@
-require 'simplecov' unless ENV['CI']
+if ENV['SIMPLECOV']
+  require 'simplecov'
+end
 
-if ENV['TRAVIS']
+if ENV['COVERALLS']
   require 'coveralls'
-  Coveralls.wear!
+  Coveralls.wear_merged!('rails')
 end
 
 ENV['RAILS_ENV'] = 'test'
 require './config/environment'
-
 require 'rspec'
 require 'rspec/expectations'
 require 'database_cleaner'
 require 'spinach/capybara'
 require 'sidekiq/testing/inline'
 
-
 %w(select2_helper test_env repo_helpers).each do |f|
   require Rails.root.join('spec', 'support', f)
 end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 74fdef935433987fd48a8af7448c2476827aa897..ffa3e8a149edcc63f069f14dbddea75bcd24a5a4 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -53,8 +53,8 @@ module API
     end
 
     class ProjectMember < UserBasic
-      expose :project_access, as: :access_level do |user, options|
-        options[:project].users_projects.find_by(user_id: user.id).project_access
+      expose :access_level do |user, options|
+        options[:project].project_members.find_by(user_id: user.id).access_level
       end
     end
 
@@ -67,8 +67,8 @@ module API
     end
 
     class GroupMember < UserBasic
-      expose :group_access, as: :access_level do |user, options|
-        options[:group].users_groups.find_by(user_id: user.id).group_access
+      expose :access_level do |user, options|
+        options[:group].group_members.find_by(user_id: user.id).access_level
       end
     end
 
@@ -170,24 +170,24 @@ module API
     end
 
     class ProjectAccess < Grape::Entity
-      expose :project_access, as: :access_level
+      expose :access_level
       expose :notification_level
     end
 
     class GroupAccess < Grape::Entity
-      expose :group_access, as: :access_level
+      expose :access_level
       expose :notification_level
     end
 
     class ProjectWithAccess < Project
       expose :permissions do
         expose :project_access, using: Entities::ProjectAccess do |project, options|
-          project.users_projects.find_by(user_id: options[:user].id)
+          project.project_members.find_by(user_id: options[:user].id)
         end
 
         expose :group_access, using: Entities::GroupAccess do |project, options|
           if project.group
-            project.group.users_groups.find_by(user_id: options[:user].id)
+            project.group.group_members.find_by(user_id: options[:user].id)
           end
         end
       end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index caa2ca97a3eba15f0098f01ea2ae7985e12d01ff..4841e04689d481a81c476a19ae43dc5393c85de6 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -104,7 +104,7 @@ module API
       #  GET /groups/:id/members
       get ":id/members" do
         group = find_group(params[:id])
-        members = group.users_groups
+        members = group.group_members
         users = (paginate members).collect(&:user)
         present users, with: Entities::GroupMember, group: group
       end
@@ -123,11 +123,11 @@ module API
           render_api_error!("Wrong access level", 422)
         end
         group = find_group(params[:id])
-        if group.users_groups.find_by(user_id: params[:user_id])
+        if group.group_members.find_by(user_id: params[:user_id])
           render_api_error!("Already exists", 409)
         end
         group.add_users([params[:user_id]], params[:access_level])
-        member = group.users_groups.find_by(user_id: params[:user_id])
+        member = group.group_members.find_by(user_id: params[:user_id])
         present member.user, with: Entities::GroupMember, group: group
       end
 
@@ -141,7 +141,7 @@ module API
       #   DELETE /groups/:id/members/:user_id
       delete ":id/members/:user_id" do
         group = find_group(params[:id])
-        member =  group.users_groups.find_by(user_id: params[:user_id])
+        member =  group.group_members.find_by(user_id: params[:user_id])
         if member.nil?
           render_api_error!("404 Not Found - user_id:#{params[:user_id]} not a member of group #{group.name}",404)
         else
diff --git a/lib/api/project_members.rb b/lib/api/project_members.rb
index 47c4ddce16340089c9e575b616a083b3d53cd9af..1595ed0bc3653dc068a8cd7fc318eace0be245de 100644
--- a/lib/api/project_members.rb
+++ b/lib/api/project_members.rb
@@ -6,8 +6,8 @@ module API
     resource :projects do
       helpers do
         def handle_project_member_errors(errors)
-          if errors[:project_access].any?
-            error!(errors[:project_access], 422)
+          if errors[:access_level].any?
+            error!(errors[:access_level], 422)
           end
           not_found!
         end
@@ -56,9 +56,9 @@ module API
         # either the user is already a team member or a new one
         team_member = user_project.team_member_by_id(params[:user_id])
         if team_member.nil?
-          team_member = user_project.users_projects.new(
+          team_member = user_project.project_members.new(
             user_id: params[:user_id],
-            project_access: params[:access_level]
+            access_level: params[:access_level]
           )
         end
 
@@ -82,10 +82,10 @@ module API
         authorize! :admin_project, user_project
         required_attributes! [:access_level]
 
-        team_member = user_project.users_projects.find_by(user_id: params[:user_id])
+        team_member = user_project.project_members.find_by(user_id: params[:user_id])
         not_found!("User can not be found") if team_member.nil?
 
-        if team_member.update_attributes(project_access: params[:access_level])
+        if team_member.update_attributes(access_level: params[:access_level])
           @member = team_member.user
           present @member, with: Entities::ProjectMember, project: user_project
         else
@@ -102,7 +102,7 @@ module API
       #   DELETE /projects/:id/members/:user_id
       delete ":id/members/:user_id" do
         authorize! :admin_project, user_project
-        team_member = user_project.users_projects.find_by(user_id: params[:user_id])
+        team_member = user_project.project_members.find_by(user_id: params[:user_id])
         unless team_member.nil?
           team_member.destroy
         else
diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb
index 87f9cfab608ee17c4d659b0385b338654df6b74e..411b2b9a3cc7e014ce20134ff91c9ba2e04a37b9 100644
--- a/lib/gitlab/access.rb
+++ b/lib/gitlab/access.rb
@@ -16,6 +16,10 @@ module Gitlab
         options.values
       end
 
+      def all_values
+        options_with_owner.values
+      end
+
       def options
         {
           "Guest"     => GUEST,
diff --git a/lib/tasks/gitlab/bulk_add_permission.rake b/lib/tasks/gitlab/bulk_add_permission.rake
index 0e1a3d071e9440e7f8836078b95d6ba20ea6858b..3d8c171dfa3f1368cd38f0880cb1390d403a6896 100644
--- a/lib/tasks/gitlab/bulk_add_permission.rake
+++ b/lib/tasks/gitlab/bulk_add_permission.rake
@@ -7,10 +7,10 @@ namespace :gitlab do
       projects_ids = Project.pluck(:id)
 
       puts "Importing #{user_ids.size} users into #{projects_ids.size} projects"
-      UsersProject.add_users_into_projects(projects_ids, user_ids, UsersProject::DEVELOPER)
+      ProjectMember.add_users_into_projects(projects_ids, user_ids, ProjectMember::DEVELOPER)
 
       puts "Importing #{admin_ids.size} admins into #{projects_ids.size} projects"
-      UsersProject.add_users_into_projects(projects_ids, admin_ids, UsersProject::MASTER)
+      ProjectMember.add_users_into_projects(projects_ids, admin_ids, ProjectMember::MASTER)
     end
 
     desc "GITLAB | Add a specific user to all projects (as a developer)"
@@ -18,7 +18,7 @@ namespace :gitlab do
       user = User.find_by(email: args.email)
       project_ids = Project.pluck(:id)
       puts "Importing #{user.email} users into #{project_ids.size} projects"
-      UsersProject.add_users_into_projects(project_ids, Array.wrap(user.id), UsersProject::DEVELOPER)
+      ProjectMember.add_users_into_projects(project_ids, Array.wrap(user.id), ProjectMember::DEVELOPER)
     end
 
     desc "GITLAB | Add all users to all groups (admin users are added as owners)"
@@ -30,8 +30,8 @@ namespace :gitlab do
       puts "Importing #{user_ids.size} users into #{groups.size} groups"
       puts "Importing #{admin_ids.size} admins into #{groups.size} groups"
       groups.each do |group|
-        group.add_users(user_ids, UsersGroup::DEVELOPER)
-        group.add_users(admin_ids, UsersGroup::OWNER)
+        group.add_users(user_ids, GroupMember::DEVELOPER)
+        group.add_users(admin_ids, GroupMember::OWNER)
       end
     end
 
@@ -41,7 +41,7 @@ namespace :gitlab do
       groups = Group.all
       puts "Importing #{user.email} users into #{groups.size} groups"
       groups.each do |group|
-        group.add_users(Array.wrap(user.id), UsersGroup::DEVELOPER)
+        group.add_users(Array.wrap(user.id), GroupMember::DEVELOPER)
       end
     end
   end
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 248b567d007f182be4150e7154fa3e849c428104..9ec368254ac046dcbb6c223015e47fa8e9892752 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -17,7 +17,7 @@ namespace :gitlab do
       check_database_config_exists
       check_database_is_not_sqlite
       check_migrations_are_up
-      check_orphaned_users_groups
+      check_orphaned_group_members
       check_gitlab_config_exists
       check_gitlab_config_not_outdated
       check_log_writable
@@ -194,13 +194,13 @@ namespace :gitlab do
       end
     end
 
-    def check_orphaned_users_groups
-      print "Database contains orphaned UsersGroups? ... "
-      if UsersGroup.where("user_id not in (select id from users)").count > 0
+    def check_orphaned_group_members
+      print "Database contains orphaned GroupMembers? ... "
+      if GroupMember.where("user_id not in (select id from users)").count > 0
         puts "yes".red
         try_fixing_it(
           "You can delete the orphaned records using something along the lines of:",
-          sudo_gitlab("bundle exec rails runner -e production 'UsersGroup.where(\"user_id NOT IN (SELECT id FROM users)\").delete_all'")
+          sudo_gitlab("bundle exec rails runner -e production 'GroupMember.where(\"user_id NOT IN (SELECT id FROM users)\").delete_all'")
         )
       else
         puts "no".green
diff --git a/spec/factories.rb b/spec/factories.rb
index f7f65bffb8b32f369e4a60121ff630b02e0876ad..a960571206cc40a45b729c5c4c08bba0ec125370 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -39,10 +39,10 @@ FactoryGirl.define do
     owner
   end
 
-  factory :users_project do
+  factory :project_member do
     user
     project
-    project_access { UsersProject::MASTER }
+    access_level { ProjectMember::MASTER }
   end
 
   factory :issue do
diff --git a/spec/factories/users_groups.rb b/spec/factories/group_members.rb
similarity index 81%
rename from spec/factories/users_groups.rb
rename to spec/factories/group_members.rb
index 49c3a367e16f7214fbe5b098d611bd0f7d0119a3..debb86d997f48773b6a323ea08d9228e6f80f883 100644
--- a/spec/factories/users_groups.rb
+++ b/spec/factories/group_members.rb
@@ -1,6 +1,6 @@
 # == Schema Information
 #
-# Table name: users_groups
+# Table name: group_members
 #
 #  id                 :integer          not null, primary key
 #  group_access       :integer          not null
@@ -12,8 +12,8 @@
 #
 
 FactoryGirl.define do
-  factory :users_group do
-    group_access { UsersGroup::OWNER }
+  factory :group_member do
+    access_level { GroupMember::OWNER }
     group
     user
   end
diff --git a/spec/features/atom/dashboard_spec.rb b/spec/features/atom/dashboard_spec.rb
index e5d9f8ab5d5c7ac3e5f16ebb1e56e5353a06aa2e..a72a41fdf398ab9c03480849a1e65ed449601f8a 100644
--- a/spec/features/atom/dashboard_spec.rb
+++ b/spec/features/atom/dashboard_spec.rb
@@ -10,5 +10,34 @@ describe "Dashboard Feed", feature: true  do
         page.body.should have_selector("feed title")
       end
     end
+
+    context 'feed content' do
+      let(:project) { create(:project) }
+      let(:issue) { create(:issue, project: project, author: user, description: '') }
+      let(:note) { create(:note, noteable: issue, author: user, note: 'Bug confirmed', project: project) }
+
+      before do
+        project.team << [user, :master]
+        issue_event(issue, user)
+        note_event(note, user)
+        visit dashboard_path(:atom, private_token: user.private_token)
+      end
+
+      it "should have issue opened event" do
+        page.body.should have_content("#{user.name} opened issue ##{issue.iid}")
+      end
+
+      it "should have issue comment event" do
+        page.body.should have_content("#{user.name} commented on issue ##{issue.iid}")
+      end
+    end
+  end
+
+  def issue_event(issue, user)
+    EventCreateService.new.open_issue(issue, user)
+  end
+
+  def note_event(note, user)
+    EventCreateService.new.leave_note(note, user)
   end
 end
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index ba6af6f8b45fca4c76269e6a452cbad0dff75820..46337f8bafdc8311eb4d88b0526a7fee0d7b81e8 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -12,7 +12,7 @@ describe GitlabMarkdownHelper do
   let(:issue)         { create(:issue, project: project) }
   let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
   let(:snippet)       { create(:project_snippet, project: project) }
-  let(:member)        { project.users_projects.where(user_id: user).first }
+  let(:member)        { project.project_members.where(user_id: user).first }
 
   before do
     # Helper expects a @project instance variable
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 702431e071267255080cbc82003843040ac0a10b..799dce442cc87624d28eac87bfe20f4e7871300d 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -402,10 +402,10 @@ describe Notify do
     describe 'project access changed' do
       let(:project) { create(:project) }
       let(:user) { create(:user) }
-      let(:users_project) { create(:users_project,
+      let(:project_member) { create(:project_member,
                                    project: project,
                                    user: user) }
-      subject { Notify.project_access_granted_email(users_project.id) }
+      subject { Notify.project_access_granted_email(project_member.id) }
 
       it_behaves_like 'an email sent from GitLab'
 
@@ -416,7 +416,7 @@ describe Notify do
         should have_body_text /#{project.name}/
       end
       it 'contains new user role' do
-        should have_body_text /#{users_project.human_access}/
+        should have_body_text /#{project_member.human_access}/
       end
     end
 
@@ -506,7 +506,7 @@ describe Notify do
   describe 'group access changed' do
     let(:group) { create(:group) }
     let(:user) { create(:user) }
-    let(:membership) { create(:users_group, group: group, user: user) }
+    let(:membership) { create(:group_member, group: group, user: user) }
 
     subject { Notify.group_access_granted_email(membership.id) }
 
diff --git a/spec/models/users_group_spec.rb b/spec/models/group_member_spec.rb
similarity index 51%
rename from spec/models/users_group_spec.rb
rename to spec/models/group_member_spec.rb
index 0b6f7a08198dff1652ab32cd9ad08e08c29c0858..6acbc9bb4ae243682937b7c07f2a3c94a50fbd48 100644
--- a/spec/models/users_group_spec.rb
+++ b/spec/models/group_member_spec.rb
@@ -1,9 +1,9 @@
 # == Schema Information
 #
-# Table name: users_groups
+# Table name: group_members
 #
 #  id                 :integer          not null, primary key
-#  group_access       :integer          not null
+#  access_level       :integer          not null
 #  group_id           :integer          not null
 #  user_id            :integer          not null
 #  created_at         :datetime
@@ -13,34 +13,11 @@
 
 require 'spec_helper'
 
-describe UsersGroup do
-  describe "Associations" do
-    it { should belong_to(:group) }
-    it { should belong_to(:user) }
-  end
-
-  describe "Mass assignment" do
-  end
-
-  describe "Validation" do
-    let!(:users_group) { create(:users_group) }
-
-    it { should validate_presence_of(:user_id) }
-    it { should validate_uniqueness_of(:user_id).scoped_to(:group_id).with_message(/already exists/) }
-
-    it { should validate_presence_of(:group_id) }
-    it { should ensure_inclusion_of(:group_access).in_array(UsersGroup.group_access_roles.values) }
-  end
-
-  describe "Delegate methods" do
-    it { should respond_to(:user_name) }
-    it { should respond_to(:user_email) }
-  end
-
+describe GroupMember do
   context 'notification' do
     describe "#after_create" do
       it "should send email to user" do
-        membership = build(:users_group)
+        membership = build(:group_member)
         membership.stub(notification_service: double('NotificationService').as_null_object)
         membership.should_receive(:notification_service)
         membership.save
@@ -49,18 +26,18 @@ describe UsersGroup do
 
     describe "#after_update" do
       before do
-        @membership = create :users_group
+        @membership = create :group_member
         @membership.stub(notification_service: double('NotificationService').as_null_object)
       end
 
       it "should send email to user" do
         @membership.should_receive(:notification_service)
-        @membership.update_attribute(:group_access, UsersGroup::MASTER)
+        @membership.update_attribute(:access_level, GroupMember::MASTER)
       end
 
       it "does not send an email when the access level has not changed" do
         @membership.should_not_receive(:notification_service)
-        @membership.update_attribute(:group_access, UsersGroup::OWNER)
+        @membership.update_attribute(:access_level, GroupMember::OWNER)
       end
     end
   end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 8259ed88d83c64bb3c8ece2fb5df824620e9e7b7..1d4ba8a2b850cdae3075518d52749828e7a9246a 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -20,7 +20,7 @@ describe Group do
 
   describe "Associations" do
     it { should have_many :projects }
-    it { should have_many :users_groups }
+    it { should have_many :group_members }
   end
 
   it { should validate_presence_of :name }
@@ -39,26 +39,26 @@ describe Group do
 
   describe :add_users do
     let(:user) { create(:user) }
-    before { group.add_user(user, UsersGroup::MASTER) }
+    before { group.add_user(user, GroupMember::MASTER) }
 
-    it { group.users_groups.masters.map(&:user).should include(user) }
+    it { group.group_members.masters.map(&:user).should include(user) }
   end
 
   describe :add_users do
     let(:user) { create(:user) }
-    before { group.add_users([user.id], UsersGroup::GUEST) }
+    before { group.add_users([user.id], GroupMember::GUEST) }
 
     it "should update the group permission" do
-      group.users_groups.guests.map(&:user).should include(user)
-      group.add_users([user.id], UsersGroup::DEVELOPER)
-      group.users_groups.developers.map(&:user).should include(user)
-      group.users_groups.guests.map(&:user).should_not include(user)
+      group.group_members.guests.map(&:user).should include(user)
+      group.add_users([user.id], GroupMember::DEVELOPER)
+      group.group_members.developers.map(&:user).should include(user)
+      group.group_members.guests.map(&:user).should_not include(user)
     end
   end
 
   describe :avatar_type do
     let(:user) { create(:user) }
-    before { group.add_user(user, UsersGroup::MASTER) }
+    before { group.add_user(user, GroupMember::MASTER) }
 
     it "should be true if avatar is image" do
       group.update_attribute(:avatar, 'uploads/avatar.png')
diff --git a/spec/models/members_spec.rb b/spec/models/members_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6866c4794c28b9c8774077c005b9ed73ac8cc57e
--- /dev/null
+++ b/spec/models/members_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Member do
+  describe "Associations" do
+    it { should belong_to(:user) }
+  end
+
+  describe "Validation" do
+    subject { Member.new(access_level: Member::GUEST) }
+
+    it { should validate_presence_of(:user) }
+    it { should validate_presence_of(:source) }
+    it { should ensure_inclusion_of(:access_level).in_array(Gitlab::Access.values) }
+  end
+
+  describe "Delegate methods" do
+    it { should respond_to(:user_name) }
+    it { should respond_to(:user_email) }
+  end
+end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index d06dee6ce92912a666bde6455a3e157b12dfbe68..da51100e0d7b86cb5006eb3ea7c34ff25f51be22 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -321,8 +321,8 @@ describe Note do
 
     describe :read do
       before do
-        @p1.users_projects.create(user: @u2, project_access: UsersProject::GUEST)
-        @p2.users_projects.create(user: @u3, project_access: UsersProject::GUEST)
+        @p1.project_members.create(user: @u2, access_level: ProjectMember::GUEST)
+        @p2.project_members.create(user: @u3, access_level: ProjectMember::GUEST)
       end
 
       it { @abilities.allowed?(@u1, :read_note, @p1).should be_false }
@@ -332,8 +332,8 @@ describe Note do
 
     describe :write do
       before do
-        @p1.users_projects.create(user: @u2, project_access: UsersProject::DEVELOPER)
-        @p2.users_projects.create(user: @u3, project_access: UsersProject::DEVELOPER)
+        @p1.project_members.create(user: @u2, access_level: ProjectMember::DEVELOPER)
+        @p2.project_members.create(user: @u3, access_level: ProjectMember::DEVELOPER)
       end
 
       it { @abilities.allowed?(@u1, :write_note, @p1).should be_false }
@@ -343,9 +343,9 @@ describe Note do
 
     describe :admin do
       before do
-        @p1.users_projects.create(user: @u1, project_access: UsersProject::REPORTER)
-        @p1.users_projects.create(user: @u2, project_access: UsersProject::MASTER)
-        @p2.users_projects.create(user: @u3, project_access: UsersProject::MASTER)
+        @p1.project_members.create(user: @u1, access_level: ProjectMember::REPORTER)
+        @p1.project_members.create(user: @u2, access_level: ProjectMember::MASTER)
+        @p2.project_members.create(user: @u3, access_level: ProjectMember::MASTER)
       end
 
       it { @abilities.allowed?(@u1, :admin_note, @p1).should be_false }
diff --git a/spec/models/users_project_spec.rb b/spec/models/project_member_spec.rb
similarity index 72%
rename from spec/models/users_project_spec.rb
rename to spec/models/project_member_spec.rb
index 3f38164e9647344cbb43fda93316e26a5517b0f9..0178d065e579ea634547bfe7e5d8e2d47656a686 100644
--- a/spec/models/users_project_spec.rb
+++ b/spec/models/project_member_spec.rb
@@ -1,6 +1,6 @@
 # == Schema Information
 #
-# Table name: users_projects
+# Table name: project_members
 #
 #  id                 :integer          not null, primary key
 #  user_id            :integer          not null
@@ -13,30 +13,7 @@
 
 require 'spec_helper'
 
-describe UsersProject do
-  describe "Associations" do
-    it { should belong_to(:project) }
-    it { should belong_to(:user) }
-  end
-
-  describe "Mass assignment" do
-  end
-
-  describe "Validation" do
-    let!(:users_project) { create(:users_project) }
-
-    it { should validate_presence_of(:user) }
-    it { should validate_uniqueness_of(:user_id).scoped_to(:project_id).with_message(/already exists/) }
-
-    it { should validate_presence_of(:project) }
-    it { should ensure_inclusion_of(:project_access).in_array(UsersProject.access_roles.values) }
-  end
-
-  describe "Delegate methods" do
-    it { should respond_to(:user_name) }
-    it { should respond_to(:user_email) }
-  end
-
+describe ProjectMember do
   describe :import_team do
     before do
       @abilities = Six.new
@@ -78,10 +55,10 @@ describe UsersProject do
       @user_1 = create :user
       @user_2 = create :user
 
-      UsersProject.add_users_into_projects(
+      ProjectMember.add_users_into_projects(
         [@project_1.id, @project_2.id],
         [@user_1.id, @user_2.id],
-        UsersProject::MASTER
+        ProjectMember::MASTER
       )
     end
 
@@ -104,7 +81,7 @@ describe UsersProject do
       @project_1.team << [ @user_1, :developer]
       @project_2.team << [ @user_2, :reporter]
 
-      UsersProject.truncate_teams([@project_1.id, @project_2.id])
+      ProjectMember.truncate_teams([@project_1.id, @project_2.id])
     end
 
     it { @project_1.users.should be_empty }
diff --git a/spec/models/project_security_spec.rb b/spec/models/project_security_spec.rb
index 1f2bd7a56fffa1c3421afc56b03d3502f3f9d447..5c8d1e7438b5fcce0a2ce4fa3a10b9c4f33dcdf7 100644
--- a/spec/models/project_security_spec.rb
+++ b/spec/models/project_security_spec.rb
@@ -30,7 +30,7 @@ describe Project do
 
     describe "Guest Rules" do
       before do
-        @p1.users_projects.create(project: @p1, user: @u2, project_access: UsersProject::GUEST)
+        @p1.project_members.create(project: @p1, user: @u2, access_level: ProjectMember::GUEST)
       end
 
       it "should allow for project user any guest actions" do
@@ -42,7 +42,7 @@ describe Project do
 
     describe "Report Rules" do
       before do
-        @p1.users_projects.create(project: @p1, user: @u2, project_access: UsersProject::REPORTER)
+        @p1.project_members.create(project: @p1, user: @u2, access_level: ProjectMember::REPORTER)
       end
 
       it "should allow for project user any report actions" do
@@ -54,8 +54,8 @@ describe Project do
 
     describe "Developer Rules" do
       before do
-        @p1.users_projects.create(project: @p1, user: @u2, project_access: UsersProject::REPORTER)
-        @p1.users_projects.create(project: @p1, user: @u3, project_access: UsersProject::DEVELOPER)
+        @p1.project_members.create(project: @p1, user: @u2, access_level: ProjectMember::REPORTER)
+        @p1.project_members.create(project: @p1, user: @u3, access_level: ProjectMember::DEVELOPER)
       end
 
       it "should deny for developer master-specific actions" do
@@ -73,8 +73,8 @@ describe Project do
 
     describe "Master Rules" do
       before do
-        @p1.users_projects.create(project: @p1, user: @u2, project_access: UsersProject::DEVELOPER)
-        @p1.users_projects.create(project: @p1, user: @u3, project_access: UsersProject::MASTER)
+        @p1.project_members.create(project: @p1, user: @u2, access_level: ProjectMember::DEVELOPER)
+        @p1.project_members.create(project: @p1, user: @u3, access_level: ProjectMember::MASTER)
       end
 
       it "should deny for developer master-specific actions" do
@@ -92,8 +92,8 @@ describe Project do
 
     describe "Admin Rules" do
       before do
-        @p1.users_projects.create(project: @p1, user: @u2, project_access: UsersProject::DEVELOPER)
-        @p1.users_projects.create(project: @p1, user: @u3, project_access: UsersProject::MASTER)
+        @p1.project_members.create(project: @p1, user: @u2, access_level: ProjectMember::DEVELOPER)
+        @p1.project_members.create(project: @p1, user: @u3, access_level: ProjectMember::MASTER)
       end
 
       it "should deny for masters admin-specific actions" do
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 1c11ac395672924d2ec9f02e25adf5b486393fb6..21800ab98ff9cb867c79cbdf50edcc0e76cfa36b 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -38,7 +38,7 @@ describe Project do
     it { should have_many(:merge_requests).dependent(:destroy) }
     it { should have_many(:issues).dependent(:destroy) }
     it { should have_many(:milestones).dependent(:destroy) }
-    it { should have_many(:users_projects).dependent(:destroy) }
+    it { should have_many(:project_members).dependent(:destroy) }
     it { should have_many(:notes).dependent(:destroy) }
     it { should have_many(:snippets).class_name('ProjectSnippet').dependent(:destroy) }
     it { should have_many(:deploy_keys_projects).dependent(:destroy) }
diff --git a/spec/models/system_hook_spec.rb b/spec/models/system_hook_spec.rb
index 2b98acdeb6c332c6690b7aa2f5d8a736f60457b3..4ab5261dc9d1397e4044973e823575c966e26a01 100644
--- a/spec/models/system_hook_spec.rb
+++ b/spec/models/system_hook_spec.rb
@@ -58,7 +58,7 @@ describe SystemHook do
       user = create(:user)
       project = create(:project)
       project.team << [user, :master]
-      project.users_projects.destroy_all
+      project.project_members.destroy_all
       WebMock.should have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once
     end
   end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 7221328a45f27f4af425b865dd5b188024108e33..0250014bc21cc4aa200e09d748621c9767e6bb81 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -52,7 +52,7 @@ describe User do
   describe "Associations" do
     it { should have_one(:namespace) }
     it { should have_many(:snippets).class_name('Snippet').dependent(:destroy) }
-    it { should have_many(:users_projects).dependent(:destroy) }
+    it { should have_many(:project_members).dependent(:destroy) }
     it { should have_many(:groups) }
     it { should have_many(:keys).dependent(:destroy) }
     it { should have_many(:events).class_name('Event').dependent(:destroy) }
@@ -182,7 +182,7 @@ describe User do
       @group = create :group
       @group.add_owner(@user)
 
-      @group.add_user(@user2, UsersGroup::OWNER)
+      @group.add_user(@user2, GroupMember::OWNER)
     end
 
     it { @user2.several_namespaces?.should be_true }
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index e7f91c5e46e34c286f71aa3a85f6efda00d84ae4..caded2c92899a52fa2751d7fd0e054ac1dda80c7 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -7,8 +7,8 @@ describe API::API, api: true  do
   let(:user) { create(:user) }
   let(:user2) { create(:user) }
   let!(:project) { create(:project, creator_id: user.id) }
-  let!(:master) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
-  let!(:guest) { create(:users_project, user: user2, project: project, project_access: UsersProject::GUEST) }
+  let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) }
+  let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) }
   let!(:branch_name) { 'feature' }
   let!(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
 
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index b56269d275d475b7b21313c7a19f221890621d60..38e0a284c36e57fafca6e6a43ee3ad8ba1a1e60d 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -6,8 +6,8 @@ describe API::API, api: true  do
   let(:user) { create(:user) }
   let(:user2) { create(:user) }
   let!(:project) { create(:project, creator_id: user.id) }
-  let!(:master) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
-  let!(:guest) { create(:users_project, user: user2, project: project, project_access: UsersProject::GUEST) }
+  let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) }
+  let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) }
 
   before { project.team << [user, :reporter] }
 
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index f27a60e4bc02901f0a495206c98411d4be55455a..42ccad71aafdf586a2f5968d7d0ddfcc8b090e1a 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -174,10 +174,10 @@ describe API::API, api: true  do
     let(:guest) { create(:user) }
     let!(:group_with_members) do
       group = create(:group)
-      group.add_users([reporter.id], UsersGroup::REPORTER)
-      group.add_users([developer.id], UsersGroup::DEVELOPER)
-      group.add_users([master.id], UsersGroup::MASTER)
-      group.add_users([guest.id], UsersGroup::GUEST)
+      group.add_users([reporter.id], GroupMember::REPORTER)
+      group.add_users([developer.id], GroupMember::DEVELOPER)
+      group.add_users([master.id], GroupMember::MASTER)
+      group.add_users([guest.id], GroupMember::GUEST)
       group
     end
     let!(:group_no_members) { create(:group) }
@@ -195,11 +195,11 @@ describe API::API, api: true  do
             response.status.should == 200
             json_response.should be_an Array
             json_response.size.should == 5
-            json_response.find { |e| e['id']==owner.id }['access_level'].should == UsersGroup::OWNER
-            json_response.find { |e| e['id']==reporter.id }['access_level'].should == UsersGroup::REPORTER
-            json_response.find { |e| e['id']==developer.id }['access_level'].should == UsersGroup::DEVELOPER
-            json_response.find { |e| e['id']==master.id }['access_level'].should == UsersGroup::MASTER
-            json_response.find { |e| e['id']==guest.id }['access_level'].should == UsersGroup::GUEST
+            json_response.find { |e| e['id']==owner.id }['access_level'].should == GroupMember::OWNER
+            json_response.find { |e| e['id']==reporter.id }['access_level'].should == GroupMember::REPORTER
+            json_response.find { |e| e['id']==developer.id }['access_level'].should == GroupMember::DEVELOPER
+            json_response.find { |e| e['id']==master.id }['access_level'].should == GroupMember::MASTER
+            json_response.find { |e| e['id']==guest.id }['access_level'].should == GroupMember::GUEST
           end
         end
 
@@ -213,29 +213,29 @@ describe API::API, api: true  do
     describe "POST /groups/:id/members" do
       context "when not a member of the group" do
         it "should not add guest as member of group_no_members when adding being done by person outside the group" do
-          post api("/groups/#{group_no_members.id}/members", reporter), user_id: guest.id, access_level: UsersGroup::MASTER
+          post api("/groups/#{group_no_members.id}/members", reporter), user_id: guest.id, access_level: GroupMember::MASTER
           response.status.should == 403
         end
       end
 
       context "when a member of the group" do
         it "should return ok and add new member" do
-          count_before=group_no_members.users_groups.count
+          count_before=group_no_members.group_members.count
           new_user = create(:user)
-          post api("/groups/#{group_no_members.id}/members", owner), user_id: new_user.id, access_level: UsersGroup::MASTER
+          post api("/groups/#{group_no_members.id}/members", owner), user_id: new_user.id, access_level: GroupMember::MASTER
           response.status.should == 201
           json_response['name'].should == new_user.name
-          json_response['access_level'].should == UsersGroup::MASTER
-          group_no_members.users_groups.count.should == count_before + 1
+          json_response['access_level'].should == GroupMember::MASTER
+          group_no_members.group_members.count.should == count_before + 1
         end
 
         it "should return error if member already exists" do
-          post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: UsersGroup::MASTER
+          post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: GroupMember::MASTER
           response.status.should == 409
         end
 
         it "should return a 400 error when user id is not given" do
-          post api("/groups/#{group_no_members.id}/members", owner), access_level: UsersGroup::MASTER
+          post api("/groups/#{group_no_members.id}/members", owner), access_level: GroupMember::MASTER
           response.status.should == 400
         end
 
@@ -262,10 +262,10 @@ describe API::API, api: true  do
 
       context "when a member of the group" do
         it "should delete guest's membership of group" do
-          count_before=group_with_members.users_groups.count
+          count_before=group_with_members.group_members.count
           delete api("/groups/#{group_with_members.id}/members/#{guest.id}", owner)
           response.status.should == 200
-          group_with_members.users_groups.count.should == count_before - 1
+          group_with_members.group_members.count.should == count_before - 1
         end
 
         it "should return a 404 error when user id is not known" do
diff --git a/spec/requests/api/project_members_spec.rb b/spec/requests/api/project_members_spec.rb
index 3c480c2ac4b8b0eed700a432d6ee11f92afb157d..836f21f3e0bae6b1fc0ed2a2edf8a64c941f209c 100644
--- a/spec/requests/api/project_members_spec.rb
+++ b/spec/requests/api/project_members_spec.rb
@@ -6,12 +6,12 @@ describe API::API, api: true  do
   let(:user2) { create(:user) }
   let(:user3) { create(:user) }
   let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
-  let(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
-  let(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) }
+  let(:project_member) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) }
+  let(:project_member2) { create(:project_member, user: user3, project: project, access_level: ProjectMember::DEVELOPER) }
 
   describe "GET /projects/:id/members" do
-    before { users_project }
-    before { users_project2 }
+    before { project_member }
+    before { project_member2 }
 
     it "should return project team members" do
       get api("/projects/#{project.id}/members", user)
@@ -36,13 +36,13 @@ describe API::API, api: true  do
   end
 
   describe "GET /projects/:id/members/:user_id" do
-    before { users_project }
+    before { project_member }
 
     it "should return project team member" do
       get api("/projects/#{project.id}/members/#{user.id}", user)
       response.status.should == 200
       json_response['username'].should == user.username
-      json_response['access_level'].should == UsersProject::MASTER
+      json_response['access_level'].should == ProjectMember::MASTER
     end
 
     it "should return a 404 error if user id not found" do
@@ -55,29 +55,29 @@ describe API::API, api: true  do
     it "should add user to project team" do
       expect {
         post api("/projects/#{project.id}/members", user), user_id: user2.id,
-          access_level: UsersProject::DEVELOPER
-      }.to change { UsersProject.count }.by(1)
+          access_level: ProjectMember::DEVELOPER
+      }.to change { ProjectMember.count }.by(1)
 
       response.status.should == 201
       json_response['username'].should == user2.username
-      json_response['access_level'].should == UsersProject::DEVELOPER
+      json_response['access_level'].should == ProjectMember::DEVELOPER
     end
 
     it "should return a 201 status if user is already project member" do
       post api("/projects/#{project.id}/members", user), user_id: user2.id,
-        access_level: UsersProject::DEVELOPER
+        access_level: ProjectMember::DEVELOPER
       expect {
         post api("/projects/#{project.id}/members", user), user_id: user2.id,
-          access_level: UsersProject::DEVELOPER
-      }.not_to change { UsersProject.count }.by(1)
+          access_level: ProjectMember::DEVELOPER
+      }.not_to change { ProjectMember.count }.by(1)
 
       response.status.should == 201
       json_response['username'].should == user2.username
-      json_response['access_level'].should == UsersProject::DEVELOPER
+      json_response['access_level'].should == ProjectMember::DEVELOPER
     end
 
     it "should return a 400 error when user id is not given" do
-      post api("/projects/#{project.id}/members", user), access_level: UsersProject::MASTER
+      post api("/projects/#{project.id}/members", user), access_level: ProjectMember::MASTER
       response.status.should == 400
     end
 
@@ -93,17 +93,17 @@ describe API::API, api: true  do
   end
 
   describe "PUT /projects/:id/members/:user_id" do
-    before { users_project2 }
+    before { project_member2 }
 
     it "should update project team member" do
-      put api("/projects/#{project.id}/members/#{user3.id}", user), access_level: UsersProject::MASTER
+      put api("/projects/#{project.id}/members/#{user3.id}", user), access_level: ProjectMember::MASTER
       response.status.should == 200
       json_response['username'].should == user3.username
-      json_response['access_level'].should == UsersProject::MASTER
+      json_response['access_level'].should == ProjectMember::MASTER
     end
 
     it "should return a 404 error if user_id is not found" do
-      put api("/projects/#{project.id}/members/1234", user), access_level: UsersProject::MASTER
+      put api("/projects/#{project.id}/members/1234", user), access_level: ProjectMember::MASTER
       response.status.should == 404
     end
 
@@ -119,20 +119,20 @@ describe API::API, api: true  do
   end
 
   describe "DELETE /projects/:id/members/:user_id" do
-    before { users_project }
-    before { users_project2 }
+    before { project_member }
+    before { project_member2 }
 
     it "should remove user from project team" do
       expect {
         delete api("/projects/#{project.id}/members/#{user3.id}", user)
-      }.to change { UsersProject.count }.by(-1)
+      }.to change { ProjectMember.count }.by(-1)
     end
 
     it "should return 200 if team member is not part of a project" do
       delete api("/projects/#{project.id}/members/#{user3.id}", user)
       expect {
         delete api("/projects/#{project.id}/members/#{user3.id}", user)
-      }.to_not change { UsersProject.count }.by(1)
+      }.to_not change { ProjectMember.count }.by(1)
     end
 
     it "should return 200 if team member already removed" do
@@ -144,7 +144,7 @@ describe API::API, api: true  do
     it "should return 200 OK when the user was not member" do
       expect {
         delete api("/projects/#{project.id}/members/1000000", user)
-      }.to change { UsersProject.count }.by(0)
+      }.to change { ProjectMember.count }.by(0)
       response.status.should == 200
       json_response['message'].should == "Access revoked"
       json_response['id'].should == 1000000
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 058b831e783c2036897b1e5a9b53814c8414d61d..5575da86c2e558d640ab2c9150a1ece2a37b184e 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -8,8 +8,8 @@ describe API::API, api: true  do
   let(:admin) { create(:admin) }
   let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
   let(:snippet) { create(:project_snippet, author: user, project: project, title: 'example') }
-  let(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
-  let(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) }
+  let(:project_member) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) }
+  let(:project_member2) { create(:project_member, user: user3, project: project, access_level: ProjectMember::DEVELOPER) }
 
   describe "GET /projects" do
     before { project }
@@ -254,7 +254,7 @@ describe API::API, api: true  do
 
   describe "GET /projects/:id" do
     before { project }
-    before { users_project }
+    before { project_member }
 
     it "should return a project by id" do
       get api("/projects/#{project.id}", user)
@@ -283,7 +283,10 @@ describe API::API, api: true  do
 
     describe 'permissions' do
       context 'personal project' do
-        before { get api("/projects/#{project.id}", user) }
+        before do
+          project.team << [user, :master]
+          get api("/projects/#{project.id}", user)
+        end
 
         it { response.status.should == 200 }
         it { json_response['permissions']["project_access"]["access_level"].should == Gitlab::Access::MASTER }
@@ -305,7 +308,7 @@ describe API::API, api: true  do
   end
 
   describe "GET /projects/:id/events" do
-    before { users_project }
+    before { project_member }
 
     it "should return a project events" do
       get api("/projects/#{project.id}/events", user)
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 17173aaeeace85317c695ed289243e5af309aff1..a339dbfe9dbd871a5466c7b16134572671d0c508 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -8,8 +8,8 @@ describe API::API, api: true  do
   let(:user) { create(:user) }
   let(:user2) { create(:user) }
   let!(:project) { create(:project, creator_id: user.id) }
-  let!(:master) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
-  let!(:guest) { create(:users_project, user: user2, project: project, project_access: UsersProject::GUEST) }
+  let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) }
+  let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) }
 
   before { project.team << [user, :reporter] }
 
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index df355f6f07af40393ce374437a8113b2a2eff1c3..f8377650e0a6193a2200f93868e4850d55bbf248 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -64,12 +64,12 @@ describe NotificationService do
 
         before do
           note.project.namespace_id = group.id
-          note.project.group.add_user(@u_watcher, UsersGroup::MASTER)
+          note.project.group.add_user(@u_watcher, GroupMember::MASTER)
           note.project.save
-          user_project = note.project.users_projects.find_by_user_id(@u_watcher.id)
+          user_project = note.project.project_members.find_by_user_id(@u_watcher.id)
           user_project.notification_level = Notification::N_PARTICIPATING
           user_project.save
-          user_group = note.project.group.users_groups.find_by_user_id(@u_watcher.id)
+          user_group = note.project.group.group_members.find_by_user_id(@u_watcher.id)
           user_group.notification_level = Notification::N_GLOBAL
           user_group.save
         end
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index 7497bdb0b3ce3cebb3d477895372eb73e9cc38e7..573446d3a190dab2c564ee60ea7a711f2af2fd69 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
 describe SystemHooksService do
   let (:user)          { create :user }
   let (:project)       { create :project }
-  let (:users_project) { create :users_project }
+  let (:project_member) { create :project_member }
   let (:key)           { create(:key, user: user) }
 
   context 'event data' do
@@ -11,8 +11,8 @@ describe SystemHooksService do
     it { event_data(user, :destroy).should include(:event_name, :name, :created_at, :email, :user_id) }
     it { event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
     it { event_data(project, :destroy).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
-    it { event_data(users_project, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access, :project_visibility) }
-    it { event_data(users_project, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :project_access, :project_visibility) }
+    it { event_data(project_member, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
+    it { event_data(project_member, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) }
     it { event_data(key, :create).should include(:username, :key, :id) }
     it { event_data(key, :destroy).should include(:username, :key, :id) }
   end
@@ -22,8 +22,8 @@ describe SystemHooksService do
     it { event_name(user, :destroy).should eq "user_destroy" }
     it { event_name(project, :create).should eq "project_create" }
     it { event_name(project, :destroy).should eq "project_destroy" }
-    it { event_name(users_project, :create).should eq "user_add_to_team" }
-    it { event_name(users_project, :destroy).should eq "user_remove_from_team" }
+    it { event_name(project_member, :create).should eq "user_add_to_team" }
+    it { event_name(project_member, :destroy).should eq "user_remove_from_team" }
     it { event_name(key, :create).should eq 'key_create' }
     it { event_name(key, :destroy).should eq 'key_destroy' }
   end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 6934cabadfaea1d17c0e7e5b6db0e93df5059d41..60322b67a798559747611c154d2d86fa9dde6d50 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,14 +1,14 @@
-# This file is copied to spec/ when you run 'rails generate rspec:install'
-ENV["RAILS_ENV"] ||= 'test'
-require File.expand_path("../../config/environment", __FILE__)
-
-require 'simplecov' unless ENV['CI']
+if ENV['SIMPLECOV']
+  require 'simplecov'
+end
 
-if ENV['TRAVIS']
+if ENV['COVERALLS']
   require 'coveralls'
-  Coveralls.wear!
+  Coveralls.wear_merged!('rails')
 end
 
+ENV["RAILS_ENV"] ||= 'test'
+require File.expand_path("../../config/environment", __FILE__)
 require 'rspec/rails'
 require 'capybara/rails'
 require 'capybara/rspec'