From 8a86fe7bb0785ea69e591fd287430eb5448ac64e Mon Sep 17 00:00:00 2001 From: Andrey Kumanyaev <me@zzet.org> Date: Sat, 19 Jan 2013 21:06:50 +0400 Subject: [PATCH] Added UserTeam core models (team and m-t-m relationships) and updated other models --- app/models/concerns/issuable.rb | 1 + app/models/project.rb | 39 +++++---- app/models/user.rb | 35 +++++--- app/models/user_team.rb | 87 +++++++++++++++++++ app/models/user_team_project_relationship.rb | 24 +++++ app/models/user_team_user_relationship.rb | 15 ++++ app/models/users_project.rb | 3 + .../20121219183753_create_user_teams.rb | 11 +++ ..._create_user_team_project_relationships.rb | 11 +++ ...453_create_user_team_user_relationships.rb | 12 +++ db/schema.rb | 25 ++++++ .../user_team_project_relationship_spec.rb | 5 ++ spec/models/user_team_spec.rb | 5 ++ .../user_team_user_relationship_spec.rb | 5 ++ 14 files changed, 249 insertions(+), 29 deletions(-) create mode 100644 app/models/user_team.rb create mode 100644 app/models/user_team_project_relationship.rb create mode 100644 app/models/user_team_user_relationship.rb create mode 100644 db/migrate/20121219183753_create_user_teams.rb create mode 100644 db/migrate/20121220064104_create_user_team_project_relationships.rb create mode 100644 db/migrate/20121220064453_create_user_team_user_relationships.rb create mode 100644 spec/models/user_team_project_relationship_spec.rb create mode 100644 spec/models/user_team_spec.rb create mode 100644 spec/models/user_team_user_relationship_spec.rb diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index d1717d3bb..8872cf59a 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -22,6 +22,7 @@ module Issuable scope :opened, where(closed: false) scope :closed, where(closed: true) scope :of_group, ->(group) { where(project_id: group.project_ids) } + scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) } scope :assigned, ->(u) { where(assignee_id: u.id)} scope :recent, order("created_at DESC") diff --git a/app/models/project.rb b/app/models/project.rb index fa38093b7..fa314d9c5 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -33,28 +33,31 @@ class Project < ActiveRecord::Base attr_accessor :error_code # Relations - belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'" + belongs_to :creator, foreign_key: "creator_id", class_name: "User" + belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'" belongs_to :namespace - belongs_to :creator, - class_name: "User", - foreign_key: "creator_id" - - has_many :users, through: :users_projects - has_many :events, dependent: :destroy - has_many :merge_requests, dependent: :destroy - has_many :issues, dependent: :destroy, order: "closed, created_at DESC" - has_many :milestones, dependent: :destroy - has_many :users_projects, dependent: :destroy - has_many :notes, dependent: :destroy - has_many :snippets, dependent: :destroy - has_many :deploy_keys, dependent: :destroy, foreign_key: "project_id", class_name: "Key" - has_many :hooks, dependent: :destroy, class_name: "ProjectHook" - has_many :wikis, dependent: :destroy - has_many :protected_branches, dependent: :destroy has_one :last_event, class_name: 'Event', order: 'events.created_at DESC', foreign_key: 'project_id' has_one :gitlab_ci_service, dependent: :destroy + has_many :events, dependent: :destroy + has_many :merge_requests, dependent: :destroy + has_many :issues, dependent: :destroy, order: "closed, created_at DESC" + has_many :milestones, dependent: :destroy + has_many :users_projects, dependent: :destroy + has_many :notes, dependent: :destroy + has_many :snippets, dependent: :destroy + has_many :deploy_keys, dependent: :destroy, class_name: "Key", foreign_key: "project_id" + has_many :hooks, dependent: :destroy, class_name: "ProjectHook" + has_many :wikis, dependent: :destroy + has_many :protected_branches, dependent: :destroy + has_many :user_team_project_relationships, dependent: :destroy + + has_many :users, through: :users_projects + has_many :user_teams, through: :user_team_project_relationships + has_many :user_team_user_relationships, through: :user_teams + has_many :user_teams_members, through: :user_team_user_relationships + delegate :name, to: :owner, allow_nil: true, prefix: true # Validations @@ -77,6 +80,8 @@ class Project < ActiveRecord::Base # Scopes scope :without_user, ->(user) { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) } scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) } + scope :without_team, ->(team) { where("id NOT IN (:ids)", ids: team.projects.map(&:id)) } + scope :in_team, ->(team) { where("id IN (:ids)", ids: team.projects.map(&:id)) } scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) } scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") } scope :personal, ->(user) { where(namespace_id: user.namespace_id) } diff --git a/app/models/user.rb b/app/models/user.rb index 743d7523b..16e07e9ce 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -45,18 +45,27 @@ class User < ActiveRecord::Base attr_accessor :force_random_password # Namespace for personal projects - has_one :namespace, class_name: "Namespace", foreign_key: :owner_id, conditions: 'type IS NULL', dependent: :destroy - has_many :groups, class_name: "Group", foreign_key: :owner_id - - has_many :keys, dependent: :destroy - has_many :users_projects, dependent: :destroy - has_many :issues, foreign_key: :author_id, dependent: :destroy - has_many :notes, foreign_key: :author_id, dependent: :destroy - has_many :merge_requests, foreign_key: :author_id, dependent: :destroy - has_many :events, class_name: "Event", foreign_key: :author_id, dependent: :destroy - has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC" - has_many :assigned_issues, class_name: "Issue", foreign_key: :assignee_id, dependent: :destroy - has_many :assigned_merge_requests, class_name: "MergeRequest", foreign_key: :assignee_id, dependent: :destroy + has_one :namespace, dependent: :destroy, foreign_key: :owner_id, class_name: "Namespace", conditions: 'type IS NULL' + + has_many :keys, dependent: :destroy + has_many :users_projects, dependent: :destroy + 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 + has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event" + has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue" + has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" + + has_many :groups, class_name: "Group", foreign_key: :owner_id + has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC" + + has_many :projects, through: :users_projects + + has_many :user_team_user_relationships, dependent: :destroy + + has_many :user_teams, through: :user_team_user_relationships + has_many :user_team_project_relationships, through: :user_teams + has_many :team_projects, through: :user_team_project_relationships validates :name, presence: true validates :bio, length: { within: 0..255 } @@ -80,6 +89,8 @@ class User < ActiveRecord::Base scope :blocked, where(blocked: true) scope :active, where(blocked: false) scope :alphabetically, order('name ASC') + scope :in_team, ->(team){ where(id: team.member_ids) } + scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) } # # Class methods diff --git a/app/models/user_team.rb b/app/models/user_team.rb new file mode 100644 index 000000000..d402fd22e --- /dev/null +++ b/app/models/user_team.rb @@ -0,0 +1,87 @@ +class UserTeam < ActiveRecord::Base + attr_accessible :name, :owner_id, :path + + belongs_to :owner, class_name: User + + has_many :user_team_project_relationships, dependent: :destroy + has_many :user_team_user_relationships, dependent: :destroy + + has_many :projects, through: :user_team_project_relationships + has_many :members, through: :user_team_user_relationships, source: :user + + validates :name, presence: true, uniqueness: true + validates :owner, presence: true + validates :path, uniqueness: true, presence: true, length: { within: 1..255 }, + format: { with: Gitlab::Regex.path_regex, + message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } + + scope :with_member, ->(user){ joins(:user_team_user_relationships).where(user_team_user_relationships: {user_id: user.id}) } + scope :created_by, ->(user){ where(owner_id: user) } + + class << self + def search query + where("name LIKE :query OR path LIKE :query", query: "%#{query}%") + end + + def global_id + 'GLN' + end + + def access_roles + UsersProject.access_roles + end + end + + def to_param + path + end + + def assign_to_projects(projects, access) + projects.each do |project| + assign_to_project(project, access) + end + end + + def assign_to_project(project, access) + Gitlab::UserTeamManager.assign(self, project, access) + end + + def resign_from_project(project) + Gitlab::UserTeamManager.resign(self, project) + end + + def add_members(users, access, group_admin) + users.each do |user| + add_member(user, access, group_admin) + end + end + + def add_member(user, access, group_admin) + Gitlab::UserTeamManager.add_member_into_team(self, user, access, group_admin) + end + + def remove_member(user) + Gitlab::UserTeamManager.remove_member_from_team(self, user) + end + + def max_project_access(project) + user_team_project_relationships.find_by_project_id(project).greatest_access + end + + def human_max_project_access(project) + self.class.access_roles.invert[max_project_access(project)] + end + + def default_projects_access(member) + user_team_user_relationships.find_by_user_id(member).permission + end + + def human_default_projects_access(member) + self.class.access_roles.invert[default_projects_access(member)] + end + + def admin?(member) + user_team_user_relationships.with_user(member).first.group_admin? + end + +end diff --git a/app/models/user_team_project_relationship.rb b/app/models/user_team_project_relationship.rb new file mode 100644 index 000000000..4413c492a --- /dev/null +++ b/app/models/user_team_project_relationship.rb @@ -0,0 +1,24 @@ +class UserTeamProjectRelationship < ActiveRecord::Base + attr_accessible :greatest_access, :project_id, :user_team_id + + belongs_to :user_team + belongs_to :project + + validates :project, presence: true + validates :user_team, presence: true + validate :check_greatest_access + + scope :with_project, ->(project){ where(project_id: project.id) } + + private + + def check_greatest_access + errors.add(:base, :incorrect_access_code) unless correct_access? + end + + def correct_access? + return false if greatest_access.blank? + return true if UsersProject.access_roles.has_value?(greatest_access) + false + end +end diff --git a/app/models/user_team_user_relationship.rb b/app/models/user_team_user_relationship.rb new file mode 100644 index 000000000..00d12ebf6 --- /dev/null +++ b/app/models/user_team_user_relationship.rb @@ -0,0 +1,15 @@ +class UserTeamUserRelationship < ActiveRecord::Base + attr_accessible :group_admin, :permission, :user_id, :user_team_id + + belongs_to :user_team + belongs_to :user + + validates :user_team, presence: true + validates :user, presence: true + + scope :with_user, ->(user) { where(user_id: user.id) } + + def user_name + user.name + end +end diff --git a/app/models/users_project.rb b/app/models/users_project.rb index 791462898..d282b2acb 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -39,7 +39,10 @@ class UsersProject < ActiveRecord::Base 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(&:id)) } + scope :with_user, ->(user) { where(user_id: user.id) } class << self diff --git a/db/migrate/20121219183753_create_user_teams.rb b/db/migrate/20121219183753_create_user_teams.rb new file mode 100644 index 000000000..65c4d0539 --- /dev/null +++ b/db/migrate/20121219183753_create_user_teams.rb @@ -0,0 +1,11 @@ +class CreateUserTeams < ActiveRecord::Migration + def change + create_table :user_teams do |t| + t.string :name + t.string :path + t.integer :owner_id + + t.timestamps + end + end +end diff --git a/db/migrate/20121220064104_create_user_team_project_relationships.rb b/db/migrate/20121220064104_create_user_team_project_relationships.rb new file mode 100644 index 000000000..8eb654c87 --- /dev/null +++ b/db/migrate/20121220064104_create_user_team_project_relationships.rb @@ -0,0 +1,11 @@ +class CreateUserTeamProjectRelationships < ActiveRecord::Migration + def change + create_table :user_team_project_relationships do |t| + t.integer :project_id + t.integer :user_team_id + t.integer :greatest_access + + t.timestamps + end + end +end diff --git a/db/migrate/20121220064453_create_user_team_user_relationships.rb b/db/migrate/20121220064453_create_user_team_user_relationships.rb new file mode 100644 index 000000000..7783b0ae4 --- /dev/null +++ b/db/migrate/20121220064453_create_user_team_user_relationships.rb @@ -0,0 +1,12 @@ +class CreateUserTeamUserRelationships < ActiveRecord::Migration + def change + create_table :user_team_user_relationships do |t| + t.integer :user_id + t.integer :user_team_id + t.boolean :group_admin + t.integer :permission + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 4b3a22436..88849872a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -213,6 +213,31 @@ ActiveRecord::Schema.define(:version => 20130110172407) do t.string "name" end + create_table "user_team_project_relationships", :force => true do |t| + t.integer "project_id" + t.integer "user_team_id" + t.integer "greatest_access" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "user_team_user_relationships", :force => true do |t| + t.integer "user_id" + t.integer "user_team_id" + t.boolean "group_admin" + t.integer "permission" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + + create_table "user_teams", :force => true do |t| + t.string "name" + t.string "path" + t.integer "owner_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "users", :force => true do |t| t.string "email", :default => "", :null => false t.string "encrypted_password", :default => "", :null => false diff --git a/spec/models/user_team_project_relationship_spec.rb b/spec/models/user_team_project_relationship_spec.rb new file mode 100644 index 000000000..81051d599 --- /dev/null +++ b/spec/models/user_team_project_relationship_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe UserTeamProjectRelationship do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/user_team_spec.rb b/spec/models/user_team_spec.rb new file mode 100644 index 000000000..2d1b99db6 --- /dev/null +++ b/spec/models/user_team_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe UserTeam do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/user_team_user_relationship_spec.rb b/spec/models/user_team_user_relationship_spec.rb new file mode 100644 index 000000000..309f1975e --- /dev/null +++ b/spec/models/user_team_user_relationship_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe UserTeamUserRelationship do + pending "add some examples to (or delete) #{__FILE__}" +end -- 2.30.9