|
19 | 19 | import static org.junit.jupiter.api.Assertions.assertThrows; |
20 | 20 | import static org.junit.jupiter.api.Assertions.assertTrue; |
21 | 21 | import static org.junit.jupiter.api.Assumptions.assumeFalse; |
| 22 | +import static org.openmetadata.service.jdbi3.AppRepository.APP_BOT_IMPERSONATION_ROLE; |
| 23 | +import static org.openmetadata.service.jdbi3.AppRepository.APP_BOT_ROLE; |
22 | 24 |
|
23 | 25 | import com.fasterxml.jackson.core.type.TypeReference; |
24 | 26 | import java.time.Duration; |
|
45 | 47 | import org.openmetadata.schema.entity.app.ScheduleTimeline; |
46 | 48 | import org.openmetadata.schema.entity.app.ScheduleType; |
47 | 49 | import org.openmetadata.schema.entity.app.ScheduledExecutionContext; |
| 50 | +import org.openmetadata.schema.entity.teams.User; |
48 | 51 | import org.openmetadata.schema.utils.JsonUtils; |
49 | 52 | import org.openmetadata.schema.utils.ResultList; |
50 | 53 | import org.openmetadata.sdk.client.OpenMetadataClient; |
@@ -813,4 +816,134 @@ void test_listApps_combineAgentTypeWithOtherFilters(TestNamespace ns) throws Exc |
813 | 816 | assertNotNull(apps.getData()); |
814 | 817 | assertTrue(apps.getData().size() <= 50); |
815 | 818 | } |
| 819 | + |
| 820 | + @Test |
| 821 | + void test_appBotRole_withoutImpersonation(TestNamespace ns) throws Exception { |
| 822 | + HttpClient httpClient = SdkClients.adminClient().getHttpClient(); |
| 823 | + String appName = "noImpApp" + System.currentTimeMillis(); |
| 824 | + |
| 825 | + try { |
| 826 | + CreateAppMarketPlaceDefinitionReq marketPlaceReq = |
| 827 | + new CreateAppMarketPlaceDefinitionReq() |
| 828 | + .withName(appName) |
| 829 | + .withDisplayName("No Impersonation App") |
| 830 | + .withDescription("Test app without impersonation") |
| 831 | + .withFeatures("test features") |
| 832 | + .withDeveloper("Test Developer") |
| 833 | + .withDeveloperUrl("https://www.example.com") |
| 834 | + .withPrivacyPolicyUrl("https://www.example.com/privacy") |
| 835 | + .withSupportEmail("support@example.com") |
| 836 | + .withClassName("org.openmetadata.service.resources.apps.TestApp") |
| 837 | + .withAppType(AppType.Internal) |
| 838 | + .withScheduleType(ScheduleType.Scheduled) |
| 839 | + .withRuntime(new ScheduledExecutionContext().withEnabled(true)) |
| 840 | + .withAppConfiguration(new HashMap<>()) |
| 841 | + .withPermission(NativeAppPermission.All); |
| 842 | + |
| 843 | + AppMarketPlaceDefinition marketPlaceDef = |
| 844 | + httpClient.execute( |
| 845 | + HttpMethod.POST, |
| 846 | + "/v1/apps/marketplace", |
| 847 | + marketPlaceReq, |
| 848 | + AppMarketPlaceDefinition.class); |
| 849 | + |
| 850 | + CreateApp createApp = |
| 851 | + new CreateApp() |
| 852 | + .withName(marketPlaceDef.getName()) |
| 853 | + .withAppConfiguration(marketPlaceDef.getAppConfiguration()) |
| 854 | + .withAppSchedule(new AppSchedule().withScheduleTimeline(ScheduleTimeline.HOURLY)) |
| 855 | + .withAllowBotImpersonation(false); |
| 856 | + |
| 857 | + App app = httpClient.execute(HttpMethod.POST, "/v1/apps", createApp, App.class); |
| 858 | + assertNotNull(app); |
| 859 | + |
| 860 | + App retrievedApp = |
| 861 | + httpClient.execute( |
| 862 | + HttpMethod.GET, "/v1/apps/name/" + appName + "?fields=bot", null, App.class); |
| 863 | + assertNotNull(retrievedApp.getBot(), "Bot should be created for the app"); |
| 864 | + |
| 865 | + String botUserName = appName + "Bot"; |
| 866 | + User botUser = |
| 867 | + httpClient.execute( |
| 868 | + HttpMethod.GET, "/v1/users/name/" + botUserName + "?fields=roles", null, User.class); |
| 869 | + |
| 870 | + assertNotNull(botUser.getRoles(), "Bot user should have roles assigned"); |
| 871 | + assertTrue( |
| 872 | + botUser.getRoles().stream().anyMatch(r -> r.getName().equals(APP_BOT_ROLE)), |
| 873 | + "Bot without impersonation should have ApplicationBotRole"); |
| 874 | + assertTrue( |
| 875 | + botUser.getRoles().stream() |
| 876 | + .noneMatch(r -> r.getName().equals(APP_BOT_IMPERSONATION_ROLE)), |
| 877 | + "Bot without impersonation should NOT have ApplicationBotImpersonationRole"); |
| 878 | + |
| 879 | + } finally { |
| 880 | + try { |
| 881 | + Apps.uninstall(appName, true); |
| 882 | + } catch (Exception ignored) { |
| 883 | + } |
| 884 | + } |
| 885 | + } |
| 886 | + |
| 887 | + @Test |
| 888 | + void test_appBotRole_withImpersonation(TestNamespace ns) throws Exception { |
| 889 | + HttpClient httpClient = SdkClients.adminClient().getHttpClient(); |
| 890 | + String appName = "impApp" + System.currentTimeMillis(); |
| 891 | + |
| 892 | + try { |
| 893 | + CreateAppMarketPlaceDefinitionReq marketPlaceReq = |
| 894 | + new CreateAppMarketPlaceDefinitionReq() |
| 895 | + .withName(appName) |
| 896 | + .withDisplayName("With Impersonation App") |
| 897 | + .withDescription("Test app with impersonation") |
| 898 | + .withFeatures("test features") |
| 899 | + .withDeveloper("Test Developer") |
| 900 | + .withDeveloperUrl("https://www.example.com") |
| 901 | + .withPrivacyPolicyUrl("https://www.example.com/privacy") |
| 902 | + .withSupportEmail("support@example.com") |
| 903 | + .withClassName("org.openmetadata.service.resources.apps.TestApp") |
| 904 | + .withAppType(AppType.Internal) |
| 905 | + .withScheduleType(ScheduleType.Scheduled) |
| 906 | + .withRuntime(new ScheduledExecutionContext().withEnabled(true)) |
| 907 | + .withAppConfiguration(new HashMap<>()) |
| 908 | + .withPermission(NativeAppPermission.All); |
| 909 | + |
| 910 | + AppMarketPlaceDefinition marketPlaceDef = |
| 911 | + httpClient.execute( |
| 912 | + HttpMethod.POST, |
| 913 | + "/v1/apps/marketplace", |
| 914 | + marketPlaceReq, |
| 915 | + AppMarketPlaceDefinition.class); |
| 916 | + |
| 917 | + CreateApp createApp = |
| 918 | + new CreateApp() |
| 919 | + .withName(marketPlaceDef.getName()) |
| 920 | + .withAppConfiguration(marketPlaceDef.getAppConfiguration()) |
| 921 | + .withAppSchedule(new AppSchedule().withScheduleTimeline(ScheduleTimeline.HOURLY)) |
| 922 | + .withAllowBotImpersonation(true); |
| 923 | + |
| 924 | + App app = httpClient.execute(HttpMethod.POST, "/v1/apps", createApp, App.class); |
| 925 | + assertNotNull(app); |
| 926 | + |
| 927 | + App retrievedApp = |
| 928 | + httpClient.execute( |
| 929 | + HttpMethod.GET, "/v1/apps/name/" + appName + "?fields=bot", null, App.class); |
| 930 | + assertNotNull(retrievedApp.getBot(), "Bot should be created for the app"); |
| 931 | + |
| 932 | + String botUserName = appName + "Bot"; |
| 933 | + User botUser = |
| 934 | + httpClient.execute( |
| 935 | + HttpMethod.GET, "/v1/users/name/" + botUserName + "?fields=roles", null, User.class); |
| 936 | + |
| 937 | + assertNotNull(botUser.getRoles(), "Bot user should have roles assigned"); |
| 938 | + assertTrue( |
| 939 | + botUser.getRoles().stream().anyMatch(r -> r.getName().equals(APP_BOT_IMPERSONATION_ROLE)), |
| 940 | + "Bot with impersonation should have ApplicationBotImpersonationRole"); |
| 941 | + |
| 942 | + } finally { |
| 943 | + try { |
| 944 | + Apps.uninstall(appName, true); |
| 945 | + } catch (Exception ignored) { |
| 946 | + } |
| 947 | + } |
| 948 | + } |
816 | 949 | } |
0 commit comments