//  [go]
func TestAuthorizeUser(t *testing.T) {
	t.Parallel()

	newUser := &fleet.User{}
	user := &fleet.User{ID: 42}
	newTeamUser := &fleet.User{
		Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver}},
	}
	teamAdmin := &fleet.User{
		ID:    101,
		Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleAdmin}},
	}
	teamObserver := &fleet.User{
		ID:    102,
		Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver}},
	}

	runTestCases(t, []authTestCase{
		{user: nil, object: user, action: read, allow: false},
		{user: nil, object: user, action: write, allow: false},
		{user: nil, object: user, action: writeRole, allow: false},
		{user: nil, object: user, action: changePwd, allow: false},
		{user: nil, object: newUser, action: write, allow: false},

		// Global admin can read/write all and create new.
		{user: test.UserAdmin, object: user, action: read, allow: true},
		{user: test.UserAdmin, object: user, action: write, allow: true},
		{user: test.UserAdmin, object: user, action: writeRole, allow: true},
		{user: test.UserAdmin, object: user, action: changePwd, allow: true},
		{user: test.UserAdmin, object: newUser, action: write, allow: true},
		{user: test.UserAdmin, object: test.UserAdmin, action: read, allow: true},
		{user: test.UserAdmin, object: test.UserAdmin, action: write, allow: true},
		{user: test.UserAdmin, object: test.UserAdmin, action: writeRole, allow: true},
		{user: test.UserAdmin, object: test.UserAdmin, action: changePwd, allow: true},

		// Global maintainers cannot read/write users.
		{user: test.UserMaintainer, object: user, action: read, allow: false},
		{user: test.UserMaintainer, object: user, action: write, allow: false},
		{user: test.UserMaintainer, object: user, action: writeRole, allow: false},
		{user: test.UserMaintainer, object: user, action: changePwd, allow: false},
		// Global maintainers cannot create users.
		{user: test.UserMaintainer, object: newUser, action: write, allow: false},
		// Global maintainers can read/write itself (besides roles).
		{user: test.UserMaintainer, object: test.UserMaintainer, action: read, allow: true},
		{user: test.UserMaintainer, object: test.UserMaintainer, action: write, allow: true},
		{user: test.UserMaintainer, object: test.UserMaintainer, action: writeRole, allow: false},
		{user: test.UserMaintainer, object: test.UserMaintainer, action: changePwd, allow: true},

		// Users without roles cannot read/write users.
		{user: test.UserNoRoles, object: user, action: read, allow: false},
		{user: test.UserNoRoles, object: user, action: write, allow: false},
		{user: test.UserNoRoles, object: user, action: writeRole, allow: false},
		{user: test.UserNoRoles, object: user, action: changePwd, allow: false},
		// User without roles cannot add new users.
		{user: test.UserNoRoles, object: newUser, action: write, allow: false},
		// User without roles can read/write itself (besides roles).
		{user: test.UserNoRoles, object: test.UserNoRoles, action: read, allow: true},
		{user: test.UserNoRoles, object: test.UserNoRoles, action: write, allow: true},
		{user: test.UserNoRoles, object: test.UserNoRoles, action: writeRole, allow: false},
		{user: test.UserNoRoles, object: test.UserNoRoles, action: changePwd, allow: true},

		// Global observers cannot read/write users.
		{user: test.UserObserver, object: user, action: read, allow: false},
		{user: test.UserObserver, object: user, action: write, allow: false},
		{user: test.UserObserver, object: user, action: writeRole, allow: false},
		{user: test.UserObserver, object: user, action: changePwd, allow: false},
		// Global observers cannot create users.
		{user: test.UserObserver, object: newUser, action: write, allow: false},
		// Global observers can read/write itself (besides roles).
		{user: test.UserObserver, object: test.UserObserver, action: read, allow: true},
		{user: test.UserObserver, object: test.UserObserver, action: write, allow: true},
		{user: test.UserObserver, object: test.UserObserver, action: writeRole, allow: false},
		{user: test.UserObserver, object: test.UserObserver, action: changePwd, allow: true},

		// Team admins cannot read/write global users.
		{user: teamAdmin, object: user, action: read, allow: false},
		{user: teamAdmin, object: user, action: write, allow: false},
		{user: teamAdmin, object: user, action: writeRole, allow: false},
		{user: teamAdmin, object: user, action: changePwd, allow: false},
		// Team admins cannot create new global users.
		{user: teamAdmin, object: newUser, action: write, allow: false},
		// Team admins can read/write team users (except change their password).
		{user: teamAdmin, object: teamObserver, action: read, allow: true},
		{user: teamAdmin, object: teamObserver, action: write, allow: true},
		{user: teamAdmin, object: teamObserver, action: writeRole, allow: true},
		{user: teamAdmin, object: teamObserver, action: changePwd, allow: false},
		// Team admins can add new users to the team.
		{user: teamAdmin, object: newTeamUser, action: write, allow: true},
		// Team admins can read/write itself.
		{user: teamAdmin, object: teamAdmin, action: read, allow: true},
		{user: teamAdmin, object: teamAdmin, action: write, allow: true},
		{user: teamAdmin, object: teamAdmin, action: writeRole, allow: true},
		{user: teamAdmin, object: teamAdmin, action: changePwd, allow: true},
	})
}