Compare commits
13 Commits
feature/ma
...
vdrokov_fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82bf612299 | ||
|
|
0c25678af9 | ||
|
|
52339da247 | ||
|
|
d25966f7ca | ||
|
|
3268b36046 | ||
|
|
f11cc1d442 | ||
|
|
1352dd1657 | ||
|
|
bf8573f1ff | ||
|
|
491f07624b | ||
|
|
4666d74567 | ||
|
|
13193d142c | ||
|
|
3fbfd1c490 | ||
|
|
c9a27e2f06 |
@@ -336,10 +336,19 @@ public enum EDatabaseTypeName {
|
||||
.getProjectPreferenceManager()
|
||||
.getBoolean(IProjectSettingPreferenceConstants.METADATA_DBCONNECTION_ODBC_ENABLE);
|
||||
isSupport = isSupportODBC;
|
||||
} else if (EDatabaseTypeName.SAS == this) {
|
||||
isSupport = false;
|
||||
}
|
||||
|
||||
return isSupport;
|
||||
}
|
||||
|
||||
public static boolean isDeprecateDbType(String dbType) {
|
||||
if (EDatabaseTypeName.SAS.getXmlName().equals(dbType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for dbType.
|
||||
|
||||
@@ -418,6 +418,52 @@ public class NodeUtil {
|
||||
return conns;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC
|
||||
* <p>
|
||||
* The method searches for the incoming node connections of type
|
||||
* on a processing path and returns the first ones only
|
||||
* </p>
|
||||
*
|
||||
* @param node
|
||||
* @param type - node type to look for
|
||||
* @return
|
||||
*/
|
||||
public static List<? extends IConnection> getFirstIncomingLineConnectionsOfType(INode node, String type) {
|
||||
if (type == null)
|
||||
return new ArrayList<IConnection>();
|
||||
|
||||
Set<String> uniqueNamesDone = new HashSet<String>();
|
||||
List<? extends IConnection> allIncomingConnections = getFirstIncomingLineConnectionsOfType(node, uniqueNamesDone, type);
|
||||
|
||||
return allIncomingConnections;
|
||||
}
|
||||
|
||||
private static List<? extends IConnection> getFirstIncomingLineConnectionsOfType(INode node, Set<String> uniqueNamesDone, String type) {
|
||||
List<IConnection> conns = new ArrayList<IConnection>();
|
||||
|
||||
List<? extends IConnection> incomingConnections = node.getIncomingConnections();
|
||||
if (incomingConnections != null) {
|
||||
|
||||
for (int i = 0; i < incomingConnections.size(); i++) {
|
||||
|
||||
IConnection connection = incomingConnections.get(i);
|
||||
INode nextNode = connection.getSource();
|
||||
|
||||
if (!uniqueNamesDone.contains(nextNode.getUniqueName())) {
|
||||
uniqueNamesDone.add(nextNode.getUniqueName());
|
||||
|
||||
if (type.equals((String)nextNode.getElementParameter("COMPONENT_NAME").getValue())) {
|
||||
conns.add(connection);
|
||||
} else {
|
||||
conns.addAll(getFirstIncomingLineConnectionsOfType(nextNode, uniqueNamesDone, type)); // follow this way
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return conns;
|
||||
}
|
||||
|
||||
public static INode getFirstMergeNode(INode node) {
|
||||
INode mergeNode = null;
|
||||
for (IConnection connection : node.getOutgoingConnections()) {
|
||||
|
||||
@@ -67,9 +67,6 @@ import org.talend.core.language.LanguageManager;
|
||||
import org.talend.core.model.components.ComponentCategory;
|
||||
import org.talend.core.model.components.EComponentType;
|
||||
import org.talend.core.model.components.IComponent;
|
||||
import org.talend.core.model.components.IComponentsFactory;
|
||||
import org.talend.core.model.components.IComponentsService;
|
||||
import org.talend.core.model.context.ContextUtils;
|
||||
import org.talend.core.model.general.ModuleNeeded;
|
||||
import org.talend.core.model.general.Project;
|
||||
import org.talend.core.model.metadata.IMetadataColumn;
|
||||
@@ -183,8 +180,6 @@ public class ProcessorUtilities {
|
||||
|
||||
private static boolean isDebug = false;
|
||||
|
||||
private static boolean isCIMode = false;
|
||||
|
||||
private static boolean isDynamicJobAndCITest = false;
|
||||
|
||||
private static JobInfo mainJobInfo;
|
||||
@@ -1099,7 +1094,7 @@ public class ProcessorUtilities {
|
||||
checkMetadataDynamic(currentProcess, jobInfo);
|
||||
|
||||
int options = TalendProcessOptionConstants.MODULES_DEFAULT;
|
||||
if (isCIMode && BitwiseOptionUtils.containOption(option, GENERATE_MAIN_ONLY)) {
|
||||
if (isCIMode() && BitwiseOptionUtils.containOption(option, GENERATE_MAIN_ONLY)) {
|
||||
options |= TalendProcessOptionConstants.MODULES_WITH_CHILDREN;
|
||||
}
|
||||
Set<ModuleNeeded> neededLibraries = new HashSet<>();
|
||||
@@ -2697,12 +2692,11 @@ public class ProcessorUtilities {
|
||||
}
|
||||
|
||||
public static boolean isCIMode() {
|
||||
return isCIMode;
|
||||
// if it's CI mode , then the system property of maven.local.repository will store the value of studio
|
||||
// m2 path,otherwise it's null
|
||||
return System.getProperty("maven.local.repository") != null;
|
||||
}
|
||||
|
||||
public static void setCIMode(boolean isCIMode) {
|
||||
ProcessorUtilities.isCIMode = isCIMode;
|
||||
}
|
||||
|
||||
public static void setExportConfig(boolean export) {
|
||||
setExportConfig(JavaUtils.JAVA_APP_NAME, null, null, export, new Date());
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-shared-utils</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.15</version>
|
||||
<version>1.4.16</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -22,11 +22,23 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-shared-utils</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-shared-utils</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -37,6 +49,12 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-shared-utils</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<tcomp.version>1.31.0</tcomp.version>
|
||||
<tcomp.version>1.32.0</tcomp.version>
|
||||
<slf4j.version>1.7.25</slf4j.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<artifactItem>
|
||||
<groupId>org.talend.studio</groupId>
|
||||
<artifactId>studio-maven-repository</artifactId>
|
||||
<version>7.4.1.v20210416</version>
|
||||
<version>7.4.1.v20210427</version>
|
||||
<type>zip</type>
|
||||
<overWrite>true</overWrite>
|
||||
<outputDirectory>${project.basedir}/../repository</outputDirectory>
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<!-- This dependency provides the implementation of compiler "jdt": -->
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-shared-utils</artifactId>
|
||||
<version>3.3.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-compiler-jdt</artifactId>
|
||||
@@ -53,6 +58,11 @@
|
||||
<artifactId>plexus-utils</artifactId>
|
||||
<version>3.0.24</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-shared-utils</artifactId>
|
||||
<version>3.3.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -60,6 +70,11 @@
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-shared-utils</artifactId>
|
||||
<version>3.3.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-utils</artifactId>
|
||||
@@ -82,6 +97,11 @@
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.shared</groupId>
|
||||
<artifactId>maven-shared-utils</artifactId>
|
||||
<version>3.3.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-utils</artifactId>
|
||||
@@ -108,6 +128,11 @@
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-utils</artifactId>
|
||||
<version>3.0.24</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
|
||||
@@ -97,7 +97,7 @@ public abstract class MavenCommandLauncher {
|
||||
|
||||
private Map<String, Object> argumentsMap;
|
||||
|
||||
private static final String REGEX_TEST_CASE_FAILURES_STR = "\\[ERROR\\] Tests run:.*\\[ERROR\\] There are test\\p{Print}+\n";
|
||||
private static final String REGEX_TEST_CASE_FAILURES_STR = "\\[ERROR\\] There are test failures.*\n";
|
||||
|
||||
private static final Pattern REGEX_TEST_CASE_FAILURES = Pattern.compile(REGEX_TEST_CASE_FAILURES_STR, Pattern.DOTALL);
|
||||
|
||||
|
||||
@@ -355,8 +355,9 @@ public class PomIdsHelper {
|
||||
|
||||
public static boolean skipFolders() {
|
||||
String projectTechName = ProjectManager.getInstance().getCurrentProject().getTechnicalLabel();
|
||||
ProjectPreferenceManager manager = getPreferenceManager(projectTechName);
|
||||
return manager.getBoolean(MavenConstants.SKIP_FOLDERS);
|
||||
Project project = ProjectManager.getInstance().getProjectFromProjectTechLabel(projectTechName);
|
||||
ProjectPreferenceManager preferenceManager = new ProjectPreferenceManager(project, DesignerMavenPlugin.PLUGIN_ID, false);
|
||||
return preferenceManager.getBoolean(MavenConstants.SKIP_FOLDERS);
|
||||
}
|
||||
|
||||
public static boolean isValidGroupId(String text) {
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
package org.talend.platform.logging;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.talend.utils.format.PresentableBox;
|
||||
|
||||
@@ -18,6 +26,8 @@ public class Activator extends AbstractUIPlugin {
|
||||
// The shared instance
|
||||
private static Activator plugin;
|
||||
|
||||
private static String version = null;// studio version
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
@@ -33,6 +43,7 @@ public class Activator extends AbstractUIPlugin {
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
plugin = this;
|
||||
version = null;
|
||||
if (log.isInfoEnabled()) {
|
||||
Object version = getVersion();
|
||||
String mess = "Starting Talend's platform log system."; //$NON-NLS-1$
|
||||
@@ -51,6 +62,7 @@ public class Activator extends AbstractUIPlugin {
|
||||
*/
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
version = null;
|
||||
super.stop(context);
|
||||
}
|
||||
|
||||
@@ -64,10 +76,43 @@ public class Activator extends AbstractUIPlugin {
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
String version = System.getProperty("talend.studio.version"); //$NON-NLS-1$
|
||||
if (version == null || "".equals(version.trim())) { //$NON-NLS-1$
|
||||
version = (String) getDefault().getBundle().getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION);
|
||||
if (version == null) {
|
||||
try {
|
||||
File file = null;
|
||||
try {
|
||||
file = new File(Platform.getInstallLocation().getDataArea(".eclipseproduct").getPath());
|
||||
} catch (IOException e1) {
|
||||
//
|
||||
}
|
||||
Properties prop = new Properties();
|
||||
if (file != null && file.exists()) {
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
prop.load(fis);
|
||||
} catch (Exception e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
version = prop.getProperty("version");
|
||||
|
||||
if (StringUtils.isEmpty(version)) {
|
||||
version = System.getProperty("talend.studio.version"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(version)) {
|
||||
Bundle b = Platform.getBundle("org.talend.commons.runtime");
|
||||
if (b != null) {
|
||||
version = b.getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//
|
||||
}
|
||||
|
||||
if (version == null || "".equals(version.trim())) { //$NON-NLS-1$
|
||||
version = (String) getDefault().getBundle().getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -61,6 +61,7 @@ import org.talend.commons.utils.workbench.resources.ResourceUtils;
|
||||
import org.talend.core.GlobalServiceRegister;
|
||||
import org.talend.core.context.Context;
|
||||
import org.talend.core.context.RepositoryContext;
|
||||
import org.talend.core.database.EDatabaseTypeName;
|
||||
import org.talend.core.model.context.ContextUtils;
|
||||
import org.talend.core.model.context.link.ContextLinkService;
|
||||
import org.talend.core.model.metadata.builder.connection.Connection;
|
||||
@@ -70,6 +71,7 @@ import org.talend.core.model.properties.BusinessProcessItem;
|
||||
import org.talend.core.model.properties.ByteArray;
|
||||
import org.talend.core.model.properties.ConnectionItem;
|
||||
import org.talend.core.model.properties.ContextItem;
|
||||
import org.talend.core.model.properties.DatabaseConnectionItem;
|
||||
import org.talend.core.model.properties.FileItem;
|
||||
import org.talend.core.model.properties.FolderItem;
|
||||
import org.talend.core.model.properties.FolderType;
|
||||
@@ -367,6 +369,14 @@ public class ImportBasicHandler extends AbstractImportExecutableHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ERepositoryObjectType.METADATA_CONNECTIONS.equals(itemType) && (item instanceof DatabaseConnectionItem)) {
|
||||
DatabaseConnectionItem connItem = (DatabaseConnectionItem) item;
|
||||
if (EDatabaseTypeName.isDeprecateDbType(connItem.getTypeName())) {
|
||||
importItem.addError(Messages.getString("AbstractImportHandler_deprecateItem"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final RepositoryObjectCache repObjectcache = ImportCacheHelper.getInstance().getRepObjectcache();
|
||||
|
||||
IRepositoryViewObject itemWithSameIdObj = null;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
AbstractImportHandler_cannotImportMessage=from the project {0} use a more recent version of studio so cannot import it.
|
||||
AbstractImportHandler_persistenceException=A newer version of {0} already exist.
|
||||
AbstractImportHandler_unsupportItem=Can not import the item, Please ensure the items are valid in current product.
|
||||
AbstractImportHandler_deprecateItem=Can not import the item, the item is deprecate in current product.
|
||||
AbstractImportHandler_itemLocked=The item is locked.
|
||||
AbstractImportHandler_nameUsed=This item already exists. Check the Recycle bin and empty it if needed.
|
||||
AbstractImportHandler_nameUsed.differentRepositoryType=An item with the same name already exists. Check the Recycle bin and empty it if needed.
|
||||
|
||||
@@ -85,6 +85,14 @@
|
||||
name="AccessMigrationTask"
|
||||
version="6.0.0">
|
||||
</projecttask>
|
||||
<projecttask
|
||||
beforeLogon="false"
|
||||
breaks="7.4.0"
|
||||
class="org.talend.repository.metadata.migration.RemoveDeprecateSASItemMigrationTask"
|
||||
id="org.talend.repository.metadata.migration.RemoveDeprecateSASItemMigrationTask"
|
||||
name="RemoveDeprecateSASItemMigrationTask"
|
||||
version="7.4.1">
|
||||
</projecttask>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.talend.core.repositoryContextualsActions">
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// ============================================================================
|
||||
//
|
||||
// Copyright (C) 2006-2021 Talend Inc. - www.talend.com
|
||||
//
|
||||
// This source code is available under agreement available at
|
||||
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
|
||||
//
|
||||
// You should have received a copy of the agreement
|
||||
// along with this program; if not, write to Talend SA
|
||||
// 9 rue Pages 92150 Suresnes, France
|
||||
//
|
||||
// ============================================================================
|
||||
package org.talend.repository.metadata.migration;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.talend.commons.exception.ExceptionHandler;
|
||||
import org.talend.commons.exception.PersistenceException;
|
||||
import org.talend.core.database.EDatabaseTypeName;
|
||||
import org.talend.core.model.metadata.builder.connection.Connection;
|
||||
import org.talend.core.model.metadata.builder.connection.DatabaseConnection;
|
||||
import org.talend.core.model.migration.AbstractItemMigrationTask;
|
||||
import org.talend.core.model.properties.DatabaseConnectionItem;
|
||||
import org.talend.core.model.properties.Item;
|
||||
import org.talend.core.model.repository.IRepositoryViewObject;
|
||||
import org.talend.core.repository.model.ProxyRepositoryFactory;
|
||||
|
||||
/**
|
||||
* DOC jding class global comment. Detailled comment
|
||||
*/
|
||||
public class RemoveDeprecateSASItemMigrationTask extends AbstractItemMigrationTask {
|
||||
|
||||
@Override
|
||||
public Date getOrder() {
|
||||
GregorianCalendar gc = new GregorianCalendar(2021, 4, 20, 17, 50, 30);
|
||||
return gc.getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionResult execute(Item item) {
|
||||
if (item instanceof DatabaseConnectionItem) {
|
||||
String typeName = null;
|
||||
DatabaseConnectionItem connItem = (DatabaseConnectionItem) item;
|
||||
typeName = connItem.getTypeName();
|
||||
if (StringUtils.isBlank(typeName)) {
|
||||
Connection connection = connItem.getConnection();
|
||||
if (connection instanceof DatabaseConnection) {
|
||||
typeName = ((DatabaseConnection) connection).getDatabaseType();
|
||||
}
|
||||
}
|
||||
if (StringUtils.isBlank(typeName) || item.getProperty() == null
|
||||
|| !EDatabaseTypeName.SAS.getXmlName().equals(typeName)) {
|
||||
return ExecutionResult.NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
ProxyRepositoryFactory factory = ProxyRepositoryFactory.getInstance();
|
||||
try {
|
||||
IRepositoryViewObject repositoryObject = factory.getSpecificVersion(item.getProperty().getId(),
|
||||
item.getProperty().getVersion(), true);
|
||||
// to delete all version items
|
||||
factory.deleteObjectPhysical(repositoryObject);
|
||||
} catch (PersistenceException e) {
|
||||
ExceptionHandler.process(e);
|
||||
return ExecutionResult.FAILURE;
|
||||
}
|
||||
|
||||
} else {
|
||||
return ExecutionResult.NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
return ExecutionResult.SUCCESS_NO_ALERT;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user