feat(saved): saved, shared, starred, scheduled and widget analyses, export, SQL handoff
Extension 1.4.0: saved analyses of every kind re-run as the viewer (fields they cannot analyze are dropped), owner-or-shared READ through core record locks with owner-only writes (and a database CHECK so a private row can never lose its read owner), personal stars, schedules that run as the owner and mail only recipients who could run the analysis themselves, CSV/XLSX export, the SQL Workbench handoff, an analysis dashboard widget, and an Analyses home built from standard widgets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
43c7571864
commit
d2c9871d98
42 files changed
+3786
-296
No files matched your search
@@ -69,7 +69,7 @@ class DataAnalysisMetadataTest
|
||||
assertThat(instance.getTables()).containsOnlyKeys(DataAnalysisTables.ALL);
|
||||
assertThat(instance.getPossibleValueSources().keySet().stream().filter(name -> name.startsWith("data_analysis_"))).hasSize(16);
|
||||
assertThat(instance.getJoins()).hasSize(3);
|
||||
assertThat(instance.getWidgets()).hasSize(4).containsKey(DataAnalysisHome.HOME_WIDGET);
|
||||
assertThat(instance.getWidgets()).hasSize(8).containsKey(DataAnalysisHome.HOME_WIDGET);
|
||||
assertThat(instance.getApp("dataAnalysis").getSections().getFirst().getProcesses()).isNullOrEmpty();
|
||||
assertThat(instance.getApp("dataAnalysis").getLabel()).isEqualTo("Analyses");
|
||||
assertThat(instance.getApp("dataAnalysis").getSections().getFirst().getTables()).containsExactlyElementsOf(DataAnalysisTables.NAV_TABLES);
|
||||
@@ -90,7 +90,7 @@ class DataAnalysisMetadataTest
|
||||
assertThat(lock.getSecurityKeyType()).isEqualTo("data_analysis_user");
|
||||
assertThat(lock.getFieldName()).isEqualTo(name.equals(DataAnalysisTables.SAVED) ? "owner_user_id" : "user_id");
|
||||
assertThat(lock.getNullValueBehavior()).isEqualTo(RecordSecurityLock.NullValueBehavior.DENY);
|
||||
assertThat(lock.getLockScope()).isEqualTo(RecordSecurityLock.LockScope.READ_AND_WRITE);
|
||||
assertThat(lock.getLockScope()).isEqualTo(name.equals(DataAnalysisTables.SAVED) ? RecordSecurityLock.LockScope.WRITE : RecordSecurityLock.LockScope.READ_AND_WRITE);
|
||||
}
|
||||
assertThat(instance.getSecurityKeyType("data_analysis_user").getAllAccessKeyName()).isEqualTo("data_analysis.admin");
|
||||
assertThat(PermissionsHelper.getAllAvailablePermissionNames(instance)).contains("data_analysis.settings.read", "data_analysis.settings.edit", "data_analysis.run.read", "data_analysis.run.delete", "data_analysis.saved.read", "data_analysis.saved.insert",
|
||||
@@ -205,7 +205,8 @@ class DataAnalysisMetadataTest
|
||||
assertThat(ddl).contains("id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY", "create_date TIMESTAMP WITHOUT TIME ZONE",
|
||||
"modify_date TIMESTAMP WITHOUT TIME ZONE", "rows_scanned BIGINT", "result_json TEXT", "shared BOOLEAN", "day INTEGER",
|
||||
"owner_user_id VARCHAR(250) NOT NULL", "date_field VARCHAR(250) NOT NULL", "last_value NUMERIC", "last_message TEXT", "CREATE UNIQUE INDEX IF NOT EXISTS uq_data_analysis_table_config_1 ON data_analysis_table_config (table_name)",
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS uq_data_analysis_saved_star_1 ON data_analysis_saved_star (saved_id, user_id)");
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS uq_data_analysis_saved_star_1 ON data_analysis_saved_star (saved_id, user_id)",
|
||||
"CHECK (shared = TRUE OR read_owner_user_id IS NOT NULL)");
|
||||
assertThat(ddl).endsWith(";\n");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user