Refactor scope loading to dynamically retrieve first-level subdirectories
- Introduced a new function to get first-level subdirectories in the scopes directory, enhancing the flexibility of scope definition loading. - Updated the loadScopeDefinitions method to utilize this new function, replacing hardcoded subdirectory names with a dynamic approach. - Improved the description of the invite verification scope in the user scope initialization for clarity.
This commit is contained in:
parent
e1405a5fa2
commit
f6aead62bb
3 changed files with 58 additions and 28 deletions
|
|
@ -223,22 +223,53 @@ func (m *ScopeManager) expandAlias(alias string, visited map[string]bool) ([]str
|
||||||
return expanded, nil
|
return expanded, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getFirstLevelSubdirs returns all first-level subdirectories in a given directory
|
||||||
|
func getFirstLevelSubdirs(baseDir string) ([]string, error) {
|
||||||
|
var subdirs []string
|
||||||
|
|
||||||
|
err := application.App.Walk(baseDir, func(root, filename string, isdir bool) error {
|
||||||
|
// Only process directories
|
||||||
|
if !isdir {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the root directory itself
|
||||||
|
if filename == baseDir {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get relative path from baseDir
|
||||||
|
relPath := strings.TrimPrefix(filename, baseDir)
|
||||||
|
relPath = strings.TrimPrefix(relPath, string(filepath.Separator))
|
||||||
|
|
||||||
|
// Only include first-level directories (no nested paths)
|
||||||
|
if !strings.Contains(relPath, string(filepath.Separator)) && relPath != "" {
|
||||||
|
subdirs = append(subdirs, relPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, "")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return subdirs, nil
|
||||||
|
}
|
||||||
|
|
||||||
// loadScopeDefinitions loads scope definitions from subdirectories
|
// loadScopeDefinitions loads scope definitions from subdirectories
|
||||||
func (m *ScopeManager) loadScopeDefinitions() error {
|
func (m *ScopeManager) loadScopeDefinitions() error {
|
||||||
scopesDir := filepath.Join("openapi", "scopes")
|
scopesDir := filepath.Join("openapi", "scopes")
|
||||||
|
|
||||||
// Subdirectories to scan
|
// Get all subdirectories in the scopes directory
|
||||||
subDirs := []string{"kb", "job", "file", "user"}
|
subDirs, err := getFirstLevelSubdirs(scopesDir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to scan scopes directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load scope definitions from each subdirectory
|
||||||
for _, subDir := range subDirs {
|
for _, subDir := range subDirs {
|
||||||
dirPath := filepath.Join(scopesDir, subDir)
|
dirPath := filepath.Join(scopesDir, subDir)
|
||||||
exists, err := application.App.Exists(dirPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Walk through all .yml files in the directory
|
// Walk through all .yml files in the directory
|
||||||
err = application.App.Walk(dirPath, func(root, filename string, isdir bool) error {
|
err = application.App.Walk(dirPath, func(root, filename string, isdir bool) error {
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,11 @@ func init() {
|
||||||
"GET /file/:uploaderID/:fileID/content",
|
"GET /file/:uploaderID/:fileID/content",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Invite verification scope - allows users to accept team invitations
|
// Invite verification scope - allows users to view invitation details before accepting
|
||||||
&acl.ScopeDefinition{
|
&acl.ScopeDefinition{
|
||||||
Name: ScopeInviteVerification,
|
Name: ScopeInviteVerification,
|
||||||
Description: "Invite verification - temporary access for accepting team invitations",
|
Description: "Invite verification - temporary access for viewing invitation details",
|
||||||
Endpoints: []string{
|
Endpoints: []string{
|
||||||
"POST /user/teams/invitations/:invitation_id/accept",
|
|
||||||
"GET /user/teams/invitations/:invitation_id",
|
"GET /user/teams/invitations/:invitation_id",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ func TestSeedImportDuplicateUpdateAfterClear(t *testing.T) {
|
||||||
|
|
||||||
// Step 1: Clear and import data (initial import)
|
// Step 1: Clear and import data (initial import)
|
||||||
_, _ = mod.DestroyWhere(model.QueryParam{})
|
_, _ = mod.DestroyWhere(model.QueryParam{})
|
||||||
|
|
||||||
p1 := process.New("seeds.import", "roles.csv", "__yao.role", map[string]interface{}{
|
p1 := process.New("seeds.import", "roles.csv", "__yao.role", map[string]interface{}{
|
||||||
"chunk_size": 100,
|
"chunk_size": 100,
|
||||||
"duplicate": "update",
|
"duplicate": "update",
|
||||||
|
|
@ -39,7 +39,7 @@ func TestSeedImportDuplicateUpdateAfterClear(t *testing.T) {
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Greater(t, resultMap1.Success, 0, "First import should succeed")
|
assert.Greater(t, resultMap1.Success, 0, "First import should succeed")
|
||||||
assert.Equal(t, 0, resultMap1.Failure, "First import should have no failures")
|
assert.Equal(t, 0, resultMap1.Failure, "First import should have no failures")
|
||||||
|
|
||||||
firstCount := resultMap1.Success
|
firstCount := resultMap1.Success
|
||||||
|
|
||||||
// Step 2: Clear all data (simulate Reset scenario)
|
// Step 2: Clear all data (simulate Reset scenario)
|
||||||
|
|
@ -63,15 +63,15 @@ func TestSeedImportDuplicateUpdateAfterClear(t *testing.T) {
|
||||||
result2 := p2.Run()
|
result2 := p2.Run()
|
||||||
resultMap2, ok := result2.(*ImportResult)
|
resultMap2, ok := result2.(*ImportResult)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
t.Logf("Second import result: Total=%d, Success=%d, Failure=%d, Ignore=%d",
|
t.Logf("Second import result: Total=%d, Success=%d, Failure=%d, Ignore=%d",
|
||||||
resultMap2.Total, resultMap2.Success, resultMap2.Failure, resultMap2.Ignore)
|
resultMap2.Total, resultMap2.Success, resultMap2.Failure, resultMap2.Ignore)
|
||||||
|
|
||||||
// Print errors if any
|
// Print errors if any
|
||||||
if len(resultMap2.Errors) > 0 {
|
if len(resultMap2.Errors) > 0 {
|
||||||
t.Logf("Import errors: %+v", resultMap2.Errors)
|
t.Logf("Import errors: %+v", resultMap2.Errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical assertions: data should be imported successfully
|
// Critical assertions: data should be imported successfully
|
||||||
assert.Greater(t, resultMap2.Success, 0, "Second import should succeed (CREATE new records)")
|
assert.Greater(t, resultMap2.Success, 0, "Second import should succeed (CREATE new records)")
|
||||||
assert.Equal(t, 0, resultMap2.Failure, "Second import should have no failures")
|
assert.Equal(t, 0, resultMap2.Failure, "Second import should have no failures")
|
||||||
|
|
@ -101,7 +101,7 @@ func TestSeedImportDuplicateUpdateMixedScenario(t *testing.T) {
|
||||||
|
|
||||||
// Step 1: Clear and initial import
|
// Step 1: Clear and initial import
|
||||||
_, _ = mod.DestroyWhere(model.QueryParam{})
|
_, _ = mod.DestroyWhere(model.QueryParam{})
|
||||||
|
|
||||||
p1 := process.New("seeds.import", "roles.csv", "__yao.role", map[string]interface{}{
|
p1 := process.New("seeds.import", "roles.csv", "__yao.role", map[string]interface{}{
|
||||||
"duplicate": "update",
|
"duplicate": "update",
|
||||||
"mode": "each",
|
"mode": "each",
|
||||||
|
|
@ -117,7 +117,7 @@ func TestSeedImportDuplicateUpdateMixedScenario(t *testing.T) {
|
||||||
allRoles, _ := mod.Get(model.QueryParam{
|
allRoles, _ := mod.Get(model.QueryParam{
|
||||||
Select: []interface{}{"id", "role_id"},
|
Select: []interface{}{"id", "role_id"},
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(allRoles) > 0 {
|
if len(allRoles) > 0 {
|
||||||
// Delete the first role
|
// Delete the first role
|
||||||
roleID := allRoles[0].Get("id")
|
roleID := allRoles[0].Get("id")
|
||||||
|
|
@ -140,29 +140,29 @@ func TestSeedImportDuplicateUpdateMixedScenario(t *testing.T) {
|
||||||
})
|
})
|
||||||
result2 := p2.Run()
|
result2 := p2.Run()
|
||||||
resultMap2 := result2.(*ImportResult)
|
resultMap2 := result2.(*ImportResult)
|
||||||
|
|
||||||
t.Logf("Second import result: Total=%d, Success=%d, Failure=%d, Ignore=%d",
|
t.Logf("Second import result: Total=%d, Success=%d, Failure=%d, Ignore=%d",
|
||||||
resultMap2.Total, resultMap2.Success, resultMap2.Failure, resultMap2.Ignore)
|
resultMap2.Total, resultMap2.Success, resultMap2.Failure, resultMap2.Ignore)
|
||||||
|
|
||||||
// Print errors if any
|
// Print errors if any
|
||||||
if len(resultMap2.Errors) > 0 {
|
if len(resultMap2.Errors) > 0 {
|
||||||
for i, err := range resultMap2.Errors {
|
for i, err := range resultMap2.Errors {
|
||||||
t.Logf("Error %d: Row=%d, Message=%s", i+1, err.Row, err.Message)
|
t.Logf("Error %d: Row=%d, Message=%s", i+1, err.Row, err.Message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should import all records
|
// Should import all records
|
||||||
assert.Greater(t, resultMap2.Success, 0, "Should import successfully")
|
assert.Greater(t, resultMap2.Success, 0, "Should import successfully")
|
||||||
|
|
||||||
// Note: Some failures may occur if CSV has duplicate IDs or validation issues
|
// Note: Some failures may occur if CSV has duplicate IDs or validation issues
|
||||||
// The important thing is that deleted record should be recreated
|
// The important thing is that deleted record should be recreated
|
||||||
|
|
||||||
// Verify count increased (deleted record was recreated)
|
// Verify count increased (deleted record was recreated)
|
||||||
finalRoles, err := mod.Get(model.QueryParam{})
|
finalRoles, err := mod.Get(model.QueryParam{})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
t.Logf("Final roles count: %d (expected %d)", len(finalRoles), initialCount)
|
t.Logf("Final roles count: %d (expected %d)", len(finalRoles), initialCount)
|
||||||
|
|
||||||
// At minimum, should have more records than before re-import
|
// At minimum, should have more records than before re-import
|
||||||
assert.GreaterOrEqual(t, len(finalRoles), len(remainingRoles),
|
assert.GreaterOrEqual(t, len(finalRoles), len(remainingRoles),
|
||||||
"Should have at least as many records as before (deleted record recreated)")
|
"Should have at least as many records as before (deleted record recreated)")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue