Coder Social home page Coder Social logo

cuba-platform / multitenancy-addon Goto Github PK

View Code? Open in Web Editor NEW
8.0 10.0 9.0 584 KB

Implementation of a single database multi-tenancy support for CUBA applications.

License: Apache License 2.0

Java 68.99% XSLT 31.01%
multi-tenancy apache2 cuba-platform cuba-component

multitenancy-addon's People

Contributors

belyaev-andrey avatar dmakagonova avatar funxies avatar gorbunkov avatar igor-korotkov avatar ivan-osipov avatar nikitashchienko avatar plakhov avatar tinhol avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

multitenancy-addon's Issues

Access denied to parent entity attribute for user without system-full-access role

based on forum's question

Environment

CUBA Platform version: 7.2.12
CUBA Studio plugin version: 15.3-202
IntelliJ version: IntelliJ IDEA 2020.3.1 (Community Edition)

Description of the bug

  • Minimal reproducible example
  1. Open attached project -> open data store settings and set right credentials -> create database
  2. Run app -> login as admin
  3. Create any students in student browser
  4. Open tenant management -> create tenant name 'user' -> generate group -> create admin for this tenant
  5. Set name 'user', password 'user', add role 'default-admin-tenant' -> Save
  6. Create role 'newrole' with access to entity Student, screens Student browser and Student Reports, menu items Application, reports -> save -> add to user 'user' this role -> save
  7. Logout and login as user -> open Student Reports screen

AR:
image

15:17:45.732 ERROR c.h.cuba.core.sys.ServiceInterceptor    - Exception in DataService.loadValues(..): com.haulmont.cuba.core.global.AccessDeniedException: ENTITY_ATTR testapp_Student.e.nation
15:17:45.737 ERROR com.haulmont.cuba.web.log.AppLog        - Exception in com.haulmont.cuba.web.widgets.CubaSideMenu: com.haulmont.cuba.core.global.AccessDeniedException: ENTITY_ATTR testapp_St

udent.e.nation

user has no access to attributes of entity NationEntity which is parent for Student
even admin has no opportunity to get access to parent entity because it's a mappedsuperclass

ER:
user should have access to parent entity attributes if access to child entity was permitted

Impossible to view Users, Roles, User Groups menu items by user with tenant-admin-role

Environment

CUBA Platform version: 7.2.8
CUBA Studio plugin version: 15.0.SNAPSHOT2597-202
IntelliJ version: IntelliJ IDEA 2020.2 (Community Edition)

Description of the bug or enhancement

Add the design-time role tenant-user-manager for users with the tenant, who has screen access Administration and entity access sec$MultipleTarget, sec$OperationTarget.

Add @Deprecated annotation for TenantsAdminRole.

Minimal reproducible example

  1. user 1 has two predefined roles (tenant-admin-role, default-tenant-role)
    for tenant-admin-role Users, Access groups, Roles screens are alloved (corresponding entities, uttributes are also allowed), but Administration screen isn`t allowed
    login by user 1 (password = 1)

Expected behavior:

Users, Roles, User Groups menu items should be visible

Actual behavior:

no menu items from Aministration section are visible
multitenant.zip
image

  1. for tenant-admin-role need to add permission for OperationPermissionTarget entity, otherwise user see empty strings during create new role
    image

  2. User with yentant role should be able to see all assigned roles in user editor (now there are empty strings instead of non-tentant roles)

Issues with Tenant management

Issues:

  • Since tenant is removed we can't create a new tenant with the same name. Unique index should be changed
  • Admin field of tenant must be required
  • Tenant removing should deactivate users

Add mentioning of EntityManager to the documentation

Description of the bug or enhancement

https://www.cuba-platform.com/discuss/t/multitenancy-plugin-not-filtering-on-tenants-through-entitymanager/10825/3?u=alexbudarov

Newbie users don't realize that multitenancy constraints are applied.

The documentation doesn't say anything about the way you should load data in order for tenant constraints to be applied.

It should be a separate section.
Things we would like to see in the doc:

  • Adding multitenancy constraints work on the EntityManager layer for JPQL queries. Multitenancy constraints don't work for native SQL queries.
  • If you need auto-applying of tenant constraints, you need to load data with EntityManager/DataManager
  • All data loaders use DataManager to load their data
  • REST API also uses DataManager to load data
  • Reporting: SQL bands don't apply multitenancy constraints. Those can be applied only if you call DataManager queries inside of a Groovy band or use JPQL bands
  • Reporting: JPQL bands work with multitenancy constraints.

Incorrect local messages when using Multitenancy addon

Incorrect local messages when using Multitenancy addon.

Please take a look at attached screenshots
and a screenshot in original post in chinese forum: https://forum.cuba-platform.cn/t/topic/1867

Tested on
CUBA Platform version: 7.2.13
CUBA Studio plugin version: 15.4-202
IntelliJ version: IntelliJ IDEA 2021.1.3 (Community Edition)
Simplified Chinese Translation addon v.7.2.0
Italian Translation addon v.7.2.1
Multitenancy addon v.2.0.2

All addons installed from Marketplace.

Case 1.

  1. Create a CUBA project with Simplified Chinese Translation and Multitenancy addons.
  2. Set Chinese language in Setting screen.
  3. Open Users screen (用户).
  4. Try to create a new user or edit existing one.

ER: All field titles are localized.

AR: Some field titles are not localized.

CUBA Simplified Chinese Translation and Multitenancy addons - User-screen

Case 2.

  1. Create a CUBA project with Simplified Chinese Translation addon. (Uninstall Multitenancy one).
  2. Set Chinese language in Setting screen.
  3. Open Users screen (用户).
  4. Try to create a new user or edit existing one.

ER: All field titles are localized.

AR: Security scope field title isn’t translated.

CUBA Simplified Chinese Translation addon only - User-screen

Case 3.

  1. Create a CUBA project with Italian Translation addon and Multitenancy addon.
  2. Set Italian the in Setting screen.
  3. Open Users screen (Amministrazione > Utenti)
  4. Try to create a new user or edit existing one.

ER: All field titles are localized.

AR: Some field titles are not localized. Please take a look at attached screenshot.

CUBA mammamia User screen with Multitenancy addon

by comparison screenshot below is without Multitenancy addon:

CUBA mammamia User screen without Multitenancy addon

Extend the functionality of the add-on MultiTenancy

Description of the enhancement

Create additional functionality for tenant management:

  • Tenant lock - Temporarily block users with a specific tenantId
  • Tenant Management - data management of the selected tenant
  • Removal tenant - Data management when removing tenant

User can't run demo app

Environment

  • Platform version: 7.0.6
  • Addon version: 1.3.3, 1.2.2
  1. Open demo app
  2. Set repository http://repository.haulmont.com:8587/nexus/content/groups/work, addon version = 1.3.3 / 1.2.2. Click Ok
  3. Click CUBA -> Start Application Server
  4. Open url http://localhost:8080/app

Expected result: login page
Actual result: HTTP Status 404

2019-06-14 15:39:17.233 INFO [main] com.haulmont.cuba.web.sys.remoting.WebRemoteProxyBeanCreator - Configuring proxy beans for local service invocations: [cuba_LoginService, cuba_AuthenticationService, cuba_TrustedClientService, cuba_ServerInfoService, cuba_UserSettingService, cuba_UserManagementService, cuba_DataService, cuba_ConfigStorageService, cuba_PersistenceManagerService, cuba_LockService, cuba_UserSessionService, cuba_FoldersService, cuba_EmailService, cuba_FileStorageService, cuba_EntitySnapshotService, cuba_UniqueNumbersService, cuba_LocalizedMessageService, cuba_ResourceService, cuba_ScheduledTasksService, cuba_EntityLogService, cuba_TestingService, cuba_DomainDescriptionService, cuba_RelatedEntitiesService, cuba_EntitySqlGenerationService, cuba_NumberIdService, cuba_QueryResultsService, cuba_DynamicAttributesCacheService, cuba_EntityRestoreService, cuba_LocalFileExchangeService, cuba_EntityImportExportService, cuba_ServerTokenStore, cuba_ConstraintLocalizationService, cuba_AttributeAccessService, cuba_ExceptionReportService, cuba_BulkEditorDataService]
2019-06-14 15:39:18.822 INFO [main] com.haulmont.cuba.core.sys.CubaThreadPoolTaskScheduler - Initializing ExecutorService 'scheduler'
2019-06-14 15:39:18.857 WARN [main] com.haulmont.cuba.core.sys.CubaClassPathXmlApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sdbmtUserEditorDelegate': Lookup method resolution failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [com.haulmont.addon.sdbmt.gui.app.security.user.edit.SdbmtUserEditorDelegate] from ClassLoader [ParallelWebappClassLoader
context: app
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@43f02ef2
]
2019-06-14 15:39:18.858 INFO [main] com.haulmont.cuba.core.sys.CubaThreadPoolTaskScheduler - Shutting down ExecutorService 'scheduler'
2019-06-14 15:39:18.878 ERROR [main] com.haulmont.cuba.core.sys.AbstractWebAppContextLoader - Error initializing application
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sdbmtUserEditorDelegate': Lookup method resolution failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [com.haulmont.addon.sdbmt.gui.app.security.user.edit.SdbmtUserEditorDelegate] from ClassLoader [ParallelWebappClassLoader
context: app
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@43f02ef2
]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:265) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1236) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1151) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:144) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:95) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at com.haulmont.cuba.core.sys.CubaClassPathXmlApplicationContext.(CubaClassPathXmlApplicationContext.java:27) ~[cuba-global-7.0.0.jar:7.0.0]
at com.haulmont.cuba.core.sys.AbstractAppContextLoader.createApplicationContext(AbstractAppContextLoader.java:90) ~[cuba-global-7.0.0.jar:7.0.0]
at com.haulmont.cuba.core.sys.AbstractAppContextLoader.initAppContext(AbstractAppContextLoader.java:62) ~[cuba-global-7.0.0.jar:7.0.0]
at com.haulmont.cuba.core.sys.AbstractWebAppContextLoader.contextInitialized(AbstractWebAppContextLoader.java:77) ~[cuba-global-7.0.0.jar:7.0.0]
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4663) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5131) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:713) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1133) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1868) [catalina.jar:9.0.14]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_211]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_211]
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:9.0.14]
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112) [na:1.8.0_211]
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:1045) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:429) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1577) [catalina.jar:9.0.14]
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:309) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:424) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:367) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:934) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1382) [catalina.jar:9.0.14]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1372) [catalina.jar:9.0.14]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_211]
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:9.0.14]
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) [na:1.8.0_211]
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:907) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:933) [catalina.jar:9.0.14]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:9.0.14]
at org.apache.catalina.startup.Catalina.start(Catalina.java:637) [catalina.jar:9.0.14]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_211]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_211]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_211]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_211]
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350) [bootstrap.jar:9.0.14]
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492) [bootstrap.jar:9.0.14]
Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.haulmont.addon.sdbmt.gui.app.security.user.edit.SdbmtUserEditorDelegate] from ClassLoader [ParallelWebappClassLoader
context: app
delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@43f02ef2
]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:680) ~[spring-core-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:577) ~[spring-core-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:562) ~[spring-core-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:248) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
... 58 common frames omitted
Caused by: java.lang.NoClassDefFoundError: com/haulmont/cuba/gui/components/Component$ValueChangeEvent
at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_211]
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[na:1.8.0_211]
at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[na:1.8.0_211]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:662) ~[spring-core-5.1.2.RELEASE.jar:5.1.2.RELEASE]
... 61 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.haulmont.cuba.gui.components.Component$ValueChangeEvent
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1343) ~[catalina.jar:9.0.14]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1173) ~[catalina.jar:9.0.14]
... 65 common frames omitted

Description of the bug or enhancement

  • Minimal reproducible example
  • Expected behavior
  • Actual behavior

Add config for data management

Environment

  • Platform version: 7.2
  • Addon version: 1.4

Description of the bug or enhancement

Add boolean config to display data with tenantId = null.

If true, display data with tenantId = null to all users.
If false, display data with tenantId = null only to admin.

Issue with SDBMT and cuba_App bean

I was following the directions in this link

https://www.cuba-platform.com/discuss/t/multiple-main-window/831/5

It would seem that adding in a cuba_App bean is causing an issue with SDBMT

It seems to throw this error when starting the application. Removing the spring.xml entry gets the app working again.


javax.management.MBeanException: RuntimeException thrown in RequiredModelMBean while trying to invoke operation getCount
2018-05-28 18:43:27.682 ERROR [scheduler-7] com.haulmont.cuba.core.sys.MBeanInterceptor - MBeanInterceptor caught exception: 
java.lang.ClassCastException: com.haulmont.cuba.security.entity.UserSessionEntity cannot be cast to com.haulmont.addon.sdbmt.entity.HasTenant
 at com.haulmont.addon.sdbmt.security.app.SdbmtUserSessions.getUserSessionInfo(SdbmtUserSessions.java:29) ~[sdbmt-core-0.7.2-SNAPSHOT.jar:na]
 at com.haulmont.cuba.security.jmx.UserSessions.getCount(UserSessions.java:56) ~[cuba-core-6.8.8.jar:6.8.8]
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
 at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) [spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at com.haulmont.cuba.core.sys.MBeanInterceptor.aroundInvoke(MBeanInterceptor.java:39) ~[cuba-core-6.8.8.jar:6.8.8]
 at sun.reflect.GeneratedMethodAccessor260.invoke(Unknown Source) ~[na:na]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
 at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629) [spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618) [spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) [spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) [spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) [spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at com.sun.proxy.$Proxy261.getCount(Unknown Source) [na:na]
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
 at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
 at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71) [na:1.8.0_151]
 at sun.reflect.GeneratedMethodAccessor70.invoke(Unknown Source) ~[na:na]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
 at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
 at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275) [na:1.8.0_151]
 at javax.management.modelmbean.RequiredModelMBean$4.run(RequiredModelMBean.java:1252) [na:1.8.0_151]
 at java.security.AccessController.doPrivileged(Native Method) [na:1.8.0_151]
 at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80) [na:1.8.0_151]
 at javax.management.modelmbean.RequiredModelMBean.invokeMethod(RequiredModelMBean.java:1246) [na:1.8.0_151]
 at javax.management.modelmbean.RequiredModelMBean.invoke(RequiredModelMBean.java:1085) [na:1.8.0_151]
 at org.springframework.jmx.export.SpringModelMBean.invoke(SpringModelMBean.java:90) [spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at javax.management.modelmbean.RequiredModelMBean.getAttribute(RequiredModelMBean.java:1562) [na:1.8.0_151]
 at org.springframework.jmx.export.SpringModelMBean.getAttribute(SpringModelMBean.java:109) [spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:647) [na:1.8.0_151]
 at com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:678) [na:1.8.0_151]
 at com.haulmont.cuba.core.app.MiddlewareStatisticsAccumulator.gatherParameters(MiddlewareStatisticsAccumulator.java:70) [cuba-core-6.8.8.jar:6.8.8]
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
 at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
 at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) [spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) [spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_151]
 at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_151]
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_151]
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_151]
 at com.haulmont.cuba.core.sys.CubaThreadPoolTaskScheduler$TaskDecorator.run(CubaThreadPoolTaskScheduler.java:120) [cuba-global-6.8.8.jar:6.8.8]
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_151]
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_151]
 at java.lang.Thread.run(Thread.java:748) [na:1.8.0_151]

Support unicode in tenantId

Now unicode is not supported in tenantId. Because of this, you have to control the input characters in the "Tenant ID" field on the Tenant creation screen.
Or is it specifically so done?

Tenant admins are not able to view user sessions from the administration menu

It seems that tenant admins are not able to view user sessions from the administration menu.
When I run the addon-demo (https://github.com/cuba-platform/multitenancy-addon-demo) I don't see any user sessions (of course after I logged in as a tenant user).

This is caused by the fact that the tenantId is not set on the UserSessionEntity, because in the user session list of the global admin, the tenantId column is empty.

For me the following fix works: replace the override of the method getUserSessionInfo() in SdbmtUserSessions (which seems to be called only when counting the number of user sessions), by an override of createUserSessionEntity().

public class SdbmtUserSessions extends UserSessions {

@Override
protected UserSessionEntity createUserSessionEntity(UserSession session, long since, long lastUsedTs) {
	UserSessionEntity userSessionEntity = super.createUserSessionEntity(session, since, lastUsedTs);

	String tenantId = session.getAttribute(tenantConfig.getTenantIdName());
	((HasTenant)userSessionEntity).setTenantId(tenantId);
	return userSessionEntity;
}

}

CUBA_SDBMT_TENANT table is not dropped after add-on deleting

based on forum's question

Environment

CUBA Platform version: 7.2.14
CUBA Studio plugin version: 15.5-211
IntelliJ version: IntelliJ IDEA 2021.2 (Ultimate Edition)
Operating system: Ubuntu 20.04 LTS
Add-on version: 2.0.2

TC:

  1. Create new project
  2. Set main datastore type PostgreSQL
  3. Add the Multitenancy add-on from the Marketplace
  4. Run app -> update database -> stop app
  5. Remove the Multitenancy add-on
  6. Run app -> update database
  7. Open database tables in IDEA or DBeaver

AR:
CUBA_SDBMT_TENANT table is not dropped after add-on deleting
image

ER:
Add-on's tables should be removed after add-on deleting

TenantId is not set for new entities

Environment

  • Platform version: 7.2
  • Addon version: 2.0.BETA1

Description of the bug or enhancement

Minimal reproducible example

  1. Create a Admin User for the specific tenant
  2. Create a new tenant
  3. Create a standard browse/edit entity screen.
  4. Log in with tenant user.
  5. Create a new entity instance.
  6. Refresh page.

Expected behavior

A table with a new instance is displayed.

Actual behavior

Empty table displayed

Tenant users created in sub-sub-access groups lose tenant restrictions

If we have an access group structure like this:

  • Company
    • Tenant 1
      • Group 1
        • Group 2

Users in Group 2 lose all tenant restrictions

The problem is in MultiTenancySecurityHandler#findGroupTenant
The query for group hierarchy doesn't go through the whole hierarchy to find the tenant id as it should.

Administration menu entry missing in the tenant-admin-role

Environment

  • Platform version: 7.2.8

  • Addon version: 2.0.2

  • Client type: Web

  • Browser: Firefox

  • Database: PostgreSQL

  • Operating system: Linux

Description of the bug or enhancement

After installing the addon in a completely new and empty project, I have created a new Tenant, Access Group and Admin User following the documentation and the demo project. After all the steps I have logged in with the new tenant admin user, having access to the "Tenant management > Tenants" entry in the application menu but nothing else.

Checking the tenant-admin-role, I found that it allows the User, Group and Role screens but not the "Administration" section in the menu. I added it after creating an adhoc role "tenant-admin-role-path" and I could finally create a regular user for the new tenant.

I have checked the code of TenantsAdminRole.java class and I guess that screensIds property should contains "administration" too, currently not present:

@ScreenAccess(screenIds = {"tenant-management", "cubasdbmt$Tenant.browse", "cubasdbmt$Tenant.edit", "sec$Role.browse", "sec$Role.lookup", "sec$Role.edit", "sec$Group.browse", "sec$Group.lookup", "sec$Group.edit", "sec$User.browse", "sec$User.lookup", "sec$User.edit"})

Creating and removing process improvements

Tenant creating

Process should be simplified and absolutely clear.
To improve UX for addon's end-users, creation can be divided into three steps:

  1. Input tenant name + tenant id
  2. Generation or selection of access group
  3. Admin selection with access group update or creation admin with predefined fields
    Also a sequence of this actions should be restricted

Tenant removing

Removing process should have obvious effects
On remove either all data of tenant should be hardly removed or all users of tenant should be deactivated (in this case unique indexes for tenant name should be updated)

User with no tenant admin rights can see column Tenant Id

Environment

  • Platform version: 7.2-SNAPSHOT
  • Addon version: 2.0-SNAPSHOT

Description of the bug or enhancement

  1. Run addon demo
  2. Login as admin
  3. Create a user (Login = costco, Password = costco, Tenant Id = Costco, Group = Costco)
  4. Log out, login as costco
  5. Click Application -> Stores

Expected result: the user can NOT see a column Tenant Id
Actual result: the user can see a column Tenant Id

In some cases TenantUser class prevents data from saving

Environment

  • Platform version: 7.2.4
  • Addon version: 2.0.2

Description of the bug or enhancement

Checkout Petclinic app from https://github.com/cuba-platform/cuba-petclinic
Install Multitenancy Add-On
Create the database and run application

E.R. Application will start. All entities are not tenant-specific, so everything should work
A.R. Application fails on startup, method com.haulmont.sample.petclinic.core.VisitTestDataCreation#commit fails.

If we remove com.haulmont.addon.sdbmt.entity.TenantUser class from the add-on, the application starts.

Error:

20:08:30.796 ERROR c.h.c.c.s.AbstractWebAppContextLoader   - Error initializing application
java.lang.IllegalStateException: An attempt to save an entity with reference to some not persisted entity. All newly created entities must be saved in the same transaction. Put all these objects to the CommitContext before commit.
	at com.haulmont.cuba.core.sys.aop.CascadePersistExceptionAspect.changeCascadePersistMessage(CascadePersistExceptionAspect.java:38) ~[cuba-core-7.2.4.jar:7.2.4]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:626) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:66) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at com.sun.proxy.$Proxy283.commit(Unknown Source) ~[na:na]
	at com.haulmont.cuba.core.app.DataManagerBean.commit(DataManagerBean.java:188) ~[cuba-core-7.2.4.jar:7.2.4]
	at com.haulmont.cuba.core.app.DataManagerBean.commit(DataManagerBean.java:220) ~[cuba-core-7.2.4.jar:7.2.4]
	at com.haulmont.sample.petclinic.core.VisitTestDataCreation.commit(VisitTestDataCreation.java:126) ~[petclinic-core-2.0.jar:na]
	at com.haulmont.sample.petclinic.core.VisitTestDataCreation.createData(VisitTestDataCreation.java:65) ~[petclinic-core-2.0.jar:na]
	at com.haulmont.sample.petclinic.core.TestdataOnApplicationStart.appStarted(TestdataOnApplicationStart.java:19) ~[petclinic-core-2.0.jar:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:an]
....
	Suppressed: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: com.haulmont.addon.sdbmt.entity.TenantUser-78c1b6c3-f217-dc2e-8af6-e1d502256dd0 [detached].
		at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:315) ~[org.eclipse.persistence.core-2.7.3-6-cuba.jar:na]
		at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:768) ~[org.eclipse.persistence.core-2.7.3-6-cuba.jar:na]
		at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:443) ~[org.eclipse.persistence.core-2.7.3-6-cuba.jar:na]
		at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:974) ~[org.eclipse.persistence.jpa-2.7.3-6-cuba.jar:na]

Invalid tenant id field displayed

Environment

  • Platform version: 7.0
  • Addon version: 1.3-SNAPSHOT

Description of the bug or enhancement

  1. Open the "Tenants" tab.
  2. Click "Create".
  3. Fill in all fields.
  4. Edit the "Tenant Id" field.

image

  1. Click "OK".
  2. Open the created tenant.

image

Invalid tenant id field displayed.

Upgrade add-on to CUBA 7.1 platform version.

Upgrade add-on to CUBA 7.1 platform version.
Snapshot add-on version should be updated to 1.4.
Current releases/cuba_7.0 branch should be merged from the master. Create this branch if it does not exist.

UI and Specific tabs are not displayed

Environment

  • Platform version: 7.2
  • Add-on version: 2.0

Description of the bug or enhancement

UI tab and Specific are not displayed.

Topic: https://www.cuba-platform.com/discuss/t/bug-continues-from-multitenancy-add-on-from-beta-to-2-0/11846

image

  • Minimal reproducible example
  1. Create a new CUBA project with the Multitenancy add-on.
  2. Run this project and show a Role screen, them click the Create button
  • Expected behavior
    UI and Specific tabs are displayed.
  • Actual behavior
    UI and Specific tabs are not displayed.

Updates

UI and Specific tabs are displayed regardless of tenantId

bug in HasTenantAdditionalCriteriaProvider

I made a ticket for this in Cuba forum before https://www.cuba-platform.com/discuss/t/bug-in-multitenancy-queries-tenant-id-no-tenant-is-applied-incorrectly/14547

    @Override
    public String getAdditionalCriteria(Class entityClass) {
        MetaProperty metaProperty = tenantEntityOperation.getTenantMetaProperty(entityClass);
        return String.format("(:tenantId = '%s' or this.%s = :tenantId)", TenantProvider.NO_TENANT, metaProperty.getName());
    }

should be replaced by

    @Override
    public String getAdditionalCriteria(Class entityClass) {
        MetaProperty metaProperty = tenantEntityOperation.getTenantMetaProperty(entityClass);
        return String.format("(this.%s = '%s' or this.%s = :tenantId)", metaProperty.getName(), TenantProvider.NO_TENANT, metaProperty.getName());
    }

However, during startup an anonymous login is mandatory. In the as is this results in a condition on the query

Copy
'no_tenant' = 'no_tenant'
after applying the fix we get

Copy
t1.TENANT_ID = 'no_tenant'
As the anonymous user has a null value in the tenant_id the condition returns false. no anymous user is found and the server fails to start.

Error: when a user open multitenancy-addon-demo

  1. Open multitenancy-addon-demo in Cuba 7.0

Expected result: user can deploy, start demo
Actual result: Unable to load class 'org.gradle.api.reflect.TypeOf'.

This is an unexpected error. Please file a bug containing the idea.log file.

Exception in com.haulmont.cuba.web.widgets.CubaButton during generate tenant group by tenant admin

CUBA Platform version: 7.2.4
CUBA Studio plugin version: 15.0.SNAPSHOT2694-202
IntelliJ version: IntelliJ IDEA 2020.2.4 (Community Edition)

Roles.zip

TC: open attached project>run app
create user 1 > assign roles 'role' attached, admin-tenant, system-minimal
create tenaten>assign user 1 to tenant admin
login by user 1
tenant>create> set name>generate group
ER: group should be generated
AR:

Exception in com.haulmont.cuba.web.widgets.CubaButton: 
com.vaadin.server.ServerRpcManager$RpcInvocationException: Unable to invoke method click in com.vaadin.shared.ui.button.ButtonServerRpc
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:157) ~[vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:115) ~[vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:431) [vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:396) [vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:260) [vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:82) [vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) [vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1578) [vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:425) [vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:329) [cuba-web-7.2.4.jar:7.2.4]
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:215) [cuba-web-7.2.4.jar:7.2.4]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) [servlet-api.jar:na]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [catalina.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.27]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) [tomcat-websocket.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.27]
	at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) [spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:74) [spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:93) [cuba-web-7.2.4.jar:7.2.4]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.27]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [catalina.jar:9.0.27]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [catalina.jar:9.0.27]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [catalina.jar:9.0.27]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [catalina.jar:9.0.27]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [catalina.jar:9.0.27]
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678) [catalina.jar:9.0.27]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [catalina.jar:9.0.27]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [catalina.jar:9.0.27]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-coyote.jar:9.0.27]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-coyote.jar:9.0.27]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-coyote.jar:9.0.27]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579) [tomcat-coyote.jar:9.0.27]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-coyote.jar:9.0.27]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:9.0.27]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
Caused by: java.lang.reflect.InvocationTargetException: null
	at sun.reflect.GeneratedMethodAccessor283.invoke(Unknown Source) ~[na:na]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:153) ~[vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	... 38 common frames omitted
Caused by: java.lang.RuntimeException: Exception on action handling
	at com.haulmont.cuba.gui.xml.DeclarativeAction.actionPerform(DeclarativeAction.java:104) ~[cuba-gui-7.2.4.jar:7.2.4]
	at com.haulmont.cuba.web.gui.components.WebButton.buttonClicked(WebButton.java:67) ~[cuba-web-7.2.4.jar:7.2.4]
	at com.haulmont.cuba.web.widgets.CubaButton.fireClick(CubaButton.java:76) ~[cuba-web-widgets-7.2.4.jar:na]
	at com.vaadin.ui.Button$1.click(Button.java:57) ~[vaadin-server-8.9.2-6-cuba.jar:8.9.2-6-cuba]
	... 42 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
	at com.haulmont.cuba.gui.xml.DeclarativeAction.actionPerform(DeclarativeAction.java:101) ~[cuba-gui-7.2.4.jar:7.2.4]
	... 45 common frames omitted
Caused by: java.lang.RuntimeException: Tenants default parent group doesn't exist
	at com.haulmont.addon.sdbmt.web.tenant.TenantEdit.onCreateTenantRootGroup(TenantEdit.java:122) ~[sdbmt-web-2.0.2.jar:na]
	... 50 common frames omitted

login error- no method found in

Environment
Platform version: 7.2

Description of the bug or enhancement

create new tenant and following exception comes when try to login

08:45:00.081 ERROR c.h.c.s.a.AuthenticationServiceBean - Login error
java.lang.NoSuchMethodError: com.haulmont.cuba.core.global.Metadata.create(Ljava/lang/Class;)Ljava/lang/Object;
at com.haulmont.addon.sdbmt.core.sys.MultiTenancySecurityHandler.addTenantIdConstraint(MultiTenancySecurityHandler.java:144) ~[sdbmt-core-1.3.3.jar:na]
at com.haulmont.addon.sdbmt.core.sys.MultiTenancySecurityHandler.compileTenantConstraints(MultiTenancySecurityHandler.java:110) ~[sdbmt-core-1.3.3.jar:na]
at com.haulmont.addon.sdbmt.core.sys.MultiTenancySecurityHandler.compileConstraints(MultiTenancySecurityHandler.java:91) ~[sdbmt-core-1.3.3.jar:na]
at com.haulmont.addon.sdbmt.core.LoginEventListener.onApplicationEvent(LoginEventListener.java:39) ~[sdbmt-core-1.3.3.jar:na]
at com.haulmont.addon.sdbmt.core.LoginEventListener.onApplicationEvent(LoginEventListener.java:27) ~[sdbmt-core-1.3.3.jar:na]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at com.haulmont.cuba.core.sys.EventsImpl.publish(EventsImpl.java:33) ~[cuba-global-7.2-SNAPSHOT.jar:7.2-SNAPSHOT]
at com.haulmont.cuba.security.auth.AuthenticationManagerBean.publishUserLoggedInEvent(AuthenticationManagerBean.java:319) ~[cuba-core-7.2-SNAPSHOT.jar:7.2-SNAPSHOT]
at com.haulmont.cuba.security.auth.AuthenticationManagerBean.login(AuthenticationManagerBean.java:131) ~[cuba-core-7.2-SNAPSHOT.jar:7.2-SNAPSHOT]
at com.haulmont.cuba.security.auth.AuthenticationServiceBean.login(AuthenticationServiceBean.java:89) ~[cuba-core-7.2-SNAPSHOT.jar:7.2-SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_211]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_211]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_211]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_211]
at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:94) [cuba-core-7.2-SNAPSHOT.jar:7.2-SNAPSHOT]
at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:154) [cuba-web-7.2-SNAPSHOT.jar:7.2-SNAPSHOT]
at com.sun.proxy.$Proxy29.login(Unknown Source) [na:na]
at com.haulmont.addon.restapi.api.auth.CubaUserAuthenticationProvider.loginMiddleware(CubaUserAuthenticationProvider.java:157) [restapi-rest-api-7.2-SNAPSHOT.jar:na]
at com.haulmont.addon.restapi.api.auth.CubaUserAuthenticationProvider.authenticate(CubaUserAuthenticationProvider.java:128) [restapi-rest-api-7.2-SNAPSHOT.jar:na]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:175) [spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter.getOAuth2Authentication(ResourceOwnerPasswordTokenGranter.java:71) [spring-security-oauth2-2.3.4.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.AbstractTokenGranter.getAccessToken(AbstractTokenGranter.java:72) [spring-security-oauth2-2.3.4.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.token.AbstractTokenGranter.grant(AbstractTokenGranter.java:67) [spring-security-oauth2-2.3.4.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.CompositeTokenGranter.grant(CompositeTokenGranter.java:38) [spring-security-oauth2-2.3.4.RELEASE.jar:na]
at org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(TokenEndpoint.java:132) [spring-security-oauth2-2.3.4.RELEASE.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_211]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_211]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_211]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_211]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) [spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) [spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) [spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) [spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) [spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) [spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) [spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908) [spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) [servlet-api.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) [spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) [servlet-api.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [catalina.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.19]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:215) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.19]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) [tomcat-websocket.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.19]
at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:107) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73) [spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:93) [cuba-web-7.2-SNAPSHOT.jar:7.2-SNAPSHOT]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.19]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200) [catalina.jar:9.0.19]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [catalina.jar:9.0.19]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) [catalina.jar:9.0.19]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [catalina.jar:9.0.19]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [catalina.jar:9.0.19]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678) [catalina.jar:9.0.19]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [catalina.jar:9.0.19]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [catalina.jar:9.0.19]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-coyote.jar:9.0.19]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-coyote.jar:9.0.19]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836) [tomcat-coyote.jar:9.0.19]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1747) [tomcat-coyote.jar:9.0.19]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-coyote.jar:9.0.19]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_211]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_211]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:9.0.19]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_211]

To add predefined system entities

Could we add predefined tenancy system classes like ExtGroup, ExtUser, ExtRole and other which are not added to persistence.xml by default but could be added to there manually by user? In my guess it is a lot more convenient way to include the addon in a project than to implement every time each of implicitly important entities

User can't run gradlew command for demo

Environment

  • Platform version: 7.0.0
  • Addon version: 1.2.1

Description of the bug or enhancement

  • Minimal reproducible example
  1. Download demo project
  2. Run in the command line
    gradlew setupTomcat deploy
  • Expected behavior
    The command is succesfull

  • Actual behavior
    Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain

*There is no graddle folder for the demo. There are always graddle folder for other demo projects.

No validation of tenant id in UI

Environment

  • Platform version: 7.0
  • Addon version: 1.3-SNAPSHOT

Description of the bug or enhancement

If you create tenant-a tenant, you will have an exception on login (which also does not describe the cause):

09:05:05.646 ERROR c.h.c.s.a.AuthenticationServiceBean     - Login error
java.lang.IllegalStateException: Tenant id is not valid: tenant-a
	at com.haulmont.addon.sdbmt.core.sys.MultiTenancySecurityHandler.compileTenantConstraints(MultiTenancySecurityHandler.java:104) ~[sdbmt-core-1.3-SNAPSHOT.jar:na]
	at com.haulmont.addon.sdbmt.core.sys.MultiTenancySecurityHandler.compileConstraints(MultiTenancySecurityHandler.java:90) ~[sdbmt-core-1.3-SNAPSHOT.jar:na]

Default tenant role not found

Environment

  • Platform version: 7.2.4
  • Addon version: 2.0.2

Description of the bug or enhancement

Minimal reproducible example:
I'm just creating a new tenant.
ER: tenant created
AR: Exception:

java.lang.RuntimeException: Default tenant role not found
at com.haulmont.addon.sdbmt.core.sys.listener.TenantListener.assignDefaultTenantRole(TenantListener.java:82)
at com.haulmont.addon.sdbmt.core.sys.listener.TenantListener.updateTenantAdmin(TenantListener.java:74)
at com.haulmont.addon.sdbmt.core.sys.listener.TenantListener.onBeforeInsert(TenantListener.java:60)
at com.haulmont.addon.sdbmt.core.sys.listener.TenantListener.onBeforeInsert(TenantListener.java:39)
at com.haulmont.cuba.core.sys.listener.EntityListenerManager.fireListener(EntityListenerManager.java:242)

PredefinedRoleDefinitionRepository#predefinedRoleDefinitionsMap is empty
predefinedRoleDefinitionsMap.get(“default-tenant-role” ) is null
Roles screen doesn't contain default tenant role

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.