2023-07-21 09:23:01 -05:00
package migrator
import (
"context"
"time"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log"
2023-07-28 05:37:24 -05:00
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
2023-07-21 09:23:01 -05:00
"github.com/grafana/grafana/pkg/services/sqlstore"
2023-07-28 05:37:24 -05:00
"github.com/grafana/grafana/pkg/services/sqlstore/session"
)
var (
batchSize = 1000
2023-07-21 09:23:01 -05:00
)
func MigrateScopeSplit ( db db . DB , log log . Logger ) error {
t := time . Now ( )
2023-07-28 05:37:24 -05:00
ctx := context . Background ( )
cnt := 0
2023-07-21 09:23:01 -05:00
2023-07-28 05:37:24 -05:00
// Search for the permissions to update
var permissions [ ] ac . Permission
if errFind := db . WithTransactionalDbSession ( ctx , func ( sess * sqlstore . DBSession ) error {
return sess . SQL ( "SELECT * FROM permission WHERE NOT scope = '' AND identifier = ''" ) . Find ( & permissions )
} ) ; errFind != nil {
2023-09-04 11:49:47 -05:00
log . Error ( "Could not search for permissions to update" , "migration" , "scopeSplit" , "error" , errFind )
2023-07-28 05:37:24 -05:00
return errFind
}
if len ( permissions ) == 0 {
2023-09-04 11:49:47 -05:00
log . Debug ( "No permission require a scope split" , "migration" , "scopeSplit" )
2023-07-28 05:37:24 -05:00
return nil
}
errBatchUpdate := batch ( len ( permissions ) , batchSize , func ( start , end int ) error {
n := end - start
// IDs to remove
delQuery := "DELETE FROM permission WHERE id IN ("
2023-08-30 10:46:47 -05:00
delArgs := make ( [ ] any , 0 , n )
2023-07-28 05:37:24 -05:00
// Query to insert the updated permissions
insertQuery := "INSERT INTO permission (id, role_id, action, scope, kind, attribute, identifier, created, updated) VALUES "
2023-08-30 10:46:47 -05:00
insertArgs := make ( [ ] any , 0 , 9 * n )
2023-07-28 05:37:24 -05:00
// Prepare batch of updated permissions
for i := start ; i < end ; i ++ {
kind , attribute , identifier := permissions [ i ] . SplitScope ( )
2023-07-21 09:23:01 -05:00
2023-07-28 05:37:24 -05:00
delQuery += "?,"
delArgs = append ( delArgs , permissions [ i ] . ID )
2023-07-21 09:23:01 -05:00
2023-07-28 05:37:24 -05:00
insertQuery += "(?, ?, ?, ?, ?, ?, ?, ?, ?),"
insertArgs = append ( insertArgs , permissions [ i ] . ID , permissions [ i ] . RoleID ,
permissions [ i ] . Action , permissions [ i ] . Scope ,
kind , attribute , identifier ,
permissions [ i ] . Created , t ,
)
}
// Remove trailing ','
insertQuery = insertQuery [ : len ( insertQuery ) - 1 ]
// Remove trailing ',' and close brackets
delQuery = delQuery [ : len ( delQuery ) - 1 ] + ")"
2023-07-21 09:23:01 -05:00
2023-07-28 05:37:24 -05:00
// Batch update the permissions
if errBatchUpdate := db . GetSqlxSession ( ) . WithTransaction ( ctx , func ( tx * session . SessionTx ) error {
if _ , errDel := tx . Exec ( ctx , delQuery , delArgs ... ) ; errDel != nil {
2023-09-04 11:49:47 -05:00
log . Error ( "Error deleting permissions" , "migration" , "scopeSplit" , "error" , errDel )
2023-07-28 05:37:24 -05:00
return errDel
}
if _ , errInsert := tx . Exec ( ctx , insertQuery , insertArgs ... ) ; errInsert != nil {
2023-09-04 11:49:47 -05:00
log . Error ( "Error saving permissions" , "migration" , "scopeSplit" , "error" , errInsert )
2023-07-28 05:37:24 -05:00
return errInsert
2023-07-21 09:23:01 -05:00
}
2023-07-28 05:37:24 -05:00
return nil
} ) ; errBatchUpdate != nil {
2023-09-04 11:49:47 -05:00
log . Error ( "Error updating permission batch" , "migration" , "scopeSplit" , "start" , start , "end" , end )
2023-07-28 05:37:24 -05:00
return errBatchUpdate
2023-07-21 09:23:01 -05:00
}
2023-07-28 05:37:24 -05:00
cnt += end - start
2023-07-21 09:23:01 -05:00
return nil
} )
2023-07-28 05:37:24 -05:00
if errBatchUpdate != nil {
2023-09-04 11:49:47 -05:00
log . Error ( "Could not migrate permissions" , "migration" , "scopeSplit" , "total" , len ( permissions ) , "succeeded" , cnt , "left" , len ( permissions ) - cnt , "error" , errBatchUpdate )
2023-07-28 05:37:24 -05:00
return errBatchUpdate
}
2023-09-04 11:49:47 -05:00
log . Debug ( "Migrated permissions" , "migration" , "scopeSplit" , "total" , len ( permissions ) , "succeeded" , cnt , "in" , time . Since ( t ) )
2023-07-28 05:37:24 -05:00
return nil
}
func batch ( count , batchSize int , eachFn func ( start , end int ) error ) error {
for i := 0 ; i < count ; {
end := i + batchSize
if end > count {
end = count
}
if err := eachFn ( i , end ) ; err != nil {
return err
}
2023-07-21 09:23:01 -05:00
2023-07-28 05:37:24 -05:00
i = end
}
2023-07-21 09:23:01 -05:00
2023-07-28 05:37:24 -05:00
return nil
2023-07-21 09:23:01 -05:00
}