Skip to content

Commit

Permalink
Add create_project, add_team_member
Browse files Browse the repository at this point in the history
  • Loading branch information
ifournight committed Apr 6, 2017
1 parent 3904c4e commit d44a9af
Show file tree
Hide file tree
Showing 13 changed files with 358 additions and 30 deletions.
79 changes: 69 additions & 10 deletions app/models/access.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,77 @@ class Access < ApplicationRecord
belongs_to :subject, polymorphic: true

ACCESS_TYPE = {
PROJECT_COLLABORATOR: 'access_type_project_collaborator',
CREATE_PROJECT: 'access_type_create_project',
DELETE_PROJECT: 'access_type_delete_project',
READ_PROJECT: 'access_type_read_project',
WRITE_PROJECT: 'access_type_write_project',
INVITE_JOIN_TEAM: 'access_type_invite_join_team',
TEAM_MEMBER_MANAGE: 'access_type_team_member_manage',
TEAM_MEMBER_AUTHORITY_MANAGE: 'access_type_team_member_authority_manage',
SLACK_LINKING: 'access_type_slack_linking'
PROJECT_COLLABORATOR: 'access_type_project_collaborator', #特殊:标记加入Project
DELETE_PROJECT: 'access_type_delete_project', # 删除指定Project
READ_PROJECT: 'access_type_read_project', # 只读Project
WRITE_PROJECT: 'access_type_write_project', # 在Project中创建(任务等...
PROJECT_COLLABORATOR_MANAGE: 'access_type_projecdt_collaborator_manage',

CREATE_TEAM_PROJECTS: 'access_type_create_projects', # 在团队中创建Project
DELETE_TEAM_PROJECTS: 'access_type_delete_projects', #在团队中删除任意Project
INVITE_JOIN_TEAM: 'access_type_invite_join_team', #邀请新的成员
TEAM_MEMBER_MANAGE: 'access_type_team_member_manage', #成员管理:包括新加/删除成员,管理成员参与的Project
TEAM_MEMBER_AUTHORITY_MANAGE: 'access_type_team_member_authority_manage', #成员权限管理
READ_TEAM_MEMBER: 'read_team_memeber'
}.freeze

ACCESS_GROUP_SUPERADMIN = ACCESS_TYPE.values.freeze
AT = ACCESS_TYPE

ACCESS_GROUP_PROJECT_MANAGER = {
PROJECT:
[
AT[:PROJECT_COLLABORATOR_MANAGE]
]
}.freeze

ACCESS_GROUP_GUEST = {
TEAM: [],
PROJECT:
[
AT[:PROJECT_COLLABORATOR],
AT[:READ_PROJECT],
AT[:WRITE_PROJECT]
]
}.freeze

ACCESS_GROUP_MEMBER = {
TEAM:
[
AT[:INVITE_JOIN_TEAM],
AT[:CREATE_TEAM_PROJECTS],
AT[:READ_TEAM_MEMBER]
],
PROJECT:
[
AT[:PROJECT_COLLABORATOR],
AT[:READ_PROJECT],
AT[:WRITE_PROJECT],
AT[:DELETE_PROJECT]
]
}.freeze

ACCESS_GROUP_ADMIN = ACCESS_GROUP_MEMBER.deep_merge(
TEAM:
[
AT[:INVITE_JOIN_TEAM],
AT[:CREATE_TEAM_PROJECTS],
AT[:READ_TEAM_MEMBER],
AT[:TEAM_MEMBER_MANAGE],
AT[:TEAM_MEMBER_AUTHORITY_MANAGE]
]
).freeze

ACCESS_GROUP_SUPERADMIN = ACCESS_GROUP_ADMIN.deep_merge(
TEAM:
[
AT[:INVITE_JOIN_TEAM],
AT[:CREATE_TEAM_PROJECTS],
AT[:READ_TEAM_MEMBER],
AT[:TEAM_MEMBER_MANAGE],
AT[:TEAM_MEMBER_AUTHORITY_MANAGE],
AT[:DELETE_TEAM_PROJECTS]
]
).freeze

validates :access_type, presence: true
validates :access_type, inclusion: { in: ACCESS_TYPE.values }
Expand Down
96 changes: 96 additions & 0 deletions app/models/add_team_member.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
class AddTeamMember
include ActiveModel::Model

attr_accessor(
:team_id,
:authorizer_id,
:member_id,
:member_authority
)

validates :team_id, presence: true
validates :authorizer_id, presence: true
validates :member_id, presence: true
validates :member_authority, presence: true
validates :member_authority, inclusion: { in: TeamMembership::MEMBERSHIP_AUTHORITY.values }

def do
return nil if invalid?
unless valid_team
errors[:team_id] << 'Invalid team id'
nil
end
unless valid_user(member_id)
errors[:member_id] << 'Invalid memeber id'
nil
end
unless valid_user(authorizer_id)
errors[:authorizer_id] << 'Invalid authorizer_id'
end

@user = User.find(member_id)
@authorizer = User.find(authorizer_id)
@team = Team.find(team_id)

if @team.members.include?(@user)
errors[:member_id] << 'already a member'
nil
end

unless check_authorizer_access
errors[:authorizer_id] << "Authorizer doesn't have acess to add member"
nil
end

add_team_member
authority_team_memeber

@user
end

def valid_team
true
end

def valid_user(_user_id)
true
end

def check_authorizer_access
unless Access.has_access?(authorizer_id, team_id, 'Team', Access::ACCESS_TYPE[:TEAM_MEMBER_MANAGE])
errors[:authorizer_id] <<
"Authorizer(User) #{@authorizer.name} don't have access to add a member in team #{@team.name}."
false
end
true
end

def add_team_member
TeamMembership.create(
team_id: team_id,
member_id: member_id,
member_authority: member_authority
)
end

def authority_team_memeber
accesses = []
case member_authority
when TeamMembership::MEMBERSHIP_AUTHORITY[:ADMIN]
accesses = Access::ACCESS_GROUP_ADMIN[:TEAM]
when TeamMembership::MEMBERSHIP_AUTHORITY[:MEMBER]
accesses = Access::ACCESS_GROUP_MEMBER[:TEAM]
when TeamMemberShip::MEMBERSHIP_AUTHORITY[:GUEST]
accesses = Access::ACCESS_GROUP_GUEST[:TEAM]
end

accesses.each do |access_type|
Access.create(
user_id: member_id,
subject_id: @team.id,
subject_type: @team.class.name,
access_type: access_type
)
end
end
end
81 changes: 81 additions & 0 deletions app/models/create_project.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
class CreateProject
include ActiveModel::Model

validates :name, presence: true

attr_accessor(
:project_name,
:desc,
:team_id,
:creator_id
)

def do
unless user_valid?
errors[:creator_id] << 'Invalid Creator ID'
return nil
end
unless team_valid?
errors[:team_id] << 'Invalid Team Invalid'
return nil
end

@user = User.find(creator_id)
@team = Team.find(team_id)

return nil unless check_user_access

@project = create_project
make_creator_collaborator
@project
end

private

def user_valid?
true
end

def team_valid?
true
end

def check_user_access
unless @team.members.include?(@user)
errors[:creator_id] <<
"Creator(User) #{@user.name} can't create project being not a memeber of team #{@team.name}."
return false
end

unless Access.has_access?(creator_id, team_id, 'Team', Access::ACCESS_TYPE[:CREATE_TEAM_PROJECTS])
errors[:creator_d] <<
"Creator(User) #{@user.name} don't have access to create a project."
return false
end

true
end

def create_project
Project.create(
creator_id: creator_id,
name: project_name,
desc: desc,
team_id: team_id
)
end

def make_creator_collaborator
accesses = Access::ACCESS_GROUP_MEMBER[:PROJECT]
.dup
.concat(Access::ACCESS_GROUP_PROJECT_MANAGER[:PROJECT].dup)
accesses.each do |access_type|
Access.create(
user_id: @user.id,
subject_id: @project.id,
subject_type: @project.class.name,
access_type: access_type
)
end
end
end
2 changes: 1 addition & 1 deletion app/models/create_team.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def make_creator_superadmin
)

# use prefabed access group to batchly factory accesses
Access::ACCESS_GROUP_SUPERADMIN.each do |access_type|
Access::ACCESS_GROUP_SUPERADMIN[:TEAM].each do |access_type|
Access.create(
user_id: creator_id,
subject_id: @team.id,
Expand Down
9 changes: 9 additions & 0 deletions app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,14 @@ class Project < ApplicationRecord
belongs_to :creator, class_name: 'User'
has_many :todos

def collaborators
Access
.where(
subject_id: id,
subject_type: self.class.name,
access_type: Access::ACCESS_TYPE[:PROJECT_COLLABORATOR]
).to_a.map(&:user)
end

validates :name, presence: true
end
19 changes: 19 additions & 0 deletions app/quries/project_collaborator_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class ProjectCollaboratorQuery
def find_project_collaborators(project)
temp = Access
.where(
subject_id: project.id,
subject_type: project.class.name,
access_type: Access::ACESS_TYPE[:PROJECT_COLLABORATOR]
)
.to_a
if block_given?
temp.each do |access|
yield(access.user)
end
else
temp.map(&:user)
end
end
end
end
8 changes: 8 additions & 0 deletions app/quries/team_member_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ def find_team_super_admin(team, &block)
)
end

def fine_team_member(team, &block)
find_given_type_team_member(
team,
TeamMembership::MEMBERSHIP_AUTHORITY[:MEMBER],
&block
)
end

private

def find_given_type_team_member(team, member_authority)
Expand Down
20 changes: 7 additions & 13 deletions spec/factories.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
FactoryGirl.define do
factory :access do
user
access_type Access::ACCESS_TYPE[:PROJECT_COLLABORATOR]
association :subject, factory: :project
factory :user, aliases: [:creator, :owner] do
sequence(:name) { |n| "User #{n}" }
end

factory :team do
owner
sequence(:name) { |n| "Team #{n}" }
end

factory :project do
Expand All @@ -11,11 +14,6 @@
sequence(:name) { |n| "Project #{n}" }
end

factory :team do
owner
sequence(:name) { |n| "Team #{n}" }
end

factory :todo, aliases: [:subject] do
project
creator
Expand All @@ -26,10 +24,6 @@
end
end

factory :user, aliases: [:creator, :owner] do
sequence(:name) { |n| "User #{n}" }
end

factory :activity do
user
subject
Expand Down
10 changes: 6 additions & 4 deletions spec/models/access_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
user = create(:user)
team = create(:team, owner: user)
project = create(:project, team: team, creator: user)
_access = create(:access,
user: user,
type: Access::ACCESS_TYPE[:PROJECT_COLLABORATOR],
subject: project)
_access = Access.create(
user_id: user.id,
type: Access::ACCESS_TYPE[:PROJECT_COLLABORATOR],
subject_id: project.id,
subject_type: project.class.name
)

result = Access.has_access?(user.id,
project.id,
Expand Down
Loading

0 comments on commit d44a9af

Please sign in to comment.