MCPcopy Index your code
hub / github.com/bytebase/bytebase / authorizeWriteTargets

Method authorizeWriteTargets

backend/api/v1/sql_service.go:1787–1883  ·  view source on GitHub ↗

authorizeWriteTargets evaluates perm for each resolved DML/DDL write target and returns the resources that were denied (empty = all authorized). A target whose database is already JIT-granted is skipped. databaseLevelOnly selects the precision of the check. For a single statement it is false and ea

(
	ctx context.Context,
	user *store.UserMessage,
	instance *store.InstanceMessage,
	database *store.DatabaseMessage,
	perm permission.Permission,
	targets []writeTargetResource,
	grantedTargets map[string]struct{},
	databaseLevelOnly bool,
	iamPolicies ...*storepb.IamPolicy,
)

Source from the content-addressed store, hash-verified

1785// always present because hasDatabaseAccessRights keeps the environment clause for SQLDml/SQLDdl,
1786// so omitting it would reintroduce a "no such attribute" error. SUP-222 / BYT-9698.
1787func (s *SQLService) authorizeWriteTargets(
1788 ctx context.Context,
1789 user *store.UserMessage,
1790 instance *store.InstanceMessage,
1791 database *store.DatabaseMessage,
1792 perm permission.Permission,
1793 targets []writeTargetResource,
1794 grantedTargets map[string]struct{},
1795 databaseLevelOnly bool,
1796 iamPolicies ...*storepb.IamPolicy,
1797) ([]string, error) {
1798 // One timestamp per request so every target evaluates request.time consistently.
1799 requestTime := time.Now()
1800
1801 // environment_id of the request database, reused without a lookup for same-database targets.
1802 envByDatabase := map[string]string{database.DatabaseName: ""}
1803 if database.EffectiveEnvironmentID != nil {
1804 envByDatabase[database.DatabaseName] = *database.EffectiveEnvironmentID
1805 }
1806 checkedDatabase := map[string]bool{} // databaseLevelOnly: authorize each target database once
1807
1808 var deniedResources []string
1809 for _, t := range targets {
1810 databaseFullName := common.FormatDatabase(instance.ResourceID, t.database)
1811 if _, granted := grantedTargets[databaseFullName]; granted {
1812 continue
1813 }
1814 // A target with no table name is a database-only target: DDL on a non-table object
1815 // (view/procedure/function/trigger/…) whose only auth-relevant identity is its database.
1816 // Authorize it at the database level — like a multi-statement batch — so a qualified
1817 // cross-database object DDL is gated by its own database, not the request database, with
1818 // no spurious table-name match. SUP-222 / BYT-9698.
1819 useDatabaseLevel := databaseLevelOnly || t.table == ""
1820 if useDatabaseLevel {
1821 if checkedDatabase[t.database] {
1822 continue
1823 }
1824 checkedDatabase[t.database] = true
1825 }
1826
1827 // A denial names the bare database for a database-level check, else the schema/table target.
1828 deniedResource := databaseFullName
1829 if !useDatabaseLevel {
1830 deniedResource = formatWriteTargetResource(databaseFullName, t.schema, t.table)
1831 }
1832
1833 env, known := envByDatabase[t.database]
1834 if !known {
1835 targetName := t.database
1836 targetDB, err := s.store.GetDatabase(ctx, &store.FindDatabaseMessage{
1837 Workspace: common.GetWorkspaceIDFromContext(ctx),
1838 InstanceID: &instance.ResourceID,
1839 DatabaseName: &targetName,
1840 })
1841 if err != nil {
1842 return nil, connect.NewError(connect.CodeInternal, errors.Errorf("failed to resolve target database %q: %v", t.database, err))
1843 }
1844 if targetDB == nil {

Callers 1

Calls 6

FormatDatabaseFunction · 0.92
ErrorfMethod · 0.80
GetDatabaseMethod · 0.65

Tested by

no test coverage detected