Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged

Dev #958

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import spock.lang.Specification
import yakworks.rest.client.OkAuth
import yakworks.rest.client.OkHttpRestTrait
import yakworks.security.gorm.model.SecRole
import yakworks.security.gorm.model.SecRolePermission
import yakworks.security.spring.PermissionsAuthorizationManager

import javax.inject.Inject
Expand Down Expand Up @@ -181,18 +180,19 @@ class ApiPermissionsSpec extends Specification implements OkHttpRestTrait {

@Rollback
void "test rpc permission - selected allowed"() {
setup: "admin has all the permissions"
setup: "Add permission to do op=rpc1 only"
SecRole cust = SecRole.query(code:Roles.CUSTOMER).get()

expect:
cust

when: "Add permission to do op=rpc1 only"
SecRolePermission.withNewTransaction {
SecRolePermission.create(cust, "rally:org:rpc:rpc1")
assert cust
SecRole.withNewTransaction {
cust.addPermission("rally:org:rpc:rpc1")
cust.persist()
}
TrxUtils.flushAndClear()
SecRole.withNewTransaction {
assert SecRole.get(cust.id).hasPermission("rally:org:rpc:rpc1")
}
TrxUtils.flush()

when:
login("cust", "123")

and: "op=rpc1 allowed"
Expand All @@ -213,8 +213,9 @@ class ApiPermissionsSpec extends Specification implements OkHttpRestTrait {
cleanup:
OkAuth.TOKEN = null

SecRolePermission.withNewTransaction {
SecRolePermission.query(role:cust, permission:"rally:org:rpc:rpc1").deleteAll()
SecRole.withNewTransaction {
cust.removePermission("rally:org:rpc:rpc1")
cust.persist()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import yakworks.api.problem.data.DataProblemException
import yakworks.security.PasswordConfig
import yakworks.security.Roles
import yakworks.security.gorm.model.SecPasswordHistoryRepo
import yakworks.security.gorm.model.SecRolePermission
import yakworks.security.gorm.model.SecRole
import yakworks.security.gorm.model.SecRoleUser
import yakworks.security.gorm.model.AppUser
import yakworks.security.gorm.model.AppUserRepo
Expand Down Expand Up @@ -94,7 +94,7 @@ class AppUserRepoSpec extends Specification implements DataIntegrationTest, Secu

then:
perms.size()
perms.size() == SecRolePermission.query("role.code":['$in':[Roles.ADMIN, "MANAGER"]]).countDistinct("permission").get()
perms.size() == SecRole.query("code":['$in':[Roles.ADMIN, "MANAGER"]]).property("permissions").get().flatten().unique().size()
}

/*see SecuritySeedData*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package gorm.tools.security

import grails.gorm.transactions.Rollback
import grails.testing.mixin.integration.Integration
import spock.lang.Specification
import yakworks.security.Roles
import yakworks.security.gorm.model.SecRole
import yakworks.testing.gorm.integration.DataIntegrationTest
import yakworks.testing.gorm.integration.SecuritySpecHelper

@Integration
@Rollback
class SecRoleTests extends Specification implements SecuritySpecHelper, DataIntegrationTest {

void "update permissions"() {
setup:
SecRole cust = SecRole.query(code: Roles.CUSTOMER).get()
List<String> perms = ["*:*:test"] + cust.permissions

when:
SecRole.repo.update([id:cust.id, permissions:perms])
flushAndClear()

then:
noExceptionThrown()

when:
cust.refresh()

then:
cust.permissions.size() == perms.size()
cust.hasPermission("*:*:test")
}

void "add remove permissions"() {
setup:
SecRole cust = SecRole.query(code: Roles.CUSTOMER).get()
String perm = "*:*:test"
expect:
cust

when:
//save in a trx and load in different trx
SecRole.withNewTransaction {
cust.addPermission(perm)
cust.persist()
}
flushAndClear()
SecRole.withNewTransaction {
cust = SecRole.get(cust.id)
}

then:
cust.hasPermission(perm)

when: "Remove permission"
SecRole.withNewTransaction {
cust.removePermission(perm)
cust.persist()
}
flushAndClear()
SecRole.withNewTransaction {
cust = SecRole.get(cust.id)
}

then:
!cust.hasPermission(perm)
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package yakworks.security

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.core.Authentication
import org.springframework.security.core.context.SecurityContextHolder

import grails.gorm.transactions.Rollback
import grails.gorm.transactions.Transactional
import grails.testing.mixin.integration.Integration
import spock.lang.Specification
import yakworks.security.gorm.model.AppUser
import yakworks.security.gorm.model.SecRole
import yakworks.security.gorm.model.SecRolePermission
import yakworks.security.gorm.model.SecRoleUser
import yakworks.security.gorm.model.SecUserPermission
import yakworks.security.user.CurrentUser
Expand Down Expand Up @@ -106,6 +103,8 @@ class CurrentUserSpec extends Specification implements DomainIntTest {
SecRole roleMgr = SecRole.create(code: "MGR")
SecRole roleUser = SecRole.create(code: 'CUST')



new SecUserPermission(admin, 'printer:print:*').persist()

new SecUserPermission(user2, 'printer:print:*').persist()
Expand All @@ -118,10 +117,11 @@ class CurrentUserSpec extends Specification implements DomainIntTest {

new SecUserPermission(user3, 'action:kick').persist()

new SecRolePermission(roleAdmin, 'printer:admin').persist()

new SecRolePermission(roleUser, 'printer:use').persist()
roleAdmin.addPermission('printer:admin')
roleAdmin.persist()

roleUser.addPermission('printer:use')
roleUser.persist()

SecRoleUser.create admin, roleAdmin, true
SecRoleUser.create admin, roleMgr, true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,29 @@ class MailMessageSpec extends Specification implements DomainIntTest {
msg2.tags.size() == 1
}

void "large mail message size success"() {
String body = RandomStringUtils.randomAlphanumeric(100000)
def msg = new MailMessage(
state: MailMessage.MsgState.Queued,
sendTo: '[email protected]',
sendFrom: "[email protected]",
replyTo: "[email protected]",
subject: "test",
body: body,
)

when:
msg.persist()
flushAndClear()

then:
noExceptionThrown()

when:
def msg2 = MailMessage.get(msg.id)

then:
msg2.body.length() == 100000
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class MailMessage implements UuidRepoEntity<MailMessage>, AuditCreatedTrait, Ser
source : [d: 'any special source indicator'],
state : [d: 'the state of the message', nullable: false],
subject : [d: 'email message subject', maxSize: 1000],
body : [d: 'body of message', maxSize: 65535],
body : [d: 'body of message', maxSize: 2_000_000], //max 2mb, assuming mostly single byte ASCII chars
attachmentIds: [d: 'ids list of attachments'],
inlineIds : [d: 'Attachment ids with inline disposition.'],
sendDate : [d: 'The send datetime, always in Zulu to match server time'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import yakworks.rally.tag.model.Tag
import yakworks.rally.tag.model.TagLink
import yakworks.security.gorm.model.AppUser
import yakworks.security.gorm.model.SecRole
import yakworks.security.gorm.model.SecRolePermission
import yakworks.security.gorm.model.SecRoleUser
import yakworks.security.gorm.testing.SecuritySeedData
import yakworks.spring.AppCtx
Expand All @@ -55,7 +54,7 @@ class RallySeed {
/** the classes to mock for unit tests, NOTE: stackoverflow if this is not specifed with generics */
static List<Class<?>> getEntityClasses() {
return [
AppUser, SecRole, SecRoleUser, SecRolePermission,
AppUser, SecRole, SecRoleUser,
Org, OrgSource, OrgTypeSetup, OrgTag, OrgMember, PartitionOrg, OrgFlex, OrgCalc, OrgInfo,
Location, Contact,
ActivityLink, Activity, TaskType, ActivityNote, ActivityContact,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ import yakworks.rally.orgs.model.OrgType
import yakworks.rally.orgs.model.OrgTypeSetup
import yakworks.security.gorm.model.AppUser
import yakworks.security.gorm.model.SecRole
import yakworks.security.gorm.model.SecRolePermission
import yakworks.security.gorm.model.SecRoleUser

@CompileDynamic
class MockData {

/** common entityClasses for base setup */
public static List<Class<Entity>> commonEntityClasses = [
Org, AppUser, SecRole, SecRoleUser, SecRolePermission ] as List<Class<Entity>>
Org, AppUser, SecRole, SecRoleUser ] as List<Class<Entity>>

static Org org(Map dta = [:]) {
Map vals = [num: 'tsla', name: 'Tesla', type: OrgType.Customer]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,17 +252,18 @@ class AppUserRepo extends LongIdGormRepo<AppUser> {

@Transactional(readOnly = true)
Set getPermissions(AppUser user) {
//have test
return SecRolePermission.executeQuery(
"""
select distinct p.permission
from SecRolePermission p
join p.role r
join SecRoleUser sru on sru.role = r
join sru.user u
where u.id = :uid
""",
[uid: user.id] ) as Set
//permissions are stored as json array, hql can not expand it and return unique perms without writing native pgsql query
String query = """
select role.permissions
from SecRole role
join SecRoleUser sru on sru.role = role
join sru.user u
where u.id = :uid
and role.permissions is not null
"""

List<List<String>> perms = (List<List<String>>) SecRole.executeQuery(query, [uid: user.id])
return perms.flatten().unique() as Set
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import gorm.tools.model.NameCodeDescription
import gorm.tools.repository.model.RepoEntity
import grails.compiler.GrailsCompileStatic
import grails.persistence.Entity
import yakworks.commons.lang.Validate
import yakworks.gorm.hibernate.type.JsonType

import static grails.gorm.hibernate.mapping.MappingBuilder.orm

Expand All @@ -26,6 +28,11 @@ class SecRole implements NameCodeDescription, RepoEntity<SecRole>, Serializable
String name
Boolean inactive = false

/**
* List of permissions strings
*/
List permissions

void beforeValidate() {
if(!this.name && this.code) this.name = code.replaceAll('-', ' ').replaceAll('_', ' ')
if(this.name && !this.code) this.code = name.replaceAll(' ', '_')
Expand All @@ -36,14 +43,42 @@ class SecRole implements NameCodeDescription, RepoEntity<SecRole>, Serializable
code:[ d: 'Upper case role key', nullable: false, maxSize: 25, matches: "[A-Z0-9-_]+" ],
name: [d: "The name of the role", nullable: false, maxSize: 50],
description: [d: "A longer description", nullable: true],
inactive: [d: "Whether role should be active", oapi:'U']
inactive: [d: "Whether role should be active", oapi:'U'],
permissions: [d: "Permissions of the role"]
]

static mapping = orm {
cache "read-write"
columns(
permissions: property(type: JsonType, typeParams: [type: ArrayList]),
)
}

static SecRole getByCode(String cd){
return SecRole.findWhere(code: cd)
}

void addPermission(String perm) {
Validate.notEmpty(perm)
if(permissions == null) permissions = []
permissions << perm
//Mark dirty explicitely, because when strings are added to list without replacing reference,
// grails do not detect dirty and does not update it.
markDirty('permissions')
}

void removePermission(String perm) {
Validate.notEmpty(perm)
if(permissions) {
permissions.remove(perm)
//Mark dirty explicitely, because when strings are added to list without replacing reference,
// grails do not detect dirty and does not update it.
markDirty('permissions')
}
}

boolean hasPermission(String perm) {
Validate.notEmpty(perm)
return permissions && permissions.contains(perm)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2021 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License")
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
package yakworks.security.gorm.model

import groovy.transform.CompileStatic

import gorm.tools.repository.GormRepository
import gorm.tools.repository.events.BeforeBindEvent
import gorm.tools.repository.events.RepoListener
import gorm.tools.repository.model.AbstractCrossRefRepo
import gorm.tools.repository.model.LongIdGormRepo

@GormRepository
@CompileStatic
class SecRoleRepo extends LongIdGormRepo<SecRole> {

/**
* Remove permissions from data map and bind before databinding, databinder doesnt handle lists
*/
@RepoListener
void beforeBind(SecRole role, Map data, BeforeBindEvent e) {
if(data && data['permissions']) {
role.permissions = data.remove('permissions') as List<String>
}
}
}
Loading