Skip to content
Merged
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 @@ -27,6 +27,7 @@
import com.epam.reportportal.base.infrastructure.commons.ContentTypeResolver;
import com.epam.reportportal.base.infrastructure.persistence.binary.UserBinaryDataService;
import com.epam.reportportal.base.infrastructure.persistence.dao.IntegrationRepository;
import com.epam.reportportal.base.infrastructure.persistence.dao.IntegrationTypeRepository;
import com.epam.reportportal.base.infrastructure.persistence.dao.ProjectRepository;
import com.epam.reportportal.base.infrastructure.persistence.dao.UserRepository;
import com.epam.reportportal.base.infrastructure.persistence.entity.enums.IntegrationAuthFlowEnum;
Expand All @@ -36,20 +37,27 @@
import com.epam.reportportal.extension.IntegrationGroupEnum;
import com.epam.reportportal.extension.PluginCommand;
import com.epam.reportportal.extension.github.command.SynchronizeGithubUserCommand;
import com.epam.reportportal.extension.github.event.listener.PluginLoadedEventListener;
import com.epam.reportportal.extension.github.oauth.GitHubOAuthProvider;
import com.epam.reportportal.extension.github.service.GitHubIntegrationStrategy;
import com.epam.reportportal.extension.github.service.GitHubRequiredParamNamesProvider;
import com.epam.reportportal.extension.github.utils.MemoizingSupplier;
import jakarta.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.jasypt.util.text.BasicTextEncryptor;
import org.pf4j.Extension;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;

Expand All @@ -58,11 +66,12 @@
*/
@Extension
@Slf4j
public class GitHubExtension implements AuthExtension {
public class GitHubExtension implements AuthExtension, DisposableBean {

public static final String SSO_LOGIN_PATH = "/oauth/login";
public static final String SCHEMA_SCRIPTS_DIR = "schema";
public static final String SCHEMA_SCRIPTS_DIR = "resources/schema";

private static final String PLUGIN_ID = "github";
private static final String PLUGIN_NAME = "GitHub OAuth Plugin";
private static final String DOCUMENTATION_LINK = "https://reportportal.io/docs/plugins/authorization/GitHubAuthorization";
private static final String DOCUMENTATION_LINK_FIELD = "documentationLink";
Expand All @@ -80,6 +89,12 @@ public boolean supports(Class<?> authentication) {
}
};

@Autowired
private ApplicationContext applicationContext;

@Autowired
private IntegrationTypeRepository integrationTypeRepository;

@Autowired
private UserRepository userRepository;

Expand Down Expand Up @@ -107,21 +122,29 @@ public boolean supports(Class<?> authentication) {
@Autowired
private BasicTextEncryptor encryptor;

@Autowired
private DataSource dataSource;

private GitHubUserReplicator replicator;
private GitHubOAuthProvider oauthProvider;
private Map<String, CommonPluginCommand<?>> commonCommands;

private Supplier<GitHubIntegrationStrategy> gitHubIntegrationStrategySupplier;
private Supplier<PluginLoadedEventListener> pluginLoadedListenerSupplier;


@PostConstruct
public void init() {
public void init() throws IOException {
log.info("Initializing GitHub OAuth extension");
this.gitHubIntegrationStrategySupplier = new MemoizingSupplier<>(
() -> new GitHubIntegrationStrategy(integrationRepository,
new UpdateAuthRequestValidator(new GitHubRequiredParamNamesProvider()), integrationDuplicateValidator,
encryptor));

this.pluginLoadedListenerSupplier = new MemoizingSupplier<>(
() -> new PluginLoadedEventListener(PLUGIN_ID, integrationTypeRepository, integrationRepository,
integrationType -> integrationType, dataSource));

replicator = new GitHubUserReplicator(
userRepository, projectRepository, personalProjectService,
userBinaryDataService, contentTypeResolver, userEventPublisher
Expand All @@ -130,8 +153,24 @@ public void init() {
SynchronizeGithubUserCommand syncCommand = new SynchronizeGithubUserCommand(replicator);
commonCommands = Map.of(syncCommand.getName(), syncCommand);

/* initApplicationListeners();
initSchema();*/
initListeners();
}

private void initListeners() {
ApplicationEventMulticaster applicationEventMulticaster = applicationContext.getBean(
AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
ApplicationEventMulticaster.class
);
applicationEventMulticaster.addApplicationListener(pluginLoadedListenerSupplier.get());
}

@Override
public void destroy() {
ApplicationEventMulticaster applicationEventMulticaster = applicationContext.getBean(
AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
ApplicationEventMulticaster.class
);
applicationEventMulticaster.removeApplicationListener(pluginLoadedListenerSupplier.get());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2026 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.epam.reportportal.extension.github.event.listener;

import static com.epam.reportportal.extension.github.GitHubExtension.SCHEMA_SCRIPTS_DIR;

import com.epam.reportportal.base.core.events.domain.PluginUploadedEvent;
import com.epam.reportportal.base.infrastructure.persistence.dao.IntegrationRepository;
import com.epam.reportportal.base.infrastructure.persistence.dao.IntegrationTypeRepository;
import com.epam.reportportal.extension.github.info.PluginInfoProvider;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
import javax.sql.DataSource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;

/**
* @author Andrei Piankouski
*/
@Slf4j
public class PluginLoadedEventListener implements ApplicationListener<PluginUploadedEvent> {

private final String pluginId;
private final IntegrationTypeRepository integrationTypeRepository;
private final IntegrationRepository integrationRepository;
private final PluginInfoProvider pluginInfoProvider;
private final DataSource dataSource;

public PluginLoadedEventListener(String pluginId,
IntegrationTypeRepository integrationTypeRepository,
IntegrationRepository integrationRepository, PluginInfoProvider pluginInfoProvider, DataSource dataSource) {
this.pluginId = pluginId;
this.integrationTypeRepository = integrationTypeRepository;
this.integrationRepository = integrationRepository;
this.pluginInfoProvider = pluginInfoProvider;
this.dataSource = dataSource;
}

@Override
public void onApplicationEvent(PluginUploadedEvent event) {
if (!supports(event)) {
return;
}
initSchema();
}

private boolean supports(PluginUploadedEvent event) {
return Objects.nonNull(event.getPluginActivityResource())
&& pluginId.equals(event.getPluginActivityResource().getName());
}

@SneakyThrows
public void initSchema() {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(getClass().getClassLoader());
Resource[] resources = resolver.getResources("classpath:" + SCHEMA_SCRIPTS_DIR + "/*.sql");
log.debug("GitHub schema init: found {} script(s)", resources.length);
if (resources.length == 0) {
return;
}
Comment on lines +77 to +80

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== SCHEMA_SCRIPTS_DIR definition =="
fd -i 'GitHubExtension.java' --exec sh -c 'echo "--- $1"; sed -n "1,220p" "$1"' sh {}

echo
echo "== SQL resources present in repository =="
fd -i '\.sql$'

Repository: reportportal/plugin-auth-github

Length of output: 8825


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find and read the PluginLoadedEventListener.java file
fd -i 'PluginLoadedEventListener.java' --exec cat -n {} \;

Repository: reportportal/plugin-auth-github

Length of output: 4331


Emit a warning log when no schema scripts are found.

The current code returns silently on line 79 with only a debug-level log when resources.length == 0. In production deployments where debug logging is disabled, this masks potential issues like broken classpath patterns or failed resource packaging, causing database migrations to be skipped without any indication. Add a log.warn() call when zero SQL scripts are discovered to ensure deployment problems are visible.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/epam/reportportal/extension/github/event/listener/PluginLoadedEventListener.java`
around lines 77 - 80, The GitHub schema init currently only logs at debug and
returns silently when resources.length == 0; update PluginLoadedEventListener
(the block that logs "GitHub schema init: found {} script(s)") to emit a warning
via log.warn(...) just before returning when no SQL scripts are found
(resources.length == 0), including contextual text that indicates schema scripts
were not discovered (mention resources/classpath or migration scripts) so
missing scripts are visible in production logs.

Arrays.sort(resources, Comparator.comparing(Resource::getFilename));
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
for (Resource r : resources) {
log.info("GitHub schema init: executing {}", r.getFilename());
try (InputStream is = r.getInputStream()) {
String sql = new String(is.readAllBytes(), StandardCharsets.UTF_8);
jdbcTemplate.execute(sql);
}
}
Comment on lines +82 to +89

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and examine the file
find . -name "PluginLoadedEventListener.java" -type f

Repository: reportportal/plugin-auth-github

Length of output: 175


🏁 Script executed:

# Also search for any transaction-related configuration or usage
rg -i "transactionmanager|transactiontemplate|@transactional" --type java | head -20

Repository: reportportal/plugin-auth-github

Length of output: 170


🏁 Script executed:

# Check for migration tools usage
rg -i "flyway|liquibase" --type java

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Check for existing Spring configuration or DataSource management
rg "DataSource|JdbcTemplate" --type java -B 2 -A 2 | head -40

Repository: reportportal/plugin-auth-github

Length of output: 4518


🏁 Script executed:

# Let's examine the actual file to see the full context of the initSchema method
cat -n src/main/java/com/epam/reportportal/extension/github/event/listener/PluginLoadedEventListener.java | sed -n '70,100p'

Repository: reportportal/plugin-auth-github

Length of output: 1178


🏁 Script executed:

# Check what method this is part of and the full context
cat -n src/main/java/com/epam/reportportal/extension/github/event/listener/PluginLoadedEventListener.java | sed -n '60,110p'

Repository: reportportal/plugin-auth-github

Length of output: 1511


🏁 Script executed:

# Let's also check if there's a PlatformTransactionManager bean configured in the project
rg "PlatformTransactionManager|TransactionManager" --type java

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Check the Spring version and available transaction dependencies
fd "pom.xml|build.gradle" -type f | head -5

Repository: reportportal/plugin-auth-github

Length of output: 245


🏁 Script executed:

# Find the build configuration files
find . -maxdepth 2 -name "pom.xml" -o -name "build.gradle"

Repository: reportportal/plugin-auth-github

Length of output: 89


🏁 Script executed:

# Let's check the pom.xml to see Spring version and transaction dependencies
head -100 pom.xml

Repository: reportportal/plugin-auth-github

Length of output: 141


🏁 Script executed:

# Check if there's a PlatformTransactionManager configured anywhere
rg "PlatformTransactionManager|TransactionManager|@EnableTransactionManagement" --type java

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Let's also check how the onApplicationEvent method is called - is it in a transaction context?
cat -n src/main/java/com/epam/reportportal/extension/github/event/listener/PluginLoadedEventListener.java | head -100

Repository: reportportal/plugin-auth-github

Length of output: 4331


🏁 Script executed:

# Check the build.gradle for dependencies
cat build.gradle

Repository: reportportal/plugin-auth-github

Length of output: 3687


🏁 Script executed:

# Search for transaction management in the broader codebase
rg "TransactionTemplate|DataSourceTransactionManager" --type java

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Check if there's a test or configuration that shows how initSchema should behave
rg "initSchema" --type java -B 3 -A 3

Repository: reportportal/plugin-auth-github

Length of output: 1932


🏁 Script executed:

# Check if PlatformTransactionManager is configured in the Spring context
rg "PlatformTransactionManager|TransactionManager|@EnableTransactionManagement|@Bean" --type java -A 2

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Let's check if there's any Spring configuration class that sets up transaction management
find . -name "*Config*" -type f | head -10

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Check the schema files to understand the complexity of the migrations
find . -name "*.sql" -type f 2>/dev/null

Repository: reportportal/plugin-auth-github

Length of output: 137


🏁 Script executed:

# Check if there's any existing issue or comment in the codebase about transactions for schema init
rg -i "schema|migration|transaction" --type java src/main/java/com/epam/reportportal/extension/github/event/listener/PluginLoadedEventListener.java -B 2 -A 2

Repository: reportportal/plugin-auth-github

Length of output: 1100


🏁 Script executed:

# Check if `@Transactional` could be used instead - verify transaction manager availability
rg "spring.jpa.hibernate|spring.datasource|DataSourceAutoConfiguration" --type properties

Repository: reportportal/plugin-auth-github

Length of output: 109


🏁 Script executed:

# Look for any Spring Boot auto-configuration or transaction setup
find . -name "application*.properties" -o -name "application*.yml"

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Check for Spring configuration files
find . -name "*.properties" -o -name "*.yml" -o -name "*.yaml"

Repository: reportportal/plugin-auth-github

Length of output: 316


🏁 Script executed:

# Look for Spring Bean configuration
rg "@Configuration|@EnableTransactionManagement|transactionManager" --type java

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Check if JdbcTemplate with DataSource auto-configures a transaction manager in Spring Boot
rg "class.*Configuration|@Bean" --type java -A 5 | head -40

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Let's check the schema file to understand what operations are being performed
cat src/main/resources/schema/001_restore_github_integration.sql

Repository: reportportal/plugin-auth-github

Length of output: 986


🏁 Script executed:

# Check if Spring Boot's auto-configuration includes transaction support for JdbcTemplate
rg "DataSourceTransactionManager|transactionManager" src/main --type java

Repository: reportportal/plugin-auth-github

Length of output: 57


🏁 Script executed:

# Verify Spring version and check if auto-configuration applies
cat build.gradle | grep -i "spring-boot"

Repository: reportportal/plugin-auth-github

Length of output: 150


Wrap schema initialization in a single database transaction to ensure atomicity.

The initSchema() method executes SQL scripts without transaction management. Even the single schema file contains multiple operations (INSERT, DELETE, DROP TABLE) that should be atomic—if any operation fails midway, the database is left in a partially applied state. Wrap the script execution loop in a transaction using TransactionTemplate with DataSourceTransactionManager.

Proposed fix (transaction wrapper)
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.transaction.support.TransactionTemplate;
...
   public void initSchema() {
...
-    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
-    for (Resource r : resources) {
-      log.info("GitHub schema init: executing {}", r.getFilename());
-      try (InputStream is = r.getInputStream()) {
-        String sql = new String(is.readAllBytes(), StandardCharsets.UTF_8);
-        jdbcTemplate.execute(sql);
-      }
-    }
+    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+    TransactionTemplate tx = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
+    tx.executeWithoutResult(status -> {
+      for (Resource r : resources) {
+        log.info("GitHub schema init: executing {}", r.getFilename());
+        try (InputStream is = r.getInputStream()) {
+          String sql = new String(is.readAllBytes(), StandardCharsets.UTF_8);
+          jdbcTemplate.execute(sql);
+        } catch (Exception e) {
+          status.setRollbackOnly();
+          throw new IllegalStateException("Failed to execute schema script: " + r.getFilename(), e);
+        }
+      }
+    });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
for (Resource r : resources) {
log.info("GitHub schema init: executing {}", r.getFilename());
try (InputStream is = r.getInputStream()) {
String sql = new String(is.readAllBytes(), StandardCharsets.UTF_8);
jdbcTemplate.execute(sql);
}
}
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
TransactionTemplate tx = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
tx.executeWithoutResult(status -> {
for (Resource r : resources) {
log.info("GitHub schema init: executing {}", r.getFilename());
try (InputStream is = r.getInputStream()) {
String sql = new String(is.readAllBytes(), StandardCharsets.UTF_8);
jdbcTemplate.execute(sql);
} catch (Exception e) {
status.setRollbackOnly();
throw new IllegalStateException("Failed to execute schema script: " + r.getFilename(), e);
}
}
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/epam/reportportal/extension/github/event/listener/PluginLoadedEventListener.java`
around lines 82 - 89, The schema initialization in
PluginLoadedEventListener.initSchema currently executes resources (Resource r)
via a JdbcTemplate without transaction management; wrap the entire loop in a
single transaction using a TransactionTemplate constructed with a
DataSourceTransactionManager (or use PlatformTransactionManager) so all SQL from
resources are executed atomically and roll back on failure; create
TransactionTemplate tx = new TransactionTemplate(new
DataSourceTransactionManager(dataSource)) (or inject the
PlatformTransactionManager), then run tx.execute(status -> { for (Resource r :
resources) { read bytes, jdbcTemplate.execute(sql); } return null; }) to ensure
atomicity and proper rollback.

log.info("GitHub schema init: completed");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2026 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.epam.reportportal.extension.github.info;

import com.epam.reportportal.base.infrastructure.persistence.entity.integration.IntegrationType;

/**
* @author <a href="mailto:ivan_budayeu@epam.com">Ivan Budayeu</a>
*/
public interface PluginInfoProvider {

IntegrationType provide(IntegrationType integrationType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2026 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.epam.reportportal.extension.github.info.impl;

import static java.util.Optional.ofNullable;

import com.epam.reportportal.base.infrastructure.persistence.entity.integration.IntegrationType;
import com.epam.reportportal.base.infrastructure.rules.exception.ErrorType;
import com.epam.reportportal.base.infrastructure.rules.exception.ReportPortalException;
import com.epam.reportportal.extension.github.info.PluginInfoProvider;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
* @author <a href="mailto:ivan_budayeu@epam.com">Ivan Budayeu</a>
*/
public class PluginInfoProviderImpl implements PluginInfoProvider {

private static final String BINARY_DATA_KEY = "binaryData";
private static final String DESCRIPTION_KEY = "description";
private static final String METADATA_KEY = "metadata";

private static final String PLUGIN_DESCRIPTION =
"The integration provides an exchange of information between ReportPortal and the Jira Cloud, such as posting issues and linking issues, getting updates on their statuses.";

Comment on lines +42 to +44

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Incorrect integration description references Jira instead of GitHub.

PLUGIN_DESCRIPTION on Line 43 describes Jira Cloud, which is inconsistent for the GitHub plugin and will surface incorrect metadata to users.

Proposed fix
-  private static final String PLUGIN_DESCRIPTION =
-      "The integration provides an exchange of information between ReportPortal and the Jira Cloud, such as posting issues and linking issues, getting updates on their statuses.";
+  private static final String PLUGIN_DESCRIPTION =
+      "The integration provides an exchange of information between ReportPortal and GitHub, such as posting issues, linking issues, and getting updates on their statuses.";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/epam/reportportal/extension/github/info/impl/PluginInfoProviderImpl.java`
around lines 42 - 44, PLUGIN_DESCRIPTION in PluginInfoProviderImpl currently
mentions Jira Cloud; update the constant's string to accurately describe the
GitHub integration (e.g., exchange of issue creation/linking and status updates
between ReportPortal and GitHub) so plugin metadata reflects GitHub rather than
Jira. Locate the PLUGIN_DESCRIPTION constant in the PluginInfoProviderImpl class
and replace the Jira-specific wording with GitHub-specific wording that matches
the plugin's functionality.

static final Map<String, Object> PLUGIN_METADATA = Map.of(
"embedded", false,
"multiple", false
);

private final String resourcesDir;
private final String propertyFile;

public PluginInfoProviderImpl(String resourcesDir, String propertyFile) {
this.resourcesDir = resourcesDir;
this.propertyFile = propertyFile;
}

@Override
public IntegrationType provide(IntegrationType integrationType) {
loadBinaryDataInfo(integrationType);
updateDescription(integrationType);
updateMetadata(integrationType);
return integrationType;
}

private void loadBinaryDataInfo(IntegrationType integrationType) {
Map<String, Object> details = integrationType.getDetails().getDetails();
if (ofNullable(details.get(BINARY_DATA_KEY)).isEmpty()) {
try (InputStream propertiesStream = Files.newInputStream(
Paths.get(resourcesDir, propertyFile))) {
Properties binaryDataProperties = new Properties();
binaryDataProperties.load(propertiesStream);
Map<String, String> binaryDataInfo = binaryDataProperties.entrySet().stream().collect(
HashMap::new, (map, entry) -> map.put(String.valueOf(entry.getKey()),
String.valueOf(entry.getValue())
), HashMap::putAll);
details.put(BINARY_DATA_KEY, binaryDataInfo);
} catch (IOException ex) {
throw new ReportPortalException(ErrorType.UNABLE_TO_LOAD_BINARY_DATA, ex.getMessage());
}
}
}

private void updateDescription(IntegrationType integrationType) {
Map<String, Object> details = integrationType.getDetails().getDetails();
details.put(DESCRIPTION_KEY, PLUGIN_DESCRIPTION);
}

private void updateMetadata(IntegrationType integrationType) {
Map<String, Object> details = integrationType.getDetails().getDetails();
details.put(METADATA_KEY, PLUGIN_METADATA);
}
}
27 changes: 27 additions & 0 deletions src/main/resources/schema/001_restore_github_integration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
DO
'
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = ''integration_backup'') THEN

-- restore saml integration from backup
INSERT INTO integration (name, type, params, creator, creation_date, enabled)
SELECT ib.name,
(SELECT it.id FROM integration_type it WHERE it.auth_flow = ''OAUTH'' AND it.group_type = ''AUTH'' AND it.plugin_type = ''EXTENSION''),
ib.params,
''SYSTEM'',
now(),
true
FROM integration_backup ib
WHERE ib.auth_type = ''github''
ON CONFLICT (id) DO NOTHING;

-- delete backup record
DELETE from integration_backup ib WHERE ib.auth_type = ''github'';

-- drop table if empty
IF NOT EXISTS (SELECT 1 FROM integration_backup) THEN
DROP TABLE integration_backup;
END IF;
END IF;
END;
';
Loading