Tighten front database column type validation
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
package com.ruoyi.generator.service.front;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -31,12 +29,11 @@ public class FrontProjectServiceImpl implements IFrontProjectService
|
||||
{
|
||||
private static final Pattern SAFE_PROJECT_FILE_NAME = Pattern.compile("^[a-z][a-z0-9-]*[a-z0-9]$|^[a-z]$");
|
||||
private static final Pattern DB_NAME_PATTERN = Pattern.compile("^[a-z][a-z0-9_]{1,63}$");
|
||||
private static final Set<String> ALLOWED_COLUMN_TYPES = new HashSet<String>(Arrays.asList(
|
||||
"tinyint", "smallint", "mediumint", "int", "integer", "bigint",
|
||||
"float", "double", "decimal", "numeric",
|
||||
"bit", "bool", "boolean",
|
||||
"char", "varchar", "text", "tinytext", "mediumtext", "longtext",
|
||||
"date", "time", "datetime", "timestamp", "json"));
|
||||
private static final Pattern BIGINT_TYPE_PATTERN = Pattern.compile("^bigint(\\(20\\))?$");
|
||||
private static final Pattern INT_TYPE_PATTERN = Pattern.compile("^int(\\(11\\))?$");
|
||||
private static final Pattern VARCHAR_TYPE_PATTERN = Pattern.compile("^varchar\\((\\d{1,5})\\)$");
|
||||
private static final Pattern CHAR_TYPE_PATTERN = Pattern.compile("^char\\((\\d{1,3})\\)$");
|
||||
private static final Pattern DECIMAL_TYPE_PATTERN = Pattern.compile("^decimal\\((\\d{1,2}),(\\d{1,2})\\)$");
|
||||
|
||||
@Autowired
|
||||
private FrontProjectMapper frontProjectMapper;
|
||||
@@ -246,12 +243,37 @@ public class FrontProjectServiceImpl implements IFrontProjectService
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String normalizedType = columnType.trim().toLowerCase(Locale.ENGLISH)
|
||||
.replaceAll("\\s+unsigned$", "")
|
||||
.replaceAll("\\s+zerofill$", "");
|
||||
int bracketIndex = normalizedType.indexOf('(');
|
||||
String baseType = bracketIndex >= 0 ? normalizedType.substring(0, bracketIndex) : normalizedType;
|
||||
return ALLOWED_COLUMN_TYPES.contains(baseType);
|
||||
String normalizedType = columnType.trim().toLowerCase(Locale.ENGLISH);
|
||||
if ("datetime".equals(normalizedType) || "date".equals(normalizedType)
|
||||
|| "text".equals(normalizedType) || "longtext".equals(normalizedType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (BIGINT_TYPE_PATTERN.matcher(normalizedType).matches()
|
||||
|| INT_TYPE_PATTERN.matcher(normalizedType).matches())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Matcher varcharMatcher = VARCHAR_TYPE_PATTERN.matcher(normalizedType);
|
||||
if (varcharMatcher.matches())
|
||||
{
|
||||
int length = Integer.parseInt(varcharMatcher.group(1));
|
||||
return length >= 1 && length <= 65535;
|
||||
}
|
||||
Matcher charMatcher = CHAR_TYPE_PATTERN.matcher(normalizedType);
|
||||
if (charMatcher.matches())
|
||||
{
|
||||
int length = Integer.parseInt(charMatcher.group(1));
|
||||
return length >= 1 && length <= 255;
|
||||
}
|
||||
Matcher decimalMatcher = DECIMAL_TYPE_PATTERN.matcher(normalizedType);
|
||||
if (decimalMatcher.matches())
|
||||
{
|
||||
int precision = Integer.parseInt(decimalMatcher.group(1));
|
||||
int scale = Integer.parseInt(decimalMatcher.group(2));
|
||||
return precision >= 1 && precision <= 65 && scale >= 0 && scale <= 30 && scale <= precision;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String joinCreateTableSql(List<DatabaseTableDesign> tables)
|
||||
|
||||
@@ -112,6 +112,44 @@ public class FrontProjectServiceImplTest
|
||||
verify(frontProjectTableMapper, never()).deleteTablesByProjectId(any(Long.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveDatabaseRejectsColumnTypeWithSuffix()
|
||||
{
|
||||
when(frontProjectMapper.selectFrontProjectByUserAndId(7L, 10L)).thenReturn(project());
|
||||
|
||||
ServiceException exception = expectServiceException(new ThrowingRunnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
service.saveDatabase(7L, 10L, database(table("sys_user", column("id", "varchar(64) not null", "1"))));
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals("字段类型不在允许范围内", exception.getMessage());
|
||||
verify(frontProjectColumnMapper, never()).deleteColumnsByProjectId(any(Long.class));
|
||||
verify(frontProjectTableMapper, never()).deleteTablesByProjectId(any(Long.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveDatabaseRejectsJsonColumnType()
|
||||
{
|
||||
when(frontProjectMapper.selectFrontProjectByUserAndId(7L, 10L)).thenReturn(project());
|
||||
|
||||
ServiceException exception = expectServiceException(new ThrowingRunnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
service.saveDatabase(7L, 10L, database(table("sys_user", column("id", "json", "1"))));
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals("字段类型不在允许范围内", exception.getMessage());
|
||||
verify(frontProjectColumnMapper, never()).deleteColumnsByProjectId(any(Long.class));
|
||||
verify(frontProjectTableMapper, never()).deleteTablesByProjectId(any(Long.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveDatabasePersistsValidDraft()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user