Tighten front database column type validation
This commit is contained in:
@@ -1,11 +1,9 @@
|
|||||||
package com.ruoyi.generator.service.front;
|
package com.ruoyi.generator.service.front;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
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 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 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(
|
private static final Pattern BIGINT_TYPE_PATTERN = Pattern.compile("^bigint(\\(20\\))?$");
|
||||||
"tinyint", "smallint", "mediumint", "int", "integer", "bigint",
|
private static final Pattern INT_TYPE_PATTERN = Pattern.compile("^int(\\(11\\))?$");
|
||||||
"float", "double", "decimal", "numeric",
|
private static final Pattern VARCHAR_TYPE_PATTERN = Pattern.compile("^varchar\\((\\d{1,5})\\)$");
|
||||||
"bit", "bool", "boolean",
|
private static final Pattern CHAR_TYPE_PATTERN = Pattern.compile("^char\\((\\d{1,3})\\)$");
|
||||||
"char", "varchar", "text", "tinytext", "mediumtext", "longtext",
|
private static final Pattern DECIMAL_TYPE_PATTERN = Pattern.compile("^decimal\\((\\d{1,2}),(\\d{1,2})\\)$");
|
||||||
"date", "time", "datetime", "timestamp", "json"));
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private FrontProjectMapper frontProjectMapper;
|
private FrontProjectMapper frontProjectMapper;
|
||||||
@@ -246,12 +243,37 @@ public class FrontProjectServiceImpl implements IFrontProjectService
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String normalizedType = columnType.trim().toLowerCase(Locale.ENGLISH)
|
String normalizedType = columnType.trim().toLowerCase(Locale.ENGLISH);
|
||||||
.replaceAll("\\s+unsigned$", "")
|
if ("datetime".equals(normalizedType) || "date".equals(normalizedType)
|
||||||
.replaceAll("\\s+zerofill$", "");
|
|| "text".equals(normalizedType) || "longtext".equals(normalizedType))
|
||||||
int bracketIndex = normalizedType.indexOf('(');
|
{
|
||||||
String baseType = bracketIndex >= 0 ? normalizedType.substring(0, bracketIndex) : normalizedType;
|
return true;
|
||||||
return ALLOWED_COLUMN_TYPES.contains(baseType);
|
}
|
||||||
|
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)
|
private String joinCreateTableSql(List<DatabaseTableDesign> tables)
|
||||||
|
|||||||
@@ -112,6 +112,44 @@ public class FrontProjectServiceImplTest
|
|||||||
verify(frontProjectTableMapper, never()).deleteTablesByProjectId(any(Long.class));
|
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
|
@Test
|
||||||
public void saveDatabasePersistsValidDraft()
|
public void saveDatabasePersistsValidDraft()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user