-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mrc-5298-Role Update Endpoints #64
Changes from 19 commits
58c6150
9580f70
49dd4aa
8baee2c
12a3d3c
aa7b95e
ce58d17
bd0145b
1095f2c
5cf4187
98e3062
5ed4a0d
5f1f1a3
e223d24
a83cacf
252975a
8658e23
27d5b0e
bf920c5
ecb871e
1ce3d7d
169ea1d
5765f22
a413033
f25fcf0
54eabf2
513285e
eb95c4c
fa37abd
c6d2bc5
dab6a1b
27d0103
163e5c0
30d168b
bc05370
5e07232
1ea9487
771eead
a98ea9e
8130999
d6d9e5f
6be3222
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,3 +29,38 @@ class RolePermission( | |
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
var id: Int? = null, | ||
) | ||
{ | ||
init | ||
{ | ||
val nonNullFields = listOf(packet, tag, packetGroup).count { it != null } | ||
require(nonNullFields <= 1) { | ||
"Either all of packet, tag, packetGroup should be null or only one of them should be not null" | ||
} | ||
} | ||
Comment on lines
+33
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Repeated logic... Given that you've got this constraint on the db, and also in the dto, maybe you don't need it here as well. But if so, should be able to implement once and use from both types. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah i thought that too but couldnt find a way to implement once and use both places.. Also they a bit different as one is ids and other is whole objects... And probs don't need but put here to for safety and mirror this constraint on DB and make more visible (as many people don't check db constraints haha) |
||
|
||
override fun equals(other: Any?): Boolean | ||
{ | ||
return when | ||
{ | ||
this === other -> true | ||
other !is RolePermission -> false | ||
role.name != other.role.name -> false | ||
permission.name != other.permission.name -> false | ||
packet?.id != other.packet?.id -> false | ||
packetGroup?.id != other.packetGroup?.id -> false | ||
tag?.id != other.tag?.id -> false | ||
else -> true | ||
} | ||
} | ||
Comment on lines
+42
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be less verbose just to check equality through the dto data class.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need on entity so can filter out data returned from entities... also mostly services using entites There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, pros and cons of both approaches, but as discussed it does seem easier to have the services talking to each other with entities. |
||
|
||
override fun hashCode(): Int | ||
{ | ||
val prime = 31 | ||
var result = role.name.hashCode() | ||
result = prime * result + permission.name.hashCode() | ||
result = prime * result + packet?.id.hashCode() | ||
result = prime * result + packetGroup?.id.hashCode() | ||
result = prime * result + tag?.id.hashCode() | ||
return result | ||
} | ||
Comment on lines
+57
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need the hash code? And could you just use that to check for equality? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah i did that initially but lint complained and said I need equals and haschode... and read and found its best to have both |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package packit.model.dto | ||
|
||
import org.jetbrains.annotations.NotNull | ||
|
||
data class UpdateRolePermissions( | ||
val addPermissions: List<UpdateRolePermission> = listOf(), | ||
val removePermissions: List<UpdateRolePermission> = listOf() | ||
) | ||
|
||
data class UpdateRolePermission( | ||
@field:NotNull | ||
val permission: String, | ||
val packetId: String? = null, | ||
val tagId: Int? = null, | ||
val packetGroupId: Int? = null | ||
) | ||
Comment on lines
+10
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we're only allowing global permissions when we create a role, but can update with scoped permissions? That seems inconsistent. Could accept a list of these on create role, rather than just permission names.. and then wouldn't this type also be the scoped permission type returned from the GET request too? ...oh, minus the id of course There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think for the create the FE most likely wont pass any permissions.. And here update is where it can pass in scoped if needed...The idea was it would be weird adding scoped permissions when creating a role as well... But adding a scoped permission when updating makes sense also.... This logic will be mirrored on the FE. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, but you still want to allow global permissions on create to make life easier for the admin cli/setup scripts? |
||
{ | ||
init | ||
{ | ||
val nonNullFields = listOf(packetId, tagId, packetGroupId).count { it != null } | ||
require(nonNullFields <= 1) { | ||
"Either all of packetId, tagId, packetGroupId should be null or only one of them should be not null" | ||
} | ||
} | ||
Comment on lines
+18
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this is nice, and I think we could still keep this anyway, even this type was also re-used as the RolePermission dto. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package packit.repository | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository | ||
import org.springframework.data.jpa.repository.Modifying | ||
import org.springframework.data.jpa.repository.Query | ||
import org.springframework.stereotype.Repository | ||
import org.springframework.transaction.annotation.Transactional | ||
import packit.model.RolePermission | ||
|
||
@Repository | ||
interface RolePermissionRepository : JpaRepository<RolePermission, Int> | ||
{ | ||
@Modifying | ||
@Transactional | ||
@Query("DELETE FROM RolePermission rp WHERE rp.id IN :ids") | ||
fun deleteAllByIdIn(ids: List<Int>) | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,81 @@ | ||||||
package packit.service | ||||||
|
||||||
import org.springframework.http.HttpStatus | ||||||
import org.springframework.stereotype.Service | ||||||
import packit.exceptions.PackitException | ||||||
import packit.model.Role | ||||||
import packit.model.RolePermission | ||||||
import packit.model.dto.UpdateRolePermission | ||||||
import packit.repository.* | ||||||
|
||||||
interface RolePermissionService | ||||||
{ | ||||||
fun getRolePermissionsToUpdate(role: Role, addRolePermissions: List<UpdateRolePermission>): List<RolePermission> | ||||||
fun removeRolePermissionsFromRole(role: Role, removeRolePermissions: List<UpdateRolePermission>) | ||||||
fun getAddRolePermissionsFromRole(role: Role, addRolePermissions: List<UpdateRolePermission>): List<RolePermission> | ||||||
} | ||||||
|
||||||
@Service | ||||||
class BaseRolePermissionService( | ||||||
private val permissionRepository: PermissionRepository, | ||||||
private val packetRepository: PacketRepository, | ||||||
private val packetGroupRepository: PacketGroupRepository, | ||||||
private val tagRepository: TagRepository, | ||||||
private val rolePermissionRepository: RolePermissionRepository | ||||||
) : RolePermissionService | ||||||
{ | ||||||
override fun getRolePermissionsToUpdate( | ||||||
role: Role, | ||||||
addRolePermissions: List<UpdateRolePermission> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i named like that to differentiate the adding and deleting of role permissions There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But you're using it for permissions being removed too: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh yup was mistaken have updated |
||||||
): List<RolePermission> | ||||||
{ | ||||||
return addRolePermissions.map { addRolePermission -> | ||||||
val permission = permissionRepository.findByName(addRolePermission.permission) | ||||||
?: throw PackitException("invalidPermissionsProvided", HttpStatus.BAD_REQUEST) | ||||||
|
||||||
RolePermission( | ||||||
role = role, | ||||||
permission = permission, | ||||||
packet = addRolePermission.packetId?.let { | ||||||
packetRepository.findById(it) | ||||||
.orElseThrow { PackitException("packetNotFound", HttpStatus.BAD_REQUEST) } | ||||||
}, | ||||||
packetGroup = addRolePermission.packetGroupId?.let { | ||||||
packetGroupRepository.findById(it) | ||||||
.orElseThrow { PackitException("packetGroupNotFound", HttpStatus.BAD_REQUEST) } | ||||||
}, | ||||||
tag = addRolePermission.tagId?.let { | ||||||
tagRepository.findById(it).orElseThrow { PackitException("tagNotFound", HttpStatus.BAD_REQUEST) } | ||||||
} | ||||||
) | ||||||
} | ||||||
} | ||||||
|
||||||
override fun removeRolePermissionsFromRole(role: Role, removeRolePermissions: List<UpdateRolePermission>) | ||||||
{ | ||||||
val rolePermissionsToRemove = getRolePermissionsToUpdate(role, removeRolePermissions) | ||||||
|
||||||
val matchedRolePermissionsToRemove = rolePermissionsToRemove.map { rolePermissionToRemove -> | ||||||
val matchedPermission = role.rolePermissions.find { rolePermissionToRemove == it } | ||||||
?: throw PackitException("rolePermissionDoesNotExist", HttpStatus.BAD_REQUEST) | ||||||
|
||||||
matchedPermission | ||||||
} | ||||||
|
||||||
rolePermissionRepository.deleteAllByIdIn(matchedRolePermissionsToRemove.map { it.id!! }) | ||||||
} | ||||||
|
||||||
override fun getAddRolePermissionsFromRole( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's quite confusing having getRolePermissionsToUpdate and getAddRolePermissionsFromRole (that sounds like it's getting the permissions from the role, but if the permissions are already in the role, you're going to throw an exception!). I wouldn't mind just making the method into a checkPermissionsToAddAreNotOnRole or something, and have the main update method call `getRolePermissionsToUpdate directly, and pass the perms into here to just do the check... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yup agree ended up changing to |
||||||
role: Role, | ||||||
addRolePermissions: List<UpdateRolePermission> | ||||||
): List<RolePermission> | ||||||
{ | ||||||
val rolePermissionsToAdd = getRolePermissionsToUpdate(role, addRolePermissions) | ||||||
if (rolePermissionsToAdd.any { role.rolePermissions.contains(it) }) | ||||||
{ | ||||||
throw PackitException("rolePermissionAlreadyExists", HttpStatus.BAD_REQUEST) | ||||||
} | ||||||
|
||||||
return rolePermissionsToAdd | ||||||
} | ||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, this overrides my previous comment!
I think this should just be
PUT /role/{roleName}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have done for all PUT as suggested as above in PR #68.. /role/{rolenmame}/permissions & /role/{rolenmame}/users