mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-08 00:02:15 +01:00
Restrict roles available to invitation and member.update, fixes ST-264
This commit is contained in:
committed by
Gregor Vostrak
parent
2184b3c835
commit
313cee2db0
@@ -60,7 +60,7 @@ class InvitationController extends Controller
|
||||
$this->user(),
|
||||
$organization,
|
||||
$request->input('email'),
|
||||
$request->input('role')
|
||||
$request->getRole()->value
|
||||
);
|
||||
|
||||
return response()->json(null, 204);
|
||||
|
||||
@@ -68,7 +68,7 @@ class MemberController extends Controller
|
||||
$member->billable_rate = $request->getBillableRate();
|
||||
}
|
||||
if ($request->has('role')) {
|
||||
$member->role = $request->input('role');
|
||||
$member->role = $request->getRole()->value;
|
||||
}
|
||||
$member->save();
|
||||
|
||||
|
||||
@@ -30,9 +30,14 @@ class InvitationStoreRequest extends FormRequest
|
||||
'role' => [
|
||||
'required',
|
||||
'string',
|
||||
// TODO: placeholder role should not be allowed
|
||||
Rule::enum(Role::class),
|
||||
Rule::enum(Role::class)
|
||||
->except([Role::Owner, Role::Placeholder]),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getRole(): Role
|
||||
{
|
||||
return Role::from($this->input('role'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ class MemberUpdateRequest extends FormRequest
|
||||
return [
|
||||
'role' => [
|
||||
'string',
|
||||
// TODO: placeholder role should not be allowed
|
||||
Rule::enum(Role::class),
|
||||
Rule::enum(Role::class)
|
||||
->except([Role::Owner, Role::Placeholder]),
|
||||
],
|
||||
'billable_rate' => [
|
||||
'nullable',
|
||||
@@ -52,4 +52,9 @@ class MemberUpdateRequest extends FormRequest
|
||||
return $this->has('billable_rate_update_time_entries') &&
|
||||
$this->input('billable_rate_update_time_entries') === 'true';
|
||||
}
|
||||
|
||||
public function getRole(): Role
|
||||
{
|
||||
return Role::from($this->input('role'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,7 @@ class InvitationEndpointTest extends ApiEndpointTestAbstract
|
||||
public function test_store_fails_if_user_has_no_permission_to_create_invitations(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission([
|
||||
]);
|
||||
$data = $this->createUserWithPermission();
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
@@ -71,6 +70,44 @@ class InvitationEndpointTest extends ApiEndpointTestAbstract
|
||||
$response->assertStatus(403);
|
||||
}
|
||||
|
||||
public function test_store_fails_if_user_invites_with_role_owner(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission([
|
||||
'invitations:create',
|
||||
]);
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->postJson(route('api.v1.invitations.store', $data->organization->getKey()), [
|
||||
'email' => 'test@asdf.at',
|
||||
'role' => Role::Owner->value,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonPath('message', 'The selected role is invalid.');
|
||||
}
|
||||
|
||||
public function test_store_fails_if_user_invites_with_role_placeholder(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission([
|
||||
'invitations:create',
|
||||
]);
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->postJson(route('api.v1.invitations.store', $data->organization->getKey()), [
|
||||
'email' => 'test@asdf.at',
|
||||
'role' => Role::Placeholder->value,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonPath('message', 'The selected role is invalid.');
|
||||
}
|
||||
|
||||
public function test_store_invites_user_to_organization(): void
|
||||
{
|
||||
// Arrange
|
||||
|
||||
@@ -136,6 +136,63 @@ class MemberEndpointTest extends ApiEndpointTestAbstract
|
||||
$this->assertSame(10001, $member->billable_rate);
|
||||
}
|
||||
|
||||
public function test_update_member_can_update_role(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission([
|
||||
'members:update',
|
||||
]);
|
||||
$otherUser = User::factory()->create();
|
||||
$otherMember = Member::factory()->forUser($otherUser)->forOrganization($data->organization)->role(Role::Employee)->create();
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->putJson(route('api.v1.members.update', [$data->organization->getKey(), $otherMember->getKey()]), [
|
||||
'role' => Role::Admin->value,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(200);
|
||||
$otherMember->refresh();
|
||||
$this->assertSame(Role::Admin->value, $otherMember->role);
|
||||
}
|
||||
|
||||
public function test_update_member_role_fails_if_role_is_owner(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission([
|
||||
'members:update',
|
||||
]);
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->putJson(route('api.v1.members.update', [$data->organization->getKey(), $data->member->getKey()]), [
|
||||
'role' => Role::Owner->value,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonPath('message', 'The selected role is invalid.');
|
||||
}
|
||||
|
||||
public function test_update_member_role_fails_if_role_is_placeholder(): void
|
||||
{
|
||||
// Arrange
|
||||
$data = $this->createUserWithPermission([
|
||||
'members:update',
|
||||
]);
|
||||
Passport::actingAs($data->user);
|
||||
|
||||
// Act
|
||||
$response = $this->putJson(route('api.v1.members.update', [$data->organization->getKey(), $data->member->getKey()]), [
|
||||
'role' => Role::Placeholder->value,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonPath('message', 'The selected role is invalid.');
|
||||
}
|
||||
|
||||
public function test_invite_placeholder_succeeds_if_data_is_valid(): void
|
||||
{
|
||||
$data = $this->createUserWithPermission([
|
||||
|
||||
Reference in New Issue
Block a user